Skip to content

fix(gateway): reject path-unsafe session_id on /v1/runs#71120

Open
fangliquanflq wants to merge 1 commit into
NousResearch:mainfrom
fangliquanflq:fix/api-runs-session-id-path-traversal
Open

fix(gateway): reject path-unsafe session_id on /v1/runs#71120
fangliquanflq wants to merge 1 commit into
NousResearch:mainfrom
fangliquanflq:fix/api-runs-session-id-path-traversal

Conversation

@fangliquanflq

Copy link
Copy Markdown

What does this PR do?

Reject path-unsafe, control-character, and oversized session_id values on POST /v1/runs before a run is accepted. Client-supplied IDs were passed through as AIAgent task_id, and Docker persistent sandboxes join get_sandbox_dir()/docker/task_id then os.makedirs, so ../ could create directories outside the sandbox root.

Bug Cause

/v1/chat/completions (X-Hermes-Session-Id) and POST /api/sessions already guard with gateway.session._is_path_unsafe plus control-char and length checks. POST /v1/runs took body.session_id (or a stored id from previous_response_id) with no equivalent check, then set effective_task_id = session_id for agent.run_conversation.

Reproduction Steps

  1. Enable the API Server with authentication and configure terminal.backend to Docker with persistent sandboxes.
  2. Authenticated POST /v1/runs with JSON {"input": "hello", "session_id": "../../pwned"}.
  3. Observe host directories created under the Hermes sandbox parent (outside .../docker/) when the agent starts a Docker environment.

Expected: HTTP 400 invalid_session_id, no agent start, no sandbox dirs outside the docker sandbox root.
Before fix: run accepted (202); task_id with ../ reaches Docker makedirs outside the sandbox root.

Fix

  • Add APIServerAdapter._reject_unsafe_session_id (control chars + _is_path_unsafe + _MAX_SESSION_HEADER_LEN).
  • Route /v1/runs, session create, and chat X-Hermes-Session-Id through the shared helper so the guard cannot drift.
  • Regression tests for path traversal, control characters, and oversized ids (assert agent is never created and no run state is allocated).

Out of scope: POST /api/sessions/{id}/fork still lacks the path-unsafe guard (sibling finding); follow-up PR.

Related Issue

No issue - discovered via bug-hunter finding BUG-2 (api_server /v1/runs session_id path traversal).

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • Security fix

Changes Made

  • gateway/platforms/api_server.py - shared _reject_unsafe_session_id; wire create, chat header, and /v1/runs
  • tests/gateway/test_api_server_runs.py - reject path-unsafe / control-char / oversized session_id

How to Test

  1. Manual: with API Server + Docker persistent backend, POST /v1/runs with session_id ../../pwned should return 400 and not create dirs outside the sandbox root.
  2. Automated (already run locally):
scripts/run_tests.sh tests/gateway/test_api_server_runs.py tests/gateway/test_session_api.py -q
scripts/run_tests.sh tests/gateway/test_api_server.py -k "traversal_session_id or provided_session_id" -q

Checklist

Code

  • I have read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this is not a duplicate
  • My PR contains only changes related to this fix/feature
  • I have run scripts/run_tests.sh on relevant tests and they pass
  • I have added tests for my changes
  • I have tested on my platform: Windows 11

Documentation and Housekeeping

  • I have updated relevant documentation - or N/A
  • I have updated cli-config.yaml.example if I added/changed config keys - or N/A
  • I have updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows - or N/A
  • I have considered cross-platform impact (Windows path separators covered by _is_path_unsafe)
  • I have updated tool descriptions/schemas if I changed tool behavior - or N/A

POST /v1/runs forwarded client session_id into AIAgent task_id without the
entry-boundary path guard used by chat/session create, so Docker persistent
sandboxes could makedirs outside the sandbox root.
@alt-glitch alt-glitch added type/security Security vulnerability or hardening comp/gateway Gateway runner, session dispatch, delivery area/auth Authentication, OAuth, credential pools P2 Medium — degraded but workaround exists sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Jul 25, 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/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists 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