Skip to content

fix(cli): close read-only bash exec-flag escapes - #11890

Merged
markijbema merged 1 commit into
mainfrom
mark/readonly-bash-exec-flag-denies
Jul 2, 2026
Merged

fix(cli): close read-only bash exec-flag escapes#11890
markijbema merged 1 commit into
mainfrom
mark/readonly-bash-exec-flag-denies

Conversation

@markijbema

Copy link
Copy Markdown
Contributor

What

Harden the readOnlyBash permission allowlist (used by the ask/plan/explore agents) against commands that are "read-only" in spirit but can still execute an arbitrary program through a flag.

The allowlist permits sort, rg, ag, man, etc., and previously relied on blocklisting only a couple of sort writer flags (-o, --output). That approach missed several exec-via-flag escapes:

  • sort --compress-program <prog> — GNU sort execs the program (the reported bypass: echo ... | sort -S 1b --compress-program "sh"), plus --files0-from
  • rg --pre <prog> / --pre=<prog> / --hostname-bin — ripgrep runs an arbitrary preprocessor
  • ag --pager <prog>
  • man -P <prog> / --pager / -H — man runs an arbitrary pager/browser (including the glued short form man -Psh)

These are now denied. While in there, the operator and sort-output deny rules were deduplicated: since * matches any run of characters (spaces and empty), *>* already subsumes >>/>|/spaced variants and *&* subsumes &&, so the redundant lines were collapsed and commented.

Why

An allowed but prompt-injected/untrusted agent could run sort --compress-program sh (and friends) to execute arbitrary shell without triggering an approval prompt.

Note

This is defense-in-depth on top of a string-matching allowlist, not a real sandbox. Command-line blocklists are inherently leaky (env-based vectors like LESSOPEN, GIT_PAGER, etc. remain). The durable fix is OS-level sandboxing of bash execution — worth a separate follow-up. Comments in the file now say as much.

Testing

Added deny cases in test/kilocode/ask-agent-permissions.test.ts for every new vector (including the glued man -Psh form). Rule logic was validated against the exact Wildcard.match + findLast semantics (all deny vectors caught; sort foo-o bar, rg --pre-glob, man --help, sort -S 1b remain allowed — no false positives).

The readOnlyBash allowlist permits sort/rg/ag/man but relied on
blocklisting only a couple of writer flags. GNU sort execs an arbitrary
program via --compress-program (e.g. sort --compress-program sh), and
rg --pre, ag --pager, and man -P/-H have equivalent exec-via-flag
escapes. Deny those flags, and dedupe the now-overlapping operator and
sort output rules.
@markijbema
markijbema marked this pull request as ready for review July 2, 2026 13:01
@markijbema
markijbema enabled auto-merge July 2, 2026 13:01
@kilo-code-bot

kilo-code-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • .changeset/fix-readonly-bash-exec-flag-escapes.md
  • packages/opencode/src/kilocode/agent/index.ts
  • packages/opencode/test/kilocode/ask-agent-permissions.test.ts

Notes

  • Verified the new deny rules against Wildcard.match's regex semantics (including the " *" → optional-trailing-group rewrite): rg *--pre *, rg *--pre=*, sort *--compress-program*, sort *--files0-from*, ag *--pager*, man *-P*, man *--pager*, and man *-H* all catch the intended exec vectors without over-matching adjacent legitimate flags (--pre-glob, --pretty, --help, sort foo-o bar).
  • findLast-based rule evaluation (packages/core/src/permission.ts) means insertion order matters; the new deny rules are appended after the corresponding allow rules, so precedence is correct.
  • The dedup of the operator/sort --output rules is a genuine no-op simplification — the removed narrower forms were already subsumed by the broader *>*/*--output* patterns.
  • Test additions in ask-agent-permissions.test.ts match the new deny rules and don't duplicate implementation logic.
  • Change is confined to packages/opencode/src/kilocode/ (no kilocode_change markers needed) and includes a concise, user-facing changeset.

lgtm


Reviewed by claude-sonnet-5-20260630 · Input: 38 · Output: 17.9K · Cached: 1.1M

Review guidance: REVIEW.md from base branch main

@markijbema
markijbema merged commit f6e0e87 into main Jul 2, 2026
27 checks passed
@markijbema
markijbema deleted the mark/readonly-bash-exec-flag-denies branch July 2, 2026 14:55
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
…ec-flag-denies

fix(cli): close read-only bash exec-flag escapes
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.

2 participants