Skip to content

Harden hosted Docker install tree against self-modification - #47490

Merged
benbarclay merged 2 commits into
NousResearch:mainfrom
shannonsands:shannonsands/hosted-readonly-install-guard
Jun 17, 2026
Merged

Harden hosted Docker install tree against self-modification#47490
benbarclay merged 2 commits into
NousResearch:mainfrom
shannonsands:shannonsands/hosted-readonly-install-guard

Conversation

@shannonsands

Copy link
Copy Markdown
Contributor

Summary

  • make the Docker image keep /opt/hermes root-owned and non-writable at runtime
  • keep writable hosted/container state under /opt/data via HERMES_WRITE_SAFE_ROOT=/opt/data
  • disable runtime lazy installs and Python bytecode writes inside the immutable install tree
  • update stage2 ownership repair so it no longer chowns source, venv, TUI bundle, or node_modules back to the hermes user
  • replace old chown-contract tests with immutable-install contract and Docker smoke coverage

Why

NS-492 tracks hosted agents being able to self-modify installed Hermes source and brick the gateway, with no easy SSH recovery path. This makes the published container enforce the intended boundary in the filesystem: agent-writable data lives under /opt/data; installed code and dependencies stay immutable to the runtime user.

Validation

  • docker build -t hermes-ns492-readonly-install:test .
  • HERMES_TEST_IMAGE=hermes-ns492-readonly-install:test python -m pytest tests/docker/test_immutable_install_permissions.py -q (2 passed)
  • HERMES_TEST_IMAGE=hermes-ns492-readonly-install:test python -m pytest tests/docker/test_main_invocation.py tests/docker/test_tui_prebuilt_bundle.py tests/docker/test_docker_exec_privilege_drop.py -q (18 passed)
  • HERMES_TEST_IMAGE=hermes-ns492-readonly-install:test python -m pytest tests/docker/test_dashboard.py -q (8 passed)
  • python -m pytest tests/tools/test_dockerfile_immutable_install.py tests/tools/test_dockerfile_node_modules_perms.py tests/tools/test_stage2_hook_immutable_install.py tests/tools/test_lazy_deps.py::TestSecurityGating -q (11 passed)
  • python -m pytest tests/tools/test_file_write_safety.py tests/tools/test_write_deny.py -q (49 passed)
  • python -m pytest tests/tools/test_stage2_hook_toplevel_chown.py tests/tools/test_stage2_hook_user_flag_guard.py tests/tools/test_stage2_hook_log_dir_seed.py tests/tools/test_stage2_hook_gateway_bootstrap_state.py tests/tools/test_dockerfile_immutable_install.py tests/tools/test_dockerfile_node_modules_perms.py tests/tools/test_stage2_hook_immutable_install.py -q (25 passed)
  • git diff --check

Linear: https://linear.app/nousresearch/issue/NS-492/agent-self-modification-can-break-the-installation

@shannonsands
shannonsands requested a review from benbarclay June 16, 2026 22:52
@alt-glitch alt-glitch added type/security Security vulnerability or hardening area/docker Docker image, Compose, packaging backend/docker Docker container execution P2 Medium — degraded but workaround exists labels Jun 16, 2026
@benbarclay

Copy link
Copy Markdown
Collaborator

The immutability boundary is currently undocumented — docker.md repeatedly says /opt/data is "the single source of truth for all state" but never says /opt/hermes is now read-only to the agent. Concretely:

Doc Gap Suggested change
website/docs/user-guide/docker.md No mention that /opt/hermes is root-owned & non-writable to the hermes user on hosted images. Operators who docker exec to hand-edit installed source (or who relied on the old writable .venv/node_modules for runtime pip/npm) will hit silent Permission denied. Add a short "Immutable install tree" subsection near the /opt/data "source of truth" block (~line 155): state that /opt/hermes is read-only to the runtime user; all mutable state (config, skills, memories, sessions, logs, dashboard uploads) lives under /opt/data; runtime lazy installs and .pyc writes are disabled; root/HERMES_DOCKER_EXEC_AS_ROOT=1 is the repair path.
website/docs/user-guide/docker.md (self-improvement framing) The hosted self-improvement policy is implicit. Worth stating explicitly. One line: "On hosted/published images, the agent's self-improvement is scoped to skills, memory, and config under /opt/data; the installed core source under /opt/hermes is immutable — core changes are made via PRs to the repo, not live edits."
website/docs/reference/environment-variables.md HERMES_DISABLE_LAZY_INSTALLS is absent from the table (only HERMES_WRITE_SAFE_ROOT is there, at line 591). Add a row. It's an internal bridge var set by the image, not user-facing config — document it as "set automatically in the official Docker image; the user-facing equivalent is security.allow_lazy_installs: false in config.yaml." Don't tell users to set it in .env.

@benbarclay benbarclay left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see the docs updated as per the comment, but otherwise I'm happy for this to be shipped

@shannonsands
shannonsands marked this pull request as ready for review June 17, 2026 06:03
@benbarclay
benbarclay merged commit 6092be4 into NousResearch:main Jun 17, 2026
35 checks passed
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…arch#47490)

* Harden hosted Docker install tree

* Document hosted Docker immutable install tree
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…arch#47490)

* Harden hosted Docker install tree

* Document hosted Docker immutable install tree
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…arch#47490)

* Harden hosted Docker install tree

* Document hosted Docker immutable install tree
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…arch#47490)

* Harden hosted Docker install tree

* Document hosted Docker immutable install tree
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…arch#47490)

* Harden hosted Docker install tree

* Document hosted Docker immutable install tree
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docker Docker image, Compose, packaging backend/docker Docker container execution P2 Medium — degraded but workaround exists type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants