Security hardening (v0.1 → v0.2): scoped auth, non-root container, verified supply chain#1
Open
mikeumus wants to merge 4 commits into
Open
Security hardening (v0.1 → v0.2): scoped auth, non-root container, verified supply chain#1mikeumus wants to merge 4 commits into
mikeumus wants to merge 4 commits into
Conversation
Replace the single optional bearer token with a two-level model: - chat level (API_TOKEN) gates /v1/* and /api/* baseline - admin level (ADMIN_TOKEN, falls back to API_TOKEN) gates the destructive/introspective control routes (restart, stop, logs) Auth now fails closed: with no token configured, protected routes return 503 unless ALLOW_UNAUTHENTICATED=true (explicit dev opt-in). Tokens are compared in constant time via SHA-256 digests. Make HERMES_GATEWAY_TOKEN mandatory (requireGatewayToken) so the Worker never sends an empty bearer, and add optional per-client rate limiting (CHAT_RATE_LIMITER / ADMIN_RATE_LIMITER, no-op when unbound). The dashboard proxy strips the Worker's own Authorization header and hw_token cookie before forwarding to the container. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Run the Hermes gateway + dashboard as an unprivileged `hermes` user (privileges dropped via gosu after the root-run startup writes config). - Fetch the Node.js tarball over verified TLS (drop `curl -k`) and check it against a pinned per-arch SHA-256. - Remove the silent unpinned fallbacks on the Hermes git clone and the [web,pty] install; the build now fails hard on a bad ref. Add an optional HERMES_COMMIT build-arg to pin an immutable commit. - Tighten secret perms: ~/.hermes is 0700, .env is 0600 under umask 077; require HERMES_GATEWAY_TOKEN (no `change-me` default). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- First test suite (vitest): 23 tests covering constant-time compare, token parsing, fail-closed behavior, and chat-vs-admin privilege separation. - Commit package-lock.json; CI uses `npm ci`. - Pin all GitHub Actions to commit SHAs; add `permissions: contents: read`, an `npm test` step, and a production-tree `npm audit` gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- README + SECURITY.md describe the fail-closed two-token model, the mandatory gateway secret, non-root agent, and rate limiting. - Correct docs/custom-domain.md, which described a dashboard gateway-token auto-injection the code never performed. - Add HARDENING.md mapping each change to its rationale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
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.
Internal hardening PR against our fork (not upstream). This is the integration base for embedding Hermes-on-Cloudflare into the Divinci app, and the source branch for a later coordinated upstream contribution (handled via PlaydaDev's private security-disclosure process, per their SECURITY.md).
What changed
Turns the audited v0.1 into a hardened v0.2. Full mapping in
HARDENING.md.Auth — two-level tokens (
API_TOKENchat /ADMIN_TOKENadmin), fail-closed (503 when unset unlessALLOW_UNAUTHENTICATED=true), constant-time compare, mandatoryHERMES_GATEWAY_TOKEN, optional rate limiting, proxy strips its own credentials before forwarding.Container — non-root
hermesuser via gosu, Node download over verified TLS with pinned SHA-256, pinned Hermes clone with no silent unpinned fallback, tight secret perms.Supply chain / maturity — SHA-pinned GitHub Actions +
permissions: contents: read, committed lockfile, production-treenpm auditgate, and the first test suite (23 auth tests).Verification
npm run typecheck— cleannpm test— 23/23 passingnpm audit --omit=dev— 0 vulnerabilitiesbash -nverified only; not image-build verified (see caveat below).Needs live-Sandbox validation before we depend on it
The non-root privilege drop assumes the Sandbox control plane launches the startup script as root (so it can chown before dropping to
hermes). On a real deploy, confirm (a) gateway/dashboard run ashermesand can read~/.hermes, and (b)POST /api/instance/restart(execskill -9 1) still works. Details inHARDENING.md.Not for upstream as-is
Per PlaydaDev's SECURITY.md, the vulnerability-class fixes go to them via a private security advisory, not a public PR. This PR stays internal to Divinci-AI.