Skip to content

fix(file): harden read_file device alias blocking - #50221

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-f6417239
Jun 21, 2026
Merged

teknium1 merged 1 commit into
mainfrom
hermes/hermes-f6417239

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Summary

Closes two residual read_file device-blocklist bypasses on top of the existing realpath pass: normpath-style path aliases (/dev/../dev/zero) and symlinks whose intermediate hop is a blocked stdio alias that realpath resolves through to a non-blocked tty.

Changes

  • tools/file_tools.py: _is_blocked_device_path normalizes via normpath before matching; _is_blocked_device walks each symlink hop (20-hop cap + cycle guard) and checks it against the blocklist before the final realpath check. Existing /proc/*/{fd,environ,cmdline,maps} protections preserved.
  • tests/tools/test_file_read_guards.py: regression coverage for /dev/..//dev/. aliases and a symlink to a blocked alias.

Validation

case before after
symlink -> /dev/stdin not blocked blocked
symlink -> /dev/../dev/stdin not blocked blocked
/dev/../dev/zero, /dev/./urandom blocked (via realpath only) blocked (literal too)
/dev/null, /tmp/test.py, /proc/cpuinfo allowed allowed (no false positives)
symlink loop no hang (20-hop + cycle guard)

tests/tools/test_file_read_guards.py: 41/41 pass. E2E verified with real imports against a temp HERMES_HOME (all 11 cases above).

Salvage of #34466 by @egilewski (cherry-picked onto current main, authorship preserved). Closes #10141 and tracking advisory #29158 (GHSA-3p9q-rxhm-5x3g).

Infographic

hardening-read-file-device-blocklist

Security-hardening fix for the read_file device guard, not a new sandbox
boundary. The guard already rejects direct device paths and upstream now
has a resolved-path pass for workspace symlinks to blocked devices, but
its concrete-path helper still compared the expanded path before
normalization. That leaves residual alias cases where the dangerous path
is visible before final terminal-specific resolution, for example:

  1. /dev/../dev/zero and /dev/./urandom should match the blocked-device
     list as concrete paths, not only after final realpath;
  2. /dev/stdin-style aliases can disappear once realpath follows them
     to /proc/self/fd/0 and then to a tty path;
  3. a user symlink to /dev/../dev/stdin exposes the dangerous
     intermediate target before final resolution, but not necessarily
     after it.

Normalize expanded paths before matching and inspect each symlink hop
before falling back to realpath. This preserves the existing /proc fd and
/proc pseudo-file guards while enforcing the intended security invariant:
model-supplied read paths must not reach blocking or infinite device
streams through spelling, normalization, or symlink-hop tricks.

Classification: security hardening / residual bypass fix for the
read_file device blocklist. This is defensive code at the file-tool
boundary, but it fixes a concrete denial-of-service class tracked as
security in #10141 and #29158.

Tests:
  - normalized /dev/../dev/zero and /dev/./urandom aliases
  - symlink to /dev/../dev/stdin blocked before realpath
  - existing symlink-to-device and regular-symlink guards still pass

Fixes #10141
Fixes #29158
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-f6417239 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11304 on HEAD, 11304 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5925 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening tool/file File tools (read, write, patch, search) P1 High — major feature broken, no workaround labels Jun 21, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

Related: #34466 (original by @egilewski, salvaged here), tracking advisory #29158 (GHSA-3p9q-rxhm-5x3g), and #10141 (symlink-bypass facet). Salvage onto current main with authorship preserved.

@egilewski

Copy link
Copy Markdown
Contributor

Follow-up: I rebased and force-pushed the original #34466 branch onto current origin/main.

#34466 now has the original hardening commit plus a separate signed follow-up for the TERMINAL_CWD relative-symlink gap:

  • 8a73c72a8 fix(file): harden read_file device alias blocking
  • acee75a84 fix(file): anchor device symlink guard to task cwd

That follow-up covers the issue found while reviewing this salvage PR: a relative workspace symlink to /dev/../dev/stdin could still reach the read sink because the symlink-hop guard ran before task-cwd resolution.

Given that the original branch now carries the current-base fix directly, this salvage PR should not need another cherry-pick of the follow-up fix.

Signed: GPT-5.5 in Codex

@teknium1
teknium1 merged commit 9078b4b into main Jun 21, 2026
35 checks passed
@teknium1
teknium1 deleted the hermes/hermes-f6417239 branch June 21, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P1 High — major feature broken, no workaround tool/file File tools (read, write, patch, search) type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] _is_blocked_device verify bypass

3 participants