|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to sigil are documented here. The project follows |
| 4 | +[Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
| 5 | + |
| 6 | +## [0.8.1] — 2026-04-30 |
| 7 | + |
| 8 | +Audit-driven hardening release. Closes 26 of 33 findings from the |
| 9 | +2026-04-30 14-perspective audit of the repository (`audit/2026-04-30/`). |
| 10 | +No public-API changes. Two findings (cert-pinning enforcement, no_std |
| 11 | +verifier) are deferred to issue #95 and issue #79 respectively. |
| 12 | + |
| 13 | +### Security |
| 14 | + |
| 15 | +- **JWT algorithm-confusion hardening** (audit C-6). The OIDC parser now |
| 16 | + validates the JWT `alg` field against an allowlist of asymmetric |
| 17 | + algorithms (RS256/384/512, ES256/384/512) **before** any payload claim |
| 18 | + is parsed. `none` and HMAC variants (`HS256/384/512`) are rejected |
| 19 | + outright. Closes a textbook algorithm-confusion path where forged |
| 20 | + tokens could be trusted by `parse_issuer()` / `parse_identity()`. |
| 21 | +- **OIDC issuer-validation env var clarified** (audit H-4). The |
| 22 | + `WSC_EXPECTED_OIDC_ISSUER` env var no longer treats an empty value as |
| 23 | + "disable validation". Disabling validation now requires an explicit |
| 24 | + `WSC_DISABLE_OIDC_ISSUER_CHECK=1`. |
| 25 | +- **Rekor SET cache poisoning prevention** (audit H-5). Rekor entries |
| 26 | + with empty `signed_entry_timestamp` or empty `inclusion_proof` are |
| 27 | + now rejected before any cache write, so subsequent verifications |
| 28 | + cannot hit a cache populated by a partial Rekor response. |
| 29 | +- **Single-owner zeroize discipline** (audit M-5, M-6). `OidcToken` is |
| 30 | + no longer `Clone`. JWT payload buffers are wrapped in |
| 31 | + `Zeroizing<String>` so they zero on every return path. |
| 32 | + |
| 33 | +### Hardening |
| 34 | + |
| 35 | +- **Bounded WASM section iteration** (audit H-1). New |
| 36 | + `MAX_SECTIONS = 4096` constant in `src/lib/src/wasm_module/mod.rs` |
| 37 | + caps the parser; `WSError::TooManySections(usize)` returned beyond. |
| 38 | +- **Bounded x509 chain depth** (audit H-2). New |
| 39 | + `MAX_CHAIN_DEPTH = 8` constant gates `verify_cert_chain` in |
| 40 | + `src/lib/src/signature/keyless/format.rs` before x509 / WebPKI |
| 41 | + invocation; `WSError::ChainTooDeep(usize)` returned beyond. |
| 42 | +- **DSSE envelope fuzz target added** (audit H-7). New |
| 43 | + `fuzz/fuzz_targets/fuzz_dsse_envelope.rs` with a parse → serialise → |
| 44 | + re-parse equality oracle, registered in `fuzz/Cargo.toml`. |
| 45 | +- **`PAYLOAD_TYPE_SLSA` mime-type fix** (audit H-6). The constant in |
| 46 | + `src/attestation/src/dsse.rs` is now |
| 47 | + `"application/vnd.slsa.provenance+json"`, no longer colliding with |
| 48 | + `PAYLOAD_TYPE_INTOTO`. |
| 49 | + |
| 50 | +### Honesty |
| 51 | + |
| 52 | +- **Verus `theorem_*` admits relabelled** (audit C-1). Verus functions |
| 53 | + ending in `assume(false)` in `src/lib/src/verus_proofs/dsse_proofs.rs` |
| 54 | + and `merkle_proofs.rs` are now annotated as **SPECIFICATION ONLY** |
| 55 | + with explicit doc-comments stating the open proof obligation. No |
| 56 | + proof was discharged in this release; the labelling is now honest. |
| 57 | +- **Lean status table corrected** (audit C-2). `lean/Ed25519.lean` |
| 58 | + status table at the top of the file matches the proof bodies. |
| 59 | + `verification_equation_complete` and `basepoint_prime_order` are |
| 60 | + marked `sorry` / open. `verification_equation_sound` (which IS |
| 61 | + proved) is unchanged. |
| 62 | +- **Rocq pipeline status clarified** (audit C-3). New |
| 63 | + `verification/rocq/README.md` states the directory holds Rust |
| 64 | + extraction stubs only; no `.v` files have been written. |
| 65 | +- **Phantom DO-178C / ISO 26262 trace claims softened** (audit L-3). |
| 66 | + `SECURITY.md` now distinguishes between modelled compliance frames |
| 67 | + (ISO/SAE 21434, IEC 62443, CRA, UNECE R155-156) and aspirational ones |
| 68 | + (DO-178C, ISO 26262). |
| 69 | +- **Artifact `implementation-status` field added** (audit L-4). Sample |
| 70 | + of 7 `approved`-status SC/CCs now carry `implementation-status: |
| 71 | + design-only` (e.g. SC-26 SCT cryptographic verification). |
| 72 | + |
| 73 | +### CI / Build |
| 74 | + |
| 75 | +- **Bazel CI now runs `bazel test //...`** (audit C-7). Previously |
| 76 | + only `bazel build //...` was invoked, so Bazel-side test failures |
| 77 | + could merge undetected. |
| 78 | +- **`continue-on-error` removed from formal-verification jobs that |
| 79 | + pass** (audit C-7). The Rocq job retains `continue-on-error` with a |
| 80 | + `# WIP — see audit C-3` comment because the directory is a stub. |
| 81 | +- **Path filters added to `rust.yml`** (audit M-9). Doc-only changes |
| 82 | + no longer fire the cross-OS cargo + bazel matrix. |
| 83 | +- **Memory-profile and TPM2 tests gated to `workflow_dispatch` + |
| 84 | + nightly** (audit M-8). Removes per-PR cost of two expensive jobs. |
| 85 | +- **`@main` action references pinned** (audit M-7). |
| 86 | + `pulseengine/rivet/.github/actions/compliance` now pinned to |
| 87 | + `@v0.6.0`. |
| 88 | +- **Crate-version drift collapsed to a single source** (audit H-8). |
| 89 | + `Cargo.toml`, `MODULE.bazel`, and `src/cli/BUILD.bazel` all read the |
| 90 | + same version (this release: 0.8.1). Comments cross-reference |
| 91 | + `Cargo.toml` as canonical. |
| 92 | +- **Dual-publish race fixed** (audit H-9). `release.yml`'s duplicate |
| 93 | + `publish-crates` job removed; `publish-to-crates-io.yml` is now the |
| 94 | + sole crates.io publisher with the `pulseengine/sigil` repo guard. |
| 95 | +- **Dockerfile.bytehound disclaimer** (audit L-6). Top-of-file note |
| 96 | + declares the image is intentionally outside the Nix flake's |
| 97 | + hermeticity guarantee. |
| 98 | + |
| 99 | +### Developer experience |
| 100 | + |
| 101 | +- **`build.rs` declares the `kani` cfg** (audit M-10). Five |
| 102 | + `unexpected cfg condition` warnings on every `cargo build` are |
| 103 | + gone. |
| 104 | +- **Stale `wasmsign2` references in user-facing docs corrected** |
| 105 | + (audit L-1). `docs/keyless.md` and `docs/bazel-build-guide.md` now |
| 106 | + use the current binary name and repo URL. |
| 107 | +- **README gained a "Quick Try" section** (audit L-2). Eight-byte |
| 108 | + WASM round-trip lets new contributors validate their build without |
| 109 | + any artefact. |
| 110 | +- **CLI verb normalised** (audit M-11). `verify_matrix` → |
| 111 | + `verify-matrix` for tab-completion consistency. |
| 112 | +- **CLI help gained `EXAMPLES:` blocks** (audit L-5). `keygen`, |
| 113 | + `sign`, `verify`, and `bundle create` show invocation patterns |
| 114 | + inline. |
| 115 | + |
| 116 | +### Deferred |
| 117 | + |
| 118 | +The following audit findings require larger work and are tracked |
| 119 | +separately: |
| 120 | + |
| 121 | +- **C-4 — enforce SPKI cert pinning** at the TLS layer. Requires |
| 122 | + migrating off `ureq` to a client that exposes |
| 123 | + `rustls::ServerCertVerifier`. Tracked at issue #95. |
| 124 | +- **M-1 / M-2 / M-3 / M-4 — `no_std` verifier path** for embedded |
| 125 | + / cFS targets. Tracked at issue #79 (per-component cFS attestation) |
| 126 | + with audit context appended in the comments. |
| 127 | + |
| 128 | +### Contributors |
| 129 | + |
| 130 | +This release was driven by a parallel multi-agent audit + fix-PR |
| 131 | +pipeline. PRs in this release: #96 (STPA-Sec / docs), #97 (hygiene), |
| 132 | +#98 (parser hardness), #99 (formal-verif honesty + CI), #100 |
| 133 | +(keyless / OIDC hardening). |
| 134 | + |
| 135 | +[0.8.1]: https://github.com/pulseengine/sigil/compare/v0.8.0...v0.8.1 |
0 commit comments