Skip to content

feat: add subprocess wrapper detection (perl -e, python -c, node -e, ruby -e)#10

Merged
royosherove merged 4 commits into
mainfrom
feat/hardno-subprocess-detection
May 16, 2026
Merged

feat: add subprocess wrapper detection (perl -e, python -c, node -e, ruby -e)#10
royosherove merged 4 commits into
mainfrom
feat/hardno-subprocess-detection

Conversation

@royosherove
Copy link
Copy Markdown
Member

Description

Deterministic pre-check in judge to detect opaque subprocess wrapper patterns that cannot be statically analyzed.

Changes

  • judge.ts: Added detectSubprocessWrapper() pre-check returning 'unsure' for perl -e/-E, python -c, node -e/-E/--eval, ruby -e
  • judge.ts: Updated classifyBashCommand() to call pre-check before LLM judge
  • judge.ts: Updated PROMPT taxonomy to document these patterns (with note that pre-check catches them)
  • test/judge.test.ts: Added 11 comprehensive tests

Why

Subprocess one-liners are inherently opaque—their behavior cannot be determined from the command line alone. Conservative fail ('unsure') is better than LLM timeout or false negatives.

Architect Review Fixes (Commit 0f12377)

  1. Regex improvements: Changed from quote requirement (-e ') to optional argument pattern ((?:\s+\S|$)) to handle unquoted (perl -e code), variables (python -c $payload), and heredocs
  2. False-positive acceptance: Documented and tested (e.g., echo "perl -e foo" returns 'unsure' — acceptable fail-safe)
  3. Prompt defense-in-depth: Kept prompt line with clarifying note even though pre-check prevents LLM seeing these patterns

Test Results

  • 431 tests passing (+11 subprocess detection tests, 0 failures)
  • TypeScript clean
  • Edge case coverage: quoted forms, unquoted forms, variables, false-positives

Related

Aligns with pi-branch-enforcer Tier 1.5 subprocess detection (same language patterns, different tool used at push-gate vs. code review)

…ruby -e)

- Detect perl -e/-E, python -c, python3 -c, node -e/-E/--eval, ruby -e patterns
- Pre-check in classifyBashCommand before LLM judge (deterministic, no runner call)
- Return 'unsure' for these patterns (cannot statically analyze subprocess contents)
- Update judge prompt taxonomy to include these patterns
- Add 8 comprehensive test cases covering all variants (uppercase flags, long flags)
- Tests verify that wrappers skip LLM call and return 'unsure' immediately
- Tests verify non-wrapper commands still call the runner

All 428 tests passing.
…ase tests

Fixes from architect review:

1. **Regex improvements:**
   - Change quote requirement to optional argument: `perl -e $code` and `perl -e code` now detected
   - Use `(?:\s+\S|$)` pattern instead of `['"]` to match unquoted, variables, heredocs
   - Updated all patterns (perl, python, node, ruby) for consistency

2. **Edge case tests:**
   - Added test for unquoted form: `perl -e some_code`
   - Added test for variable expansion: `python -c $payload`
   - Added test for false-positive (acceptable fail-safe): `echo "perl -e foo"` marks unsure even though echo is harmless

3. **Documentation:**
   - Updated function comment to explain false-positive acceptance (fail-safe is better than false negatives)
   - Updated prompt taxonomy to note these patterns are caught by pre-check

**All 431 tests passing** (no regressions, +3 edge case tests for coverage).
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f12377527

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread judge.ts
}

// node -e / -E / --eval with any argument
if (/\bnode\b.*(?:\s-[eE]|--eval)(?:\s+\S|$)/.test(command)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match node --eval= in subprocess wrapper pre-check

The new Node wrapper regex misses the canonical long-option form --eval=...: node --help documents -e, --eval=..., but this pattern only matches when --eval is followed by whitespace or end-of-command. As a result, commands like node --eval=require('fs').writeFileSync(...) bypass the deterministic unsure guard and fall through to the LLM path, which can incorrectly suppress review if it returns inspection_vcs_noop; at minimum, this defeats the intended hard fail-safe for opaque one-liners.

Useful? React with 👍 / 👎.

@royosherove royosherove merged commit 9bb9e39 into main May 16, 2026
2 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d87178de7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread judge.ts
}

// python / python3 -c with any argument
if (/\bpython\d?\b.*\s-c(?:\s+\S|$)/.test(command)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Detect no-space -e/-c one-liners in wrapper pre-check

The wrapper regexes require whitespace after the flag via (?:\s+\S|$), so valid no-space forms like python -c'print(1)', ruby -e'puts 1', and perl -e'print 1' are missed by the deterministic guard. Those commands then fall through to the LLM classifier, which can return inspection_vcs_noop and 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 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant