André Ataíde
July 17, 2026

Wardex v2.3.0: Deterministic Canonicalization and 3CP Provenance Attestation

CBOR deterministic encoding replaces ad-hoc serialization across the signing path; CDDL schemas define the canonical envelopes; and tool provenance becomes a cryptographically-bound, anchorable attestation.


Context

Wardex v2.2 introduced the Configuration Provenance Link (CPL) — a SHA-256 hash binding each gate decision to the configuration in effect. The hashing was correct, but the canonicalization layer was fragile: it relied on JSON marshalling with implicit key ordering and was vulnerable to edge cases (float/int representation, unicode normalization, map key ordering) that produce different bytes for the same semantic content across implementations or Go versions.

v2.3.0 replaces the entire canonicalization substrate with CBOR Core Deterministic Encoding (RFC 8949 §4.2.3) and formalizes every envelope with CDDL schemas (RFC 8610). On top of that foundation, it ships the 3CP Tool Provenance Attestation — a signed, anchorable proof of which tool produced which artifact.


CBOR Deterministic Canonicalization

internal/cpl/canonicalConfig() now serializes configuration via github.com/fxamacker/cbor/v2 in deterministic mode instead of encoding/json. The same logical config always produces byte-identical signed bytes across any CBOR implementation and platform.

Breaking changes


CDDL Schemas

The spec/cddl/ directory defines three formal schemas serving as the source of truth for serialization and interoperability:

SchemaDefines
cpl-entry.cddlCPL audit log entries
wexstate.cddlWexState sealed config envelopes
tool-attestation.cddl3CP tool provenance attestations

These are both design artifacts and the foundation for conformance testing — any implementation producing bytes that fail CDDL validation is, by definition, non-conformant.


3CP Tool Provenance Attestation

The new pkg/attest/ package defines 3CP tool provenance envelopes with CBOR deterministic signing and verification. A ToolAttestation carries tool identity, input/output hashes, config hash, and timestamp; a SignedAttestation wraps it with an Ed25519 signature.

The Anchorer interface abstracts the 3CP backend — Gleipnir is one backend among equals (embedded, gRPC, noop). The attestation format (spec/cddl/tool-attestation.cddl) is the canonical 3CP envelope, independent of any specific implementation.

New commands and flags:

Command / FlagDescription
wardex provenance attestCreate and sign a 3CP tool attestation (CBOR deterministic), with --submit to anchor it.
--attestFlag on the converters (grype, sbom, kev) to emit a signed attestation alongside the conversion.
Anchorer.SubmitAttested()Anchors hash + CBOR attestation, upgrading converted_by from a best-effort string to a verifiable cryptographically-bound envelope.

Why this matters

Before v2.3.0, the converted_by field in evidence envelopes was an unverifiable string. A converted SBOM claimed it came from wardex convert grype, but nothing enforced it. The 3CP attestation makes that claim cryptographically non-repudiable: the tool identity, input hash, and output hash are bound to an Ed25519 signature and anchored to an immutable consensus log.


Architectural Decisions

Deterministic encoding is not a nice-to-have for a compliance tool — it is the precondition for reproducible signatures. If the same config can produce two different signed bytes, the signature proves nothing about the config. v2.3.0 makes the signing path reproducible by construction.


Upgrade

go install github.com/had-nu/wardex/v2@latest

Checksums and SBOMs are available in the GitHub Release. Note the config_hash migration step above if you verify historical audit logs.