Skip to content

fix(runner): confine task-file reads to the state directory - #16

Merged
BoozeLee merged 1 commit into
mainfrom
fix/runner-state-containment
Oct 13, 2026
Merged

BoozeLee merged 1 commit into
mainfrom
fix/runner-state-containment

Conversation

@BoozeLee

Copy link
Copy Markdown
Collaborator

Follow-up to #14, which did not close alert #3: the SARIF code flow is server route → Runner.create → _verify_run → jload(root/AE/tasks/<task>.json) (runner.py:223), not the server's own reads.

  • policy.confine / policy.state_file: resolve with realpath (symlinks included), ValueError if outside .ai-engineering.
  • Runner.create validates the task path before queueing (so a run is never left half-started); the read at line 223 goes through state_file.
  • Server _jload reuses confine instead of its own copy.

Still not exploitable before this (names pass NAME_RE first); this puts the guard on the path CodeQL traces.

Tests: test_state_file_stays_inside_the_state_directory ('..', absolute, symlink) and test_the_runner_refuses_an_escaping_task_name_before_queueing. Local: 66 passed / 11 failed (same environment failures as main without the change: 63+tests).

🤖 Generated with Claude Code

The data flow CodeQL reports for py/path-injection goes server route ->
Runner.create -> _verify_run -> jload(root/AE/tasks/<task>.json); the
previous fix guarded the server's own reads, not this one. A shared
policy.state_file now resolves the path (symlinks included) and refuses
anything outside .ai-engineering; Runner.create checks the name before
anything is queued, and the read itself goes through it. The server's
_jload uses the same helper instead of its own copy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@BoozeLee
BoozeLee merged commit d7685c5 into main Oct 13, 2026
6 checks passed
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