-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add subprocess wrapper detection (perl -e, python -c, node -e, ruby -e) #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fca9ee2
0f12377
7ebab07
d87178d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,7 @@ TAXONOMY (authoritative): | |
| - npm/pnpm/yarn/pip/cargo install, make, cargo build, npm run format, codegen scripts → modifying | ||
| - kill/pkill/systemctl, docker run, docker compose up → modifying | ||
| - sed -i, perl -pi → modifying (in-place edit) | ||
| - perl -e, python -c, node -e, ruby -e (one-liners) → unsure (static analysis cannot determine side effects; caught by detectSubprocessWrapper pre-check) | ||
| - ./script.sh or npm run <unknown> → unsure unless clearly read-only | ||
| - truncated command (e.g. "git commi") → unsure | ||
| - Compound commands with &&, ;, ||, pipes, subshells: ANY modifying part → modifying; ANY unknown/truncated → unsure; otherwise the class of the safest-subset. | ||
|
|
@@ -101,16 +102,62 @@ export function parseJudgeResponse(raw: string): BashClassification { | |
| return "unsure"; | ||
| } | ||
|
|
||
| /** | ||
| * Detect subprocess wrappers (perl -e, python -c, node -e, ruby -e) that cannot | ||
| * be statically analyzed. Returns 'unsure' for these patterns (conservative). | ||
| * | ||
| * Note: False-positives are acceptable here (fail-safe direction). Regexes match | ||
| * broadly to catch unquoted/variable forms (perl -e $code) and even literal strings | ||
| * in other commands (echo "perl -e foo"), since marking those 'unsure' is | ||
| * safer than missing an actual one-liner. | ||
| */ | ||
| function detectSubprocessWrapper(command: string): BashClassification | null { | ||
| if (!command) return null; | ||
|
|
||
| // perl -e / -E with any argument (quoted, unquoted, or variable) | ||
| if (/\bperl\b.*\s-[eE](?:\s+\S|$)/.test(command)) { | ||
| return "unsure"; | ||
| } | ||
|
|
||
| // python / python3 -c with any argument | ||
| if (/\bpython\d?\b.*\s-c(?:\s+\S|$)/.test(command)) { | ||
| return "unsure"; | ||
| } | ||
|
|
||
| // node -e / -E / --eval with any argument | ||
| if (/\bnode\b.*(?:\s-[eE]|--eval)(?:\s+\S|$)/.test(command)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new Node wrapper regex misses the canonical long-option form Useful? React with 👍 / 👎. |
||
| return "unsure"; | ||
| } | ||
|
|
||
| // ruby -e with any argument | ||
| if (/\bruby\b.*\s-e(?:\s+\S|$)/.test(command)) { | ||
| return "unsure"; | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Run the judge on a single bash command. Always resolves (never rejects); | ||
| * any failure collapses to `unsure` so the caller's skip logic stays safe. | ||
| * | ||
| * Pre-checks for subprocess wrappers (perl -e, python -c, etc.) before calling | ||
| * the LLM, since these patterns cannot be statically analyzed. | ||
| */ | ||
| export async function classifyBashCommand( | ||
| runner: JudgeRunner, | ||
| command: string, | ||
| opts: JudgeOptions, | ||
| ): Promise<BashClassification> { | ||
| if (!command || typeof command !== "string") return "unsure"; | ||
|
|
||
| // Deterministic pre-check: subprocess wrappers | ||
| const subprocessResult = detectSubprocessWrapper(command); | ||
| if (subprocessResult) { | ||
| log(`judge: detected subprocess wrapper (${command.slice(0, 40)}...) → unsure`); | ||
| return subprocessResult; | ||
| } | ||
|
|
||
| try { | ||
| const { text } = await runner(command, opts); | ||
| return parseJudgeResponse(text); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wrapper regexes require whitespace after the flag via
(?:\s+\S|$), so valid no-space forms likepython -c'print(1)',ruby -e'puts 1', andperl -e'print 1'are missed by the deterministic guard. Those commands then fall through to the LLM classifier, which can returninspection_vcs_noopand incorrectly suppress review for code that may mutate files. Since the goal of this pre-check is to fail safe on opaque one-liners, these common shell forms should also be matched.Useful? React with 👍 / 👎.