diff --git a/inventory/inventory-graph.json b/inventory/inventory-graph.json index 730ef21ef..4ac1d3f17 100644 --- a/inventory/inventory-graph.json +++ b/inventory/inventory-graph.json @@ -5,15 +5,15 @@ "provenance": { "base": "05c800f40d1ad53b42a78609d2667ef4f726808b", "planningHead": "0a91273e61dbbd47eb0af4c02844409251e08398", - "head": "06b4a48bd9eb0d2857c863d3c0c002166f9cf129", - "sourceSha256": "2fbb6b44c6c9ee6bf73e9df413ffb754a9dfd26a473443daec0e4acfbcb6ff5a", + "head": "403a40ca4cd080ae6fe1bcd7cf04f1e1a17e4d73", + "sourceSha256": "0d6eea19f36011c47bd0dadcebba72d306cfd21789c871f79aeb8125de950751", "generatedAt": null, "generator": "scripts/generate-inventory-graph.mjs" }, "base": "05c800f40d1ad53b42a78609d2667ef4f726808b", "planningHead": "0a91273e61dbbd47eb0af4c02844409251e08398", - "head": "06b4a48bd9eb0d2857c863d3c0c002166f9cf129", - "sourceSha256": "2fbb6b44c6c9ee6bf73e9df413ffb754a9dfd26a473443daec0e4acfbcb6ff5a", + "head": "403a40ca4cd080ae6fe1bcd7cf04f1e1a17e4d73", + "sourceSha256": "0d6eea19f36011c47bd0dadcebba72d306cfd21789c871f79aeb8125de950751", "counts": { "public": { "skills": 35, @@ -76776,5 +76776,5 @@ } }, "inventorySha256": "f5ea9ebf29ba491f17b39431660e07f71eb3d78399d481c1c2b00fc34cf2ab50", - "manifestSha256": "f522f3644d5fde9ba2e04c1ba664bc826583bf648b6fc73c00f893f5e1314715" + "manifestSha256": "8e308f82d0de9d9051f498a6c049e856e000da8df3919cf3b050bcb4b1db7409" } diff --git a/src/hooks/__tests__/pre-tool-use-template-source-ext.test.ts b/src/hooks/__tests__/pre-tool-use-template-source-ext.test.ts index b14f5b289..a2153cd66 100644 --- a/src/hooks/__tests__/pre-tool-use-template-source-ext.test.ts +++ b/src/hooks/__tests__/pre-tool-use-template-source-ext.test.ts @@ -478,6 +478,8 @@ describe('pre-tool-use template source extension detection', () => { ['bash -c plus-option still executes the command string', "bash -c +x 'rm src/app.ts'", true], ['unexpanded dollar-paren heredoc delimiter still terminates', "cat <<$(printf EOF) > build.log\ndata\n$(printf EOF)\nrm src/app.ts", true], ['nested parameter expansion in dollar-paren delimiter still terminates', "cat <<$(echo ${x-)}) > build.log\ndata\n$(echo ${x-)})\nrm src/app.ts", true], + ['literal brace in parameter default does not swallow delimiter', "cat <<$(echo ${x:-{}) > build.log\ndata\n$(echo ${x:-{})\nrm src/app.ts", true], + ['bash -c plus-i still executes the command string', "bash -c +i 'rm src/app.ts'", true], ['explicit stdin shell heredoc source write', "bash -s <<'EOF'\necho hacked > src/app.ts\nEOF", true], ['explicit fd zero shell heredoc source write', "bash 0<<'EOF'\necho hacked > src/app.ts\nEOF", true], ['shell rcfile option still reads heredoc program', "bash --rcfile /tmp/rc <<'EOF'\necho hacked > src/app.ts\nEOF", true], diff --git a/templates/hooks/pre-tool-use.mjs b/templates/hooks/pre-tool-use.mjs index 837cd2190..b23ba3946 100644 --- a/templates/hooks/pre-tool-use.mjs +++ b/templates/hooks/pre-tool-use.mjs @@ -555,8 +555,7 @@ function shellGroup(text, openIndex) { if (ch === '\\') { i += 1; continue; } if (ch === '$' && text[i + 1] === '{') { brace += 1; i += 1; continue; } if (brace > 0) { - if (ch === '{') brace += 1; - else if (ch === '}') brace -= 1; + if (ch === '}') brace -= 1; else if (ch === '(') depth += 1; else if (ch === ')' && depth > 1) depth -= 1; continue; @@ -1439,7 +1438,7 @@ function checkSegment(segment, directory) { if (!shellArgs[codeIndex + 1]) return true; codeIndex += 2; continue; } - if (/^[+-][abefhkmnptuvxBCEHPT]+$/.test(value) || /^-[cilsD]$/.test(value) || /^(?:--norc|--noprofile|--posix|--restricted|--verbose|--debugger)$/.test(value)) { + if (/^[+-][abefhkmnptuvxBCEHPTcilsD]+$/.test(value) || /^(?:--norc|--noprofile|--posix|--restricted|--verbose|--debugger)$/.test(value)) { codeIndex += 1; continue; } if (value.startsWith('-') || value.startsWith('+')) return false;