Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f6d9a84
test(core): add real-shell soundness oracle for bash scanner
kitlangton Oct 4, 2026
6d9efaf
fix(core): unify bash command scanner with recursive-descent parsing
kitlangton Oct 4, 2026
0abbbe0
fix(core): tighten case and for header validation and expand oracle
kitlangton Oct 4, 2026
f3bcd53
test(core): skip real-shell oracle on Windows and format scanner
kitlangton Oct 4, 2026
d0e57b4
test(core): add failing real-shell fixtures for scanner soundness gaps
kitlangton Oct 4, 2026
0974946
refactor(core): remove dead bash scanner state and guards
kitlangton Oct 4, 2026
9926646
refactor(core): track bash list state in one place
kitlangton Oct 4, 2026
b9c934a
fix(core): scan bash quoting and expansions with one primitive
kitlangton Oct 4, 2026
32f62ed
fix(core): end case pattern words at bracket metacharacters
kitlangton Oct 4, 2026
7fc28a7
fix(core): match bash operators and assignment subscripts structurally
kitlangton Oct 4, 2026
1764fad
fix(core): fail closed on words after a bash ampersand redirect
kitlangton Oct 4, 2026
46d263f
fix(core): bound bash heredoc continuation scanning
kitlangton Oct 4, 2026
6dd193c
refactor(core): split bash and powershell directory word resolution
kitlangton Oct 4, 2026
f375126
fix(core): fail closed on bash subscript and parameter evaluation
kitlangton Oct 4, 2026
2cc542c
fix(core): fail closed on zsh glob qualifier positions
kitlangton Oct 4, 2026
bd7ab85
fix(core): scan posix for loops without an in list
kitlangton Oct 4, 2026
527cfd6
fix(core): fail closed on bash reserved words after redirects
kitlangton Oct 4, 2026
2470f60
refactor(core): read bash function heads and continuations declaratively
kitlangton Oct 4, 2026
1cdc33d
fix(core): mark every bash expansion in decoded subscript text
kitlangton Oct 4, 2026
66329a0
test(core): generate nested real-shell oracle fixtures from one list
kitlangton Oct 4, 2026
81926b2
refactor(core): skip the bash unit scanner for ordinary characters
kitlangton Oct 4, 2026
8a6f4a1
docs(core): note the runtime limit of bash subscript checks
kitlangton Oct 5, 2026
e7ae5a7
fix(core): limit bash subscript evaluation checks to shell sinks
kitlangton Oct 5, 2026
3993dce
test(core): add failing fixtures for reviewer-confirmed scanner misses
kitlangton Oct 5, 2026
454d474
fix(core): share pending bash heredocs across nested scans
kitlangton Oct 5, 2026
89b4f2c
fix(core): scan dash double parentheses under a posix dialect
kitlangton Oct 5, 2026
005e195
fix(core): fail closed on bash arithmetic that rereads as a subshell
kitlangton Oct 5, 2026
5bcebfa
fix(core): reject quote-hidden parameter ends in bash arithmetic quotes
kitlangton Oct 5, 2026
fa69d1d
fix(core): check bash arithmetic contexts and bound values for litera…
kitlangton Oct 5, 2026
d768766
fix(core): fail closed on zsh flag groups and glob modifiers
kitlangton Oct 5, 2026
e8cbdb8
fix(core): fail closed on zsh array adjacency and dash script aliases
kitlangton Oct 5, 2026
f8dd0ae
test(core): drop empty known-gap scaffolding
kitlangton Oct 5, 2026
a61ed90
test(core): verify oracle fixture execution only in strict mode
kitlangton Oct 5, 2026
a6320df
fix(core): close remaining shell scanner soundness gaps and false opa…
kitlangton Oct 5, 2026
f664209
fix(core): harden shell scanner parameter, subscript, ansi-quote, and…
kitlangton Oct 5, 2026
a197414
fix(core): harden shell scanner subscripts, escape decoders, and cont…
kitlangton Oct 5, 2026
d5debc3
fix(core): close shell scanner subscript, conditional, and quote desyncs
kitlangton Oct 5, 2026
1b113c9
fix(core): tighten ansi-quote and double-quoted parameter desync checks
kitlangton Oct 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions packages/core/src/shell/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,10 @@ export const scanPortable = Effect.fnUntraced(function* (command: string, shell:
catch: (cause) => new Error(`Portable shell scanner failed to load: ${cause}`, { cause }),
})
const powershell = ShellSelect.ps(shell)
const result = powershell ? ShellScan.scanPowerShell(command) : ShellScan.scan(command)
const name = ShellSelect.name(shell)
const result = powershell
? ShellScan.scanPowerShell(command)
: ShellScan.scan(command, name === "bash" || name === "zsh" ? name : "posix")
if (result.kind === "opaque")
return yield* Effect.fail(new Error(`Portable shell scanner cannot analyze command: ${result.reason}`))

Expand All @@ -225,15 +228,21 @@ export const scanPortable = Effect.fnUntraced(function* (command: string, shell:
if (CWD.has(name)) {
output.directories.push(
...directoryArgs(
words.flatMap((text): Part[] => {
const parameter = powershell ? /^(-(?:literalpath|path)):(.*)$/i.exec(text) : undefined
if (parameter)
return [
{ type: "command_parameter", text: parameter[1] },
{ type: "word", text: parameter[2] },
]
return [{ type: powershell && text.startsWith("-") ? "command_parameter" : "word", text }]
}),
powershell
? words.flatMap((text): Part[] => {
const parameter = /^(-(?:literalpath|path)):(.*)$/i.exec(text)
if (parameter)
return [
{ type: "command_parameter", text: parameter[1] },
{ type: "word", text: parameter[2] },
]
return [{ type: text.startsWith("-") ? "command_parameter" : "word", text }]
})
: item.rawWords.map((text, index) => ({
type: "word",
// Only literal quoting resolves to a static directory.
text: text.startsWith("$'") || (!/[$`~\\]/.test(text) && /['"]/.test(text)) ? item.words[index] : text,
})),
powershell,
cwd,
shell,
Expand Down
Loading
Loading