Skip to content

fix(security): guard cron script against path traversal and redact output - #5093

Closed
memosr wants to merge 2 commits into
NousResearch:mainfrom
memosr:fix/cron-script-path-traversal-and-redact
Closed

memosr wants to merge 2 commits into
NousResearch:mainfrom
memosr:fix/cron-script-path-traversal-and-redact

Conversation

@memosr

@memosr memosr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

The new script field added in #5082 lets cron jobs run a Python script
before each turn to collect context data. Two security issues were introduced:

1. Path Traversal

Relative script paths were resolved against HERMES_HOME/scripts/ but
without checking that the resolved path stays inside that directory:

# Before (vulnerable)
path = get_hermes_home() / "scripts" / path

A job with script: "../../.hermes/auth.json" would resolve to the auth
store and attempt to execute it as Python — leaking its path in the error
message, or worse if the file happened to be valid Python.

Fix: After resolving the path, verify it stays within scripts_dir
using Path.relative_to(). Paths that escape the directory are rejected
with a clear error message.

# After (safe)
scripts_dir = get_hermes_home() / "scripts"
path = (scripts_dir / path).resolve()
try:
    path.relative_to(scripts_dir.resolve())
except ValueError:
    return False, f"Script path escapes the scripts directory: {script_path!r}"

2. Secret Leakage via Script Output

Script stdout is injected directly into the cron job's LLM prompt context
without redaction. If a script outputs environment variables, config values,
or any string matching a known secret pattern, those secrets flow into the
LLM context unmasked.

Fix: Apply redact_sensitive_text() to stdout before injecting it —
the same function already used for execute_code sandbox output and log
redaction.

from agent.redact import redact_sensitive_text
stdout = redact_sensitive_text(stdout)

3. Absolute Path Restriction (follow-up commit)

The initial fix only guarded relative paths. Absolute paths like
/tmp/evil.py or /etc/passwd were still accepted.

Fix: Absolute paths are now also restricted — they must resolve
inside HERMES_HOME. Paths outside are rejected with a clear error.

path.relative_to(get_hermes_home().resolve())

Type of Change

  • 🔒 Security fix (path traversal)
  • 🔒 Security fix (secret leakage)

Checklist

  • Read the Contributing Guide
  • Commit messages follow Conventional Commits
  • Consistent with existing path validation pattern (Path.relative_to())
  • Consistent with existing redaction pattern (execute_code sandbox)
  • No behavior change for legitimate scripts in HERMES_HOME/scripts/

teknium1 pushed a commit that referenced this pull request Apr 4, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR #5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
teknium1 pushed a commit that referenced this pull request Apr 5, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR #5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
@teknium1

teknium1 commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

Merged via PR #5147. Your path traversal guard and secret redaction fixes were cherry-picked onto current main with your authorship preserved. The absolute path restriction to HERMES_HOME was dropped as too restrictive for the feature's design intent — users may legitimately point cron scripts at paths outside ~/.hermes/. Thanks for the contribution!

@teknium1 teknium1 closed this Apr 5, 2026
naoironman-hue pushed a commit to naoironman-hue/hermes-agent that referenced this pull request Apr 5, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
Tommyeds pushed a commit to Tommyeds/hermes-agent that referenced this pull request Apr 12, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 28, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
jh1nresh pushed a commit to jh1nresh/hermes-agent that referenced this pull request Aug 26, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
@memosr
memosr deleted the fix/cron-script-path-traversal-and-redact branch August 27, 2026 03:27
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
…tput

Relative script paths resolved against HERMES_HOME/scripts/ were not
validated to stay within that directory. Paths like '../../etc/passwd'
could escape and be executed as Python.

Fix: resolve the path and verify it stays within scripts_dir using
Path.relative_to(). Also apply redact_sensitive_text() to script stdout
before LLM injection — same pattern as execute_code sandbox output.

Cherry-picked from PR NousResearch#5093 by memosr (fixes 1 and 3; absolute path
restriction dropped as too restrictive for the feature's design intent).
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