fix(config): chown ensure_hermes_home dirs to HERMES_UID/GID in Docker (#34107)#34268
Merged
benbarclay merged 1 commit intoJun 1, 2026
Conversation
NousResearch#34107) Fixes NousResearch#34107. When Hermes runs in Docker with HERMES_UID=1000 / HERMES_GID=911, the entrypoint chowns the top-level HERMES_HOME once at startup — but subdirectories created at runtime by ensure_hermes_home() (especially for profile namespaces under profiles/<name>/ spawned by kanban workers) were landing as root:root and blocking subsequent uid-mapped worker invocations with: PermissionError: [Errno 13] Permission denied: '/opt/data/profiles/charles/logs/curator' Fix: add _resolve_hermes_uid_gid + _chown_to_hermes_uid helpers that read the env vars and apply chown after mkdir. Invoke from _secure_dir which already runs after every directory creation in the home-init path, so all newly-created subdirs (including the profile namespaces) get the right ownership. Safety properties: - No-op when HERMES_UID/HERMES_GID unset (the dominant non-Docker path) - No-op on Windows (os.chown doesn't exist; AttributeError swallowed) - No-op when running as non-root (EPERM swallowed — the entrypoint's startup chown -R picks it up on next restart, and in most cases the dir was already correctly-owned by the calling user) - Uses -1 sentinel for missing field so only the set value applies - Empty-string env vars treated as unset Adds 14 tests across: - TestResolveHermesUidGid (7) — env-var parsing - TestChownToHermesUid (5) — chown helper invariants - TestSecureDirChown (2) — end-to-end through _secure_dir Co-authored-by: Cursor <cursoragent@cursor.com>
JoeKowal
pushed a commit
to JoeKowal/hermes-agent
that referenced
this pull request
Jun 4, 2026
NousResearch#34107) (NousResearch#34268) Fixes NousResearch#34107. When Hermes runs in Docker with HERMES_UID=1000 / HERMES_GID=911, the entrypoint chowns the top-level HERMES_HOME once at startup — but subdirectories created at runtime by ensure_hermes_home() (especially for profile namespaces under profiles/<name>/ spawned by kanban workers) were landing as root:root and blocking subsequent uid-mapped worker invocations with: PermissionError: [Errno 13] Permission denied: '/opt/data/profiles/charles/logs/curator' Fix: add _resolve_hermes_uid_gid + _chown_to_hermes_uid helpers that read the env vars and apply chown after mkdir. Invoke from _secure_dir which already runs after every directory creation in the home-init path, so all newly-created subdirs (including the profile namespaces) get the right ownership. Safety properties: - No-op when HERMES_UID/HERMES_GID unset (the dominant non-Docker path) - No-op on Windows (os.chown doesn't exist; AttributeError swallowed) - No-op when running as non-root (EPERM swallowed — the entrypoint's startup chown -R picks it up on next restart, and in most cases the dir was already correctly-owned by the calling user) - Uses -1 sentinel for missing field so only the set value applies - Empty-string env vars treated as unset Adds 14 tests across: - TestResolveHermesUidGid (7) — env-var parsing - TestChownToHermesUid (5) — chown helper invariants - TestSecureDirChown (2) — end-to-end through _secure_dir Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Fixes #34107.
Problem
When Hermes runs in Docker with
HERMES_UID=1000/HERMES_GID=911, the entrypoint chowns the top-levelHERMES_HOMEonce at startup. But subdirectories created at runtime byensure_hermes_home()— especially for profile namespaces underprofiles/<name>/spawned by kanban workers — were landing asroot:rootand blocking subsequent uid-mapped worker invocations:Reporter's workaround was
chown -Rafter every container restart. Not suitable for production.Fix
Two new helpers and one
_secure_dirintegration:Hook
_chown_to_hermes_uidinto_secure_dirso it runs after every directory creation in the home-init path.ensure_hermes_homealready calls_secure_dirfor every subdir it makes, so all newly-created subdirs (including the profile namespaces created by kanban workers) get the right ownership for free.Safety properties
HERMES_UID/HERMES_GIDunset (non-Docker)os.chown)HERMES_UIDset-1for gid (POSIX 'don't change')Tests
14 new tests in
tests/hermes_cli/test_ensure_hermes_home_uid_34107.py:TestResolveHermesUidGid(7) — env-var parsing across all the edge cases aboveTestChownToHermesUid(5) — chown helper invariants (calls, EPERM swallow, AttributeError swallow, no-op when unset, -1 sentinel)TestSecureDirChown(2) — end-to-end:_secure_dirinvokes chown only when env is setVerified no regression in the broader config test suite:
Credit to @swarthyplacebo for the precise reproduction + impact analysis.
Co-authored-by: Cursor cursoragent@cursor.com