Skip to content

fix(tool): honor the safe-env allowlist in the read-only check - #3803

Open
konlue wants to merge 1 commit into
agentscope-ai:mainfrom
konlue:fix/bash-readonly-env-allowlist
Open

konlue wants to merge 1 commit into
agentscope-ai:mainfrom
konlue:fix/bash-readonly-env-allowlist

Conversation

@konlue

@konlue konlue commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

AgentScope Version

2.0.12dev (main @ 782bd43)

Description

BashCommandParser._is_single_command_read_only skipped every leading VAR=value assignment unconditionally before classifying the command, so an unsafe assignment could hide a SAFE_COMMANDS member behind it: LD_PRELOAD=/tmp/evil.so grep -n todo src/a.py (or PATH=/tmp/evil grep todo src/a.py, swapping the executed binary outright) was classified read-only and auto-allowed in every permission mode including DEFAULT — check_permissions step 1 returns ALLOW for read-only commands, and the engine's read-only fast path short-circuits the same way. Neither payload contains $(…), <( or any other dynamic structure, so the injection-risk check passes it through untouched. _extract_command_prefix in the same file already refuses to extract a prefix when a non-allowlisted assignment is present, so rule generation stayed safe while the read-only fast path allowed the command outright (#3802).

Changes — the skip loop now only steps over assignments that cannot change the program that runs:

  • the assignment name must be in the existing SAFE_ENV_VARS allowlist (matching _extract_command_prefix's semantics), except
  • PATH and the LD_* / DYLD_* loader variables are never skipped, because they change which binary executes or how it loads — PATH itself is on the allowlist, so an allowlist-only fix would not have covered PATH=/tmp/evil grep ….

Anything else (e.g. LD_PRELOAD=…, FOO=1) falls through to the normal checks.

How to test

New case in the existing BashParserReadOnlyTest (tests/permission_bash_parser_test.py):

  • test_env_assignments_are_not_skipped_blindly — fails on main (the three payloads LD_PRELOAD=… grep, PATH=/tmp/evil grep, DYLD_INSERT_LIBRARIES=… grep are all classified read-only), passes with this fix;
  • whitelisted prefixes that cannot change the program keep the fast path (NODE_ENV=prod grep …, DEBUG=1 cat … remain read-only), and the existing prefix-extraction expectations (PATH=/usr/bin npm run build → npm run) are untouched.
python -m pytest tests/permission_bash_parser_test.py
# 3 passed, 91 skipped (Windows-skipped classes), plus the unskipped run below.
# BashParserReadOnlyTest + builtin_bash_test with the Windows skip lifted: 49 tests, OK.

Fixes #3802

Checklist

  • An issue has been created for this PR
  • I have read the CONTRIBUTING.md
  • Docstrings are in Google style
  • Related documentation has been updated (e.g. links, examples, etc.) in documentation repository
  • Code is ready for review

_is_single_command_read_only skipped every leading VAR=value assignment
unconditionally before classifying the command, so an unsafe assignment
could hide a SAFE_COMMANDS member behind it: LD_PRELOAD=/tmp/evil.so
grep … (or PATH=/tmp/evil grep …, swapping the binary outright) was
classified read-only and auto-allowed in every permission mode, while
_extract_command_prefix in the same file refuses to extract a prefix
when a non-allowlisted assignment is present.

Only step over assignments that cannot change the program that runs:
whitelisted names except PATH and the LD_*/DYLD_* loader variables.
Everything else falls through to the normal checks.
@github-actions github-actions Bot added the pr/awaiting-review Waiting for maintainers to review this PR label Nov 7, 2026

This branch has not been deployed

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

Labels

pr/awaiting-review Waiting for maintainers to review this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Bash read-only fast path skips env assignments without the safe-env check — "LD_PRELOAD=… grep" is auto-allowed

1 participant