Bound Hermes Atlas pull request authority #14

Merged
bstein merged 13 commits from feature/hermes-safe-gitea-pr-client into main 2026-08-18 03:17:20 +00:00

Fifth independent-review repair for the least-authority Hermes Atlas pull-request client.

This revision adds bounded structured screening for multiline JSON and YAML credential-shaped input, including escaped JSON keys and malformed key encodings. It also caps repository, title, body, and base/head ref characters and UTF-8 bytes before Git, request construction, or network access. The helper remains limited to explicit metadata reads and verified same-repository draft creation; human review is required and mutation operations remain unavailable.

Validation:

  • focused Hermes PR client/runtime tests: 338 passed
  • complete testing suite: 607 passed
  • opener/Git spy regressions: 174 passed
  • Ruff and formatting checks: passed
  • Python compile: passed
  • Hermes render: 21,586 lines
  • client dry-run: 114 resources
  • read and draft-create CLI dry runs: passed
  • staged secret and diff scans: passed

Exact head: 8b5f26b273

Fifth independent-review repair for the least-authority Hermes Atlas pull-request client. This revision adds bounded structured screening for multiline JSON and YAML credential-shaped input, including escaped JSON keys and malformed key encodings. It also caps repository, title, body, and base/head ref characters and UTF-8 bytes before Git, request construction, or network access. The helper remains limited to explicit metadata reads and verified same-repository draft creation; human review is required and mutation operations remain unavailable. Validation: - focused Hermes PR client/runtime tests: 338 passed - complete testing suite: 607 passed - opener/Git spy regressions: 174 passed - Ruff and formatting checks: passed - Python compile: passed - Hermes render: 21,586 lines - client dry-run: 114 resources - read and draft-create CLI dry runs: passed - staged secret and diff scans: passed Exact head: 8b5f26b2731e738301fddaf67f343449d5a25e01
hermes-automation added 1 commit 2026-08-16 22:56:05 +00:00
bstein added 1 commit 2026-08-16 23:19:05 +00:00
bstein added 1 commit 2026-08-16 23:21:18 +00:00
bstein added 1 commit 2026-08-16 23:41:36 +00:00
bstein force-pushed feature/hermes-safe-gitea-pr-client from f917136e08 to c8ccc8f249 2026-08-16 23:56:31 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from c8ccc8f249 to f416b8a47c 2026-08-17 00:17:52 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from f416b8a47c to 8b5f26b273 2026-08-17 00:40:13 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from 8b5f26b273 to 86e9fbbfec 2026-08-17 02:12:54 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from 86e9fbbfec to 6715e1f023 2026-08-17 05:00:57 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from 6715e1f023 to 3fec1cd5dc 2026-08-17 05:03:31 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from 3fec1cd5dc to 3cd8a17e77 2026-08-17 09:36:56 +00:00 Compare
bstein force-pushed feature/hermes-safe-gitea-pr-client from 3cd8a17e77 to 8c6e3acdac 2026-08-17 10:58:54 +00:00 Compare
bstein added 5 commits 2026-08-17 18:15:59 +00:00
Replace the reimplemented gobwas/glob matcher with exact-literal rule
matching that fails closed on any special or malformed pattern, accepts
legacy zero priorities, and rejects duplicate primary-branch rules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Run every Gitea API and broker control exchange inside a killable helper
process whose connect, send, and read share one absolute wall-clock
deadline, and add a watchdog that force-closes streaming connections at
expiry. Redirects are rejected before authentication headers can move.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Inflate every receive-pack object under strict pack, size, and checksum
bounds, resolve deltas against in-pack bases only, and scan the real
decompressed payloads for runtime-token forms, private keys, SSH key
material, and known provider token formats. Thin packs are rejected so
no pushed content escapes the scan, and upstream Git exchanges now run
under one absolute stream deadline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expand sudoers User_Alias chains so aliases, wildcards, netgroups, and
undefined names cannot smuggle authority to the Hermes account, and
require polkit grants to scope through exact literal identity
comparisons: computed strings, bracket lookups, subject aliasing,
operator-built values, and unconditional or wildcard grants fail closed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bstein added 3 commits 2026-08-17 23:37:41 +00:00
A regex literal embedding a quote desynced the string tokenizer and
swallowed an unconditional Result.YES, so the grant read as unscoped and
slipped past the literal-identity check. Fail closed on any slash outside
a string or comment; neither regex nor division belongs in an
identity-scoped grant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A quoted, space-bearing #include path failed the include regex and fell
through to the comment branch, leaving a second authority file
unenumerated. Detect any include directive before the comment rule and
fail closed on every form except the exact bare includedir into the
audited /etc/sudoers.d.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The watchdog can only close a live socket, but getaddrinfo runs before
any socket exists and ignores socket timeouts, so a slow resolver
outlived the stream deadline. Resolve under the same absolute deadline
in a joinable worker before the real connect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bstein added 1 commit 2026-08-18 00:07:12 +00:00
Resolve 8 conflicts, uniting #16's daemonless image-release lane with
#14's SCM broker + node-audit boundary. Nothing dropped from either side.

- quality_coverage.py / test_quality_coverage_helpers.py: take main's
  dual-metric gate (line+branch enforced per file at minimum_percent);
  drop #14's now-dead branch_tracked_files/minimum_branch_percent keys.
- quality_contract.json: union all lists (managed_modules, lint_paths,
  coverage_sources, tracked_files, hygiene globs) so #14's scm-broker,
  git_pack_objects, receive_pack_scan, deadline_http and node_polkit_audit
  are branch-checked alongside #16's image-builder modules.
- Vault auth (vault_k8s_auth_configure.sh): coexist both role sets. Keep
  #16's hermes-switchyard split + hermes-jenkins-token-seed; keep #14's
  hermes-scm-broker role. Preserve #14's security property: hermes-agent
  no longer holds developer-gitea (broker role carries it).
- agent-deployment.yaml / stage_runtime_access.py: keep #16's
  jenkins-image-build-token injection/staging; keep #14's removal of the
  agent's gitea-token/gitea-username.
- Bump vault-k8s-auth-hermes job -9 -> -10 (and its health check + test)
  so the merged auth config re-applies over any -9 already in-cluster.
- flux hermes dependsOn: union jenkins + hermes-scm-broker + observer-rbac.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bstein changed title from WIP: Bound Hermes Atlas pull request authority to Bound Hermes Atlas pull request authority 2026-08-18 03:17:15 +00:00
bstein merged commit be1ff33d4b into main 2026-08-18 03:17:20 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: titan/atlas-iac#14
No description provided.