mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-12 20:57:59 +02:00
fix: resolve nested PowerShell command tokens
This commit is contained in:
@@ -944,11 +944,11 @@ function parseStatements(input) {
|
||||
wordHasQuotedContent && !wordHasUnquotedContent ? wordQuoteKind : null
|
||||
);
|
||||
segmentTokenSources.push(wordSource);
|
||||
segmentInlineValueQuoteKinds.push(
|
||||
segmentInlineValueQuoteKinds = [...segmentInlineValueQuoteKinds,
|
||||
wordInlineValueQuoteClosed && wordInlineValueQuoteKind !== 'mixed'
|
||||
? wordInlineValueQuoteKind
|
||||
: null
|
||||
);
|
||||
];
|
||||
}
|
||||
word = '';
|
||||
wordSource = '';
|
||||
@@ -1260,7 +1260,6 @@ function scanNestedPowerShell(tokens, depth, findings, analysis, scanState, upst
|
||||
: tokens.slice(index + 1).join(' ');
|
||||
const pipelinePayload = payload === '-' ? staticPipelineInput(upstreamTokens) : null;
|
||||
const payloadIndex = index + 1;
|
||||
const hasOnePayloadToken = !inlinePayload && tokens.length === payloadIndex + 1;
|
||||
const inlineQuoteKind = tokens.inlineValueQuoteKinds?.[index];
|
||||
if (inlinePayload && inlineQuoteKind !== "'") {
|
||||
const inlineSource = parameterValue(tokens.tokenSources?.[index] || token);
|
||||
@@ -1273,14 +1272,14 @@ function scanNestedPowerShell(tokens, depth, findings, analysis, scanState, upst
|
||||
payload = [expanded, ...tokens.slice(index + 1)].join(' ');
|
||||
} else if (inlinePayload) {
|
||||
payload = [inlinePayload, ...tokens.slice(index + 1)].join(' ');
|
||||
} else if (hasOnePayloadToken && tokens.quoteKinds?.[payloadIndex] !== "'") {
|
||||
} else if (tokens[payloadIndex] && tokens.quoteKinds?.[payloadIndex] !== "'") {
|
||||
const expanded = expandStaticDoubleQuotedString(
|
||||
tokens.tokenSources?.[payloadIndex] ?? payload,
|
||||
tokens.tokenSources?.[payloadIndex] ?? tokens[payloadIndex],
|
||||
scanState,
|
||||
findings
|
||||
);
|
||||
if (expanded === null) return;
|
||||
payload = expanded;
|
||||
payload = [expanded, ...tokens.slice(payloadIndex + 1)].join(' ');
|
||||
} else {
|
||||
const payloadReference = tokens.quoteKinds?.[payloadIndex] === "'"
|
||||
? null
|
||||
|
||||
@@ -2976,7 +2976,9 @@ function runTests() {
|
||||
"$payload='Remove-Item -Force C:/tmp/demo'; pwsh -Command $payload",
|
||||
"$payload='Remove-Item -Force C:/tmp/demo'; pwsh -Command \"$payload\"",
|
||||
"$payload='Remove-Item -Force C:/tmp/demo'; pwsh -Command \"Write-Output ready; $payload\"",
|
||||
"$payload='Remove-Item'; pwsh -Command $payload -Force C:/tmp/demo",
|
||||
'pwsh -Command "Write-Output ready; $runtimePayload"',
|
||||
'pwsh -Command $runtimePayload -Force C:/tmp/demo',
|
||||
'Write-Output "$(Remove-Item -Force C:/tmp/demo)"',
|
||||
'& { Remove-Item -Force C:/tmp/demo }',
|
||||
'if ($true) { Remove-Item -Force C:/tmp/demo }',
|
||||
|
||||
@@ -251,6 +251,10 @@ async function runTests() {
|
||||
command: 'pwsh -Command "Write-Output ready; $runtimePayload"',
|
||||
expectedRules: ['powershell.dynamic-execution'],
|
||||
},
|
||||
{
|
||||
command: 'pwsh -Command $runtimePayload -Force C:/private/runtime-command-sentinel',
|
||||
expectedRules: ['powershell.dynamic-execution'],
|
||||
},
|
||||
{
|
||||
command: `pwsh -EncodedCommand ${encodedPayload}`,
|
||||
expectedRules: ['powershell.remove-item.wildcard'],
|
||||
@@ -411,7 +415,7 @@ async function runTests() {
|
||||
'Should not store raw command text'
|
||||
);
|
||||
assert.ok(
|
||||
!JSON.stringify(securityEvent).includes(command),
|
||||
!JSON.stringify(securityEvent).includes(JSON.stringify(command).slice(1, -1)),
|
||||
'Serialized governance evidence should not leak the raw command'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -470,6 +470,7 @@ test('classifies static execution primitives', () => {
|
||||
"$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command \"Write-Output ready; $payload\"",
|
||||
"$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command \"Write-Output ready; $($payload)\"",
|
||||
"$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command:$payload",
|
||||
"$payload = 'Remove-Item'; pwsh -Command $payload -Force C:/tmp/demo",
|
||||
"$payload = \"Remove-Item `\n-Force C:/tmp/demo\"; pwsh -Command $payload",
|
||||
]) {
|
||||
expectRules(command, [RULES.REMOVE_FORCE]);
|
||||
@@ -482,6 +483,9 @@ test('classifies static execution primitives', () => {
|
||||
expectRules('pwsh -Command "Write-Output ready; $($runtimeValue)"', [
|
||||
RULES.DYNAMIC_EXECUTION,
|
||||
]);
|
||||
expectRules('pwsh -Command $runtimeValue -Force C:/tmp/demo', [
|
||||
RULES.DYNAMIC_EXECUTION,
|
||||
]);
|
||||
expectSafe("$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command '$payload'");
|
||||
expectSafe("$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command \"Write-Output `$payload\"");
|
||||
expectSafe("$payload = 'Remove-Item -Force C:/tmp/demo'; pwsh -Command:`$payload");
|
||||
|
||||
Reference in New Issue
Block a user