Skip to content

fix(startup): defer sealed key until startup checks pass - #840

Open
dinakarjs wants to merge 1 commit into
agentrust-io:mainfrom
dinakarjs:fix/startup-seal-after-validation
Open

dinakarjs wants to merge 1 commit into
agentrust-io:mainfrom
dinakarjs:fix/startup-seal-after-validation

Conversation

@dinakarjs

@dinakarjs dinakarjs commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

A refused first start could persist a sealed signing key bound to rejected inputs, causing the corrected configuration to fail on restart. Provisioning/unseal now occurs after all run_startup checks. Earlier public-key discovery, measurement and attestation remain necessary.

Current head: 0beb5a3434c3dffa9c77f11b61ba6bea1e2ccd69. This is our second active effort, ready for independent review under #782. Rajnish retains the landing decision.

All six hosted Linux/Windows Python 3.11–3.13 test jobs and governance pass. Each Linux job passed 2,778 tests with 29 skips and three subtests, including four new swtpm refusal/recovery cases. Eight software controls fail behaviorally on original startup.py. Documentation, CodeQL, confinement, Docker and bounded fuzz checks also pass; remote and validated local trees match.

Limits: measurement, locking and other startup effects still occur earlier; this is not transactional startup or an atomic measured-policy snapshot. Port binding occurs after return and remains outside this boundary. Existing bad-digest stores may need documented reseal. Simulator evidence does not establish production recovery.

Decision: independent review of this head; requested reviewers now appear in current metadata. No self-approval or merge.

Prepared with OpenAI Codex; DCO-signed code history retained. This description update changes no source or review head.

Historical description and validation snapshots (superseded by current status above)

What and why

A first start can persist a sealed signing key before later validation refuses the configuration. Correcting that configuration then changes the measured digest and prevents the next start from unsealing. Defer provisioning/unseal until every check in run_startup succeeds, while keeping public-key discovery, measurement and attestation in their existing order.

Refs #782. Extends our earlier dinakarjs#3 policy-first candidate using Yatsuiii's additional reproduction. #779 has merged; this is the proposed upstream home for the revised correction. Rajnish retains issue ownership and the landing decision. The separate lifecycle controls in dinakarjs#5 are not bundled here.

Security impact and compatibility

Invalid policy, identity, audit-store and session-store inputs cannot trigger new key provisioning through this path. Sealing remains opt-in; ephemeral-key behavior and existing-store mismatch refusal remain. Earlier validation errors now take precedence over sealing errors; two simulator expectations are updated accordingly. This also carries #782's empty-owner-password warning and configuration-digest wording correction.

Measurement/NV extension, store locking and other startup side effects still occur before the seal point. This is not transactional startup or atomic measurement/loaded-policy binding. The caller binds the network port after return, so a later bind failure can still leave a provisioned key. Existing bad-digest stores may be recovered by the documented reseal operation where appropriate; rotation is not asserted to be necessary.

Validation

Validated tree 44a4ce6b56dfbc537211d9aab86bf4236dd7d010, published as 0beb5a3434c3dffa9c77f11b61ba6bea1e2ccd69, Linux/Python 3.12.14:

  • Unchanged hash-required dev lock, followed by editable installation with --no-deps; pip check reports no broken requirements.
  • CI's unit/conformance/integration/confinement selection: 2,725 passed, 74 skipped before adding four simulator-only cases. Initial run had ten inherited SOCKS-proxy setup failures; rerun with upper/lowercase proxy variables removed passed.
  • Final affected selection: 37 passed, 19 skipped (all 19 swtpm startup cases skipped). No local TPM/swtpm execution is claimed.
  • Eight new software controls exercise real policy/config validation with synthetic TPM seams; reverting only startup.py produces 8 behavioral failures, then source restored. Late refusal cases each have a corrected-start positive twin.
  • Four new simulator cases check absent persisted sealed store after policy/identity/audit/session failure and provisioning after correction. They subsequently passed on all three hosted Linux Python versions, as recorded below.
  • Full-source Ruff, mypy (64 files), configured Bandit and whitespace checks pass.

Local native dependency setup was unavailable; the hosted validation update below supplies the subsequent simulator evidence. No hardware, recovery-in-production or merge-completion claim.

Hosted validation update

CI run 42487782062 passed all six Linux/Windows Python 3.11/3.12/3.13 test jobs and governance on the published head. Each Linux job reports 2,778 passed / 29 skipped / 3 subtests; Python 3.12 Windows reports 2,706 passed / 97 skipped / 3 subtests. Linux logs explicitly show all four new swtpm refusal/recovery cases and both changed error expectations passing. This resolves the local simulator execution gap; it is simulator evidence, not host-TPM or production recovery evidence.

Documentation, CodeQL, confinement-reference and Docker workflow checks also pass. ClusterFuzzLite also passed; the job reports no reportable crashes in its bounded run. Ready for independent owner/maintainer review; Rajnish's landing decision remains. Reviewer-assignment API returned 403, so the handoff is recorded in #782 rather than claiming a formal assignment.

DCO / assistance

  • Commit signed off under the Developer Certificate of Origin.
  • Prepared with OpenAI Codex; no independent approval of our own work claimed.

Extend the agentrust-io#782 policy-first repair to identity, audit and session-store refusals. Preserve early public-key measurement and document the later port-bind boundary. Add paired refusal/recovery controls and simulator cases.

Prepared with OpenAI Codex. Refs agentrust-io#782.

Signed-off-by: Srinivasa Dinakar Jainti <dinakarjs@gmail.com>
@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential LOW
Overall MEDIUM

Automated check by AgenTrust Contributor Check.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@dinakarjs
dinakarjs marked this pull request as ready for review November 8, 2026 14:06

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants