Security Threat Model & Signed Releases
Status: Partially implemented — signing/release artifacts have shipped in dev releases, and operator artifact verification passed end to end against jackin-dev-v0.1.13 on 2026-07-04; clean-cache capsule download verification and residual Fulcio-chain hardening remain
Problem
jackin❯ closed two credibility gaps with this work:
- Undocumented security implementation. Symlink rejection in
crates/jackin-instance/src/auth.rs,shellfirmandtirithin the construct image, and the YOLO-flag contract indocker/runtime/entrypoint.shwere enforced in code but invisible to operators, role authors, and contributors who reason about the trust boundary. - Unsigned capsule binary.
jackin-capsuleis downloaded into every container at runtime (crates/jackin-image/src/capsule_binary.rs) and was verified by SHA256 only — no signing, no SLSA provenance, no SBOM. A tampered artifact matching the expected SHA256 would go undetected.
Shipped
All implementation landed on this branch. Operator and contributor detail now live in canonical docs, not here:
- Security implementation — threat model, the six
auth.rssecurity functions,shellfirm/tirithrationale, and the YOLO-flag contract for all five agents → /reference/security-implementation/. - Release verification — cosign keyless verification, SLSA provenance, SBOM inspection, and capsule-manifest auditing → /getting-started/verifying-releases/.
- CI signing — cosign
sign-blobbundles,actions/attest-build-provenanceSLSA attestations, andsyftCycloneDX SBOMs for every archive in.github/workflows/release.ymland.github/workflows/preview.yml; the capsule build jobs additionally produce a signedcapsule-manifest.json+capsule-manifest.json.bundle. - Operator artifact verification —
cargo xtask release-verify <archive>.tar.gzchecks the published.sha256, cosign bundle identity/issuer, GitHub artifact attestation, and SBOM JSON. The gate passed againstjackin-dev-v0.1.13(jackin-dev-0.1.13-aarch64-unknown-linux-gnu.tar.gz, published 2026-07-02) on 2026-07-04, and a tampered archive copy failed closed at the digest check. - In-process verification —
fetch_and_verify_manifestincrates/jackin-image/src/capsule_binary.rsverifies the cosign bundle (embedded Sigstore production Rekor key viaManualTrustRoot, no TUF network call), pins the certificate SAN to therelease.yml/preview.ymlsigning workflows, and hard-aborts on any failure — no warn-and-continue. TheJACKIN_CAPSULE_BINoverride and Homebrew-packaged binaries bypass the download path unchanged.
Remaining
-
Clean-cache capsule download gate. Dev releases now exist after the signing workflows landed (latest observed:
jackin-dev-v0.1.13, 2026-07-02). Operator archive verification is proven bycargo xtask release-verify, but the remaining in-process gate is a clean-cache capsule download against one of those signed bundles; unit and integration tests still bypass it (cfg!(test)stub plusJACKIN_CAPSULE_BIN). Confirm before treating the download path as proven:rm -rf ~/.jackin/cache/jackin-capsule/ unset JACKIN_CAPSULE_BIN cargo run --bin jackin -- console --debug # expect: "capsule manifest signature verified"If verification regresses,
JACKIN_CAPSULE_BIN=/path/to/jackin-capsuleunblocks launches while a fix lands. -
Rekor key rotation. The embedded
SIGSTORE_REKOR_PUB_KEY_B64incrates/jackin-image/src/capsule_binary.rsmust be updated when Sigstore rotates the production Rekor signing key (announced at blog.sigstore.dev). -
Fulcio certificate chain not validated (known residual).
Client::verify_blobin sigstore-rs 0.14 does not chain-verify the certificate to a Fulcio root or check the OIDC issuer. The Rekor body cross-check (verify_rekor_body_binds_bundle) now closes the field-swap attack (an attacker can no longer keep a legitimate Rekor SET and substitute a self-signed cert, because the body hash and cert fields are verified against each other). However, an attacker who can forge a Rekor log entry (extremely high bar — requires the Rekor private key) or who obtains a Fulcio-issued cert with a matching SAN through any other means would still pass all checks. Full closure requires adding Fulcio root cert pool validation usingx509-cert's chain-building API against embedded Fulcio intermediate and root certs, or upgrading to a higher-level sigstore-rs API that includes the full keyless verification contract.
This item retires once the capsule download path has been clean-cache verified end to end and the remaining verification residuals are either fixed or explicitly accepted.
Non-goals
- No hostile multi-tenant safety claim from Docker hardening alone — that is Docker runtime hardening contract scope.
- No microVM replacement — smolvm backend research tracks that separately.
- No retroactive signing of historical releases — provenance starts from the first workflow that includes signing.
- No source-level (
cargo-cyclonedx) SBOM —syft scanon the binary archive is sufficient for the supply chain transparency goal here.
Related roadmap items
| Item | Relationship |
|---|---|
| Docker runtime hardening contract | Container escape is out of scope for this item; Docker hardening tracks that |
| Process-level sandboxing | Per-operation isolation inside the container; complementary to the threat model |
| smolvm backend research | Future microVM backend that addresses the shared-kernel residual risk |
| Network egress policy | Network exfiltration threat is tracked there |
| Container credential exposure | Credential safety beyond symlink rejection |
| Rust CI tooling | CI workflow patterns that signing and SBOM generation follow |
Related files
crates/jackin-image/src/capsule_binary.rs—fetch_and_verify_manifest, embedded Rekor key, SAN identity check.github/workflows/release.yml— tagged-release signing + capsule manifest.github/workflows/preview.yml— rolling-preview signing + capsule manifest- /reference/security-implementation/ — contributor-facing security internals
- /getting-started/verifying-releases/ — operator-facing verification guide