Bug Description
When nginx (or any web server) serves content from a subdirectory of HERMES_HOME (e.g.
~/.hermes/reports/), the _secure_dir() function in config.py resets ~/.hermes to 0700 on every gateway startup via
ensure_hermes_home(). This removes the execute bit for other users, preventing www-data from traversing into the
directory, resulting in 403 errors.
Steps to Reproduce
Steps to reproduce:
- Configure nginx to serve files from a subdirectory of ~/.hermes/ (e.g. alias /home/user/.hermes/reports/;)
- Set chmod o+x ~/.hermes so nginx can traverse into it
- Restart the hermes-gateway service
- Attempt to access the nginx-served content
Expected Behavior
The web server should continue to be able to serve content from subdirectories of HERMES_HOME after
a gateway restart.
Actual Behavior
_secure_dir() resets ~/.hermes to 0700, removing the other-execute bit. nginx returns 403 Forbidden.
Affected Component
CLI (interactive chat)
Messaging Platform (if gateway-related)
Discord
Operating System
ubuntu 24.04.4 LTS
Python Version
3.12.3
Hermes Version
0.8.0
Relevant Logs / Traceback
No traceback — this is a silent permission change, not a crash. The symptom is nginx returning 403
after gateway restart:
$ ls -lad ~/.hermes
drwx------ 21 x x 4096 Apr 9 23:10 /x/x/.hermes
$ curl -s -o /dev/null -w '%{http_code}' https://x.com/reports/
403
After chmod o+x ~/.hermes:
$ ls -lad ~/.hermes
drwx-----x 21 x x 4096 Apr 9 23:10 /x/x/.hermes
$ curl -s -o /dev/null -w '%{http_code}' https://x/reports/
200
Root Cause Analysis (optional)
_secure_dir() in hermes_cli/config.py unconditionally applies 0o700 to HERMES_HOME and its
subdirectories. It has a carve-out for managed mode (NixOS uses 0o750) but no mechanism for non-managed installs to
preserve the other-execute bit. When any service (nginx, caddy, etc.) needs to traverse HERMES_HOME to reach a served
subdirectory, the blanket 0o700 breaks it on every restart. A possible fix: use 0o701 as the default, or only remove
group/other read+write without touching execute.
Proposed Fix (optional)
In _secure_dir(), change 0o700 to 0o701. This preserves owner-only read/write on HERMES_HOME (configs,
keys, etc. stay protected) while allowing other users to traverse the directory. The execute-only bit on a directory
permits cd-through but not listing contents — web servers can reach explicitly configured subdirectories without
exposing anything else.
Alternatively, a more flexible approach: let users set a custom mode via an env var or config key (e.g.
HERMES_HOME_MODE=0701) so deployments that serve content from subdirectories can opt in without patching source.
Are you willing to submit a PR for this?
Bug Description
When nginx (or any web server) serves content from a subdirectory of HERMES_HOME (e.g.
~/.hermes/reports/), the _secure_dir() function in config.py resets ~/.hermes to 0700 on every gateway startup via
ensure_hermes_home(). This removes the execute bit for other users, preventing www-data from traversing into the
directory, resulting in 403 errors.
Steps to Reproduce
Steps to reproduce:
Expected Behavior
The web server should continue to be able to serve content from subdirectories of HERMES_HOME after
a gateway restart.
Actual Behavior
_secure_dir() resets ~/.hermes to 0700, removing the other-execute bit. nginx returns 403 Forbidden.
Affected Component
CLI (interactive chat)
Messaging Platform (if gateway-related)
Discord
Operating System
ubuntu 24.04.4 LTS
Python Version
3.12.3
Hermes Version
0.8.0
Relevant Logs / Traceback
Root Cause Analysis (optional)
_secure_dir() in hermes_cli/config.py unconditionally applies 0o700 to HERMES_HOME and its
subdirectories. It has a carve-out for managed mode (NixOS uses 0o750) but no mechanism for non-managed installs to
preserve the other-execute bit. When any service (nginx, caddy, etc.) needs to traverse HERMES_HOME to reach a served
subdirectory, the blanket 0o700 breaks it on every restart. A possible fix: use 0o701 as the default, or only remove
group/other read+write without touching execute.
Proposed Fix (optional)
In _secure_dir(), change 0o700 to 0o701. This preserves owner-only read/write on HERMES_HOME (configs,
keys, etc. stay protected) while allowing other users to traverse the directory. The execute-only bit on a directory
permits cd-through but not listing contents — web servers can reach explicitly configured subdirectories without
exposing anything else.
Alternatively, a more flexible approach: let users set a custom mode via an env var or config key (e.g.
HERMES_HOME_MODE=0701) so deployments that serve content from subdirectories can opt in without patching source.
Are you willing to submit a PR for this?