Skip to content

feat(approvals): detect exec-via-flag escapes on read-only commands (port kilocode#11890) - #59899

Closed
teknium1 wants to merge 1 commit into
mainfrom
kilocode-port/exec-via-flag-guard
Closed

feat(approvals): detect exec-via-flag escapes on read-only commands (port kilocode#11890)#59899
teknium1 wants to merge 1 commit into
mainfrom
kilocode-port/exec-via-flag-guard

Conversation

@teknium1

@teknium1 teknium1 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

The approval system now detects exec-via-flag escapes on otherwise read-only commands — sort --compress-program, rg --pre / --hostname-bin, ag --pager, and man -P / --pager / --html — and surfaces payloads smuggled through those flags to the hardline floor.

Port of Kilo-Org/kilocode#11890 ("close read-only bash exec-flag escapes"), adapted to Hermes's regex-based dangerous-pattern detection instead of Kilo's glob allow/deny rule list.

The gap (confirmed live on main): these flags make an innocuous-looking command execute an arbitrary program. Before this change, sort --compress-program=sh names.txt ran with zero approval, and — worse — sort --compress-program='rm -rf --no-preserve-root /' f bypassed the unconditional hardline floor entirely, because the payload was opaque argument text that never anchored at a command position.

Changes

  • tools/approval.py:
    • 7 new DANGEROUS_PATTERNS entries flagging the mechanism itself (approval required even when the payload is a script whose contents we cannot inspect).
    • _exec_flag_payloads() + wiring in _command_detection_variants(): extracts each flag's program value and yields it as its own detection variant, so a hardline payload inside the flag anchors at command position and hits the floor. man's short -P/-H flags are scoped to a man command context so grep -P (perl regex) never false-positives.
  • tests/tools/test_exec_via_flag_guard.py: 30 tests — attack shapes, hardline-payload floor coverage, legit-command negatives (rg --pretty, pip install --pre, man -k pager, grep -P), payload-extraction unit tests.

Adaptation notes

  • Kilo's fix edits a glob rule table (readOnlyBash) on their allowlist agent; Hermes has no per-agent allowlist, so the port lands in the shared DANGEROUS_PATTERNS / detection-variant machinery that guards every terminal call.
  • Kilo's sort --files0-from deny was not ported: it only reads a file list, which is within Hermes's threat model for the agent (it has read_file anyway) — flagging it would be a pointless approval prompt.
  • Defense-in-depth is layered: mechanism-level dangerous flag (yolo can pass it through, as intended) + payload-level hardline floor (nothing passes it through).

Validation

Before After
sort --compress-program=sh f no prompt approval required
sort --compress-program='rm -rf /' f runs under yolo hardline blocked
man -P 'rm -rf /' ls no prompt hardline blocked
rg --pretty, grep -P, pip install --pre pass still pass

554 tests green across the approval suites (test_approval, test_hardline_blocklist, test_approval_deny_rules, test_smart_approval_injection, test_exec_via_flag_guard + interrupt/cron/write/clean-slate suites).

Infographic

exec-via-flag-guard

…port kilocode#11890)

Flags on otherwise read-only commands that execute an arbitrary program
(sort --compress-program, rg --pre/--hostname-bin, ag --pager,
man -P/--pager/--html) were invisible to approval detection: the flag
value is opaque argument text, so 'sort --compress-program=sh f' ran
without a prompt and a hardline payload smuggled through the flag
('sort --compress-program="rm -rf /" f') bypassed the unconditional
floor entirely.

Two layers, mirroring Kilo-Org/kilocode#11890:
- New DANGEROUS_PATTERNS entries flag the mechanism itself, so the
  command requires approval even when the payload is a script whose
  contents we cannot see.
- _exec_flag_payloads() surfaces each flag's program value as its own
  detection variant in _command_detection_variants(), so hardline
  payloads anchor at command position and hit the floor.

E2E: 11 attack shapes detected, 5 hardline payloads reach the floor,
11 legit commands (rg --pretty, grep -P, pip install --pre, man -k
pager) unflagged. 554 approval-suite tests green.
@alt-glitch alt-glitch added type/security Security vulnerability or hardening comp/tools Tool registry, model_tools, toolsets area/auth Authentication, OAuth, credential pools sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data needs-repro Bug needs reproduction steps P3 Low — cosmetic, nice to have labels Jul 7, 2026
@teknium1

Copy link
Copy Markdown
Contributor Author

Closing — this exec-via-flag detection already landed on main via b90dbac1d6 "fix(approval): unify execution-bearing option detection", which uses a quote-aware structural tokenizer covering the same flag set as this PR plus interpreter -e/-c, shell -c, heredocs, and recursive nested-payload handling. Superset of this port; closing as already-implemented.

@teknium1 teknium1 closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/tools Tool registry, model_tools, toolsets needs-repro Bug needs reproduction steps P3 Low — cosmetic, nice to have sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants