fix(security): create terminal env snapshots owner-only (0600) - #60199
Merged
Conversation
BaseEnvironment writes shell snapshots and cwd metadata through the process umask. With a common 022 umask, snapshot files containing exported environment state landed at mode 0644 even though they can include env-carried credentials from the parent process. Set umask 077 only around Hermes metadata writes: the initial snapshot bootstrap and the post-command snapshot/cwd refresh. User commands still run under the caller's original umask, while Hermes-owned snapshot and cwd files are created owner-only. This intentionally does not copy the source PR's global orphan sweep; deleting all matching /tmp snapshot files could interfere with concurrent Hermes processes. The security-critical local disclosure fix is the file mode clamp. This is salvageable because the source report still identifies a concrete credential-disclosure path, but the safe subset is smaller than the original proposal: clamp only the Hermes-owned snapshot writes and leave process-wide cleanup, user command umask, and concurrent sessions alone. Salvages source PR: #20056 Related issue: #48441 Co-authored-by: Andrew Homeyer <andrew@hndl.app>
This was referenced Jul 7, 2026
Closed
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Terminal session snapshot files (
hermes-snap-*.sh) are now created owner-only (0600) instead of inheriting the process umask, closing a local credential-disclosure path on shared hosts.Root cause:
BaseEnvironmentpersists the shell environment across spawn-per-call commands viaexport -p >redirects, which inherit the ambient umask — with the common 0022/0002 defaults the snapshot landed world-readable in/tmpwhile containing every exported env var (including operator-set secrets likeBWS_ACCESS_TOKENthat the provider-env blocklist never covers).This reverses the earlier by-design call on #48441 / #41278 / #57386:
/tmpis world-traversable unlike~/.hermes, so on multi-user hosts the snapshot was the one copy of secrets another local user could actually open, and reports kept recurring. Salvages @egilewski's clean two-file commit from #57386 (co-authored by @andrewhomeyer, original fix in #20056) with authorship preserved.Changes
tools/environments/base.py:umask 077before the bootstrap snapshot dump ininit_session(), and after the user's command (before the re-dump) in_wrap_command()— the user command itself keeps its own ambient umasktests/tools/test_base_environment.py: 6 new permission tests (TestSnapshotPermissions)scripts/release.py: AUTHOR_MAP entry for co-authorValidation
scripts/run_tests.sh tests/tools/test_base_environment.pyexportsurvives across calls; user command still seesumask 0002docker execcalls use the container's single exec user (docker.py_run_bash)Closes #48441.
Infographic