Counter-signed declaration: create, verify, bundle

codafort attest creates and checks the counter-signed declaration of a scan. Creating needs the Verified or Platform plan; checking is free and offline.

The declaration (the coda-attestation/1 artifact) states: this result, at this commit, with this ruleset and this evidence, reached this verdict. Anyone can check it, with no licence.

What it proves and what it does not: it proves the integrity and authorship of the result. It does not prove absence of vulnerabilities and does not replace an independent pentest (Brazilian CMN Res. 5.274, Art. 22-A); it is complementary evidence for vendor assessment (TPRM). The same text ships inside the bundle the buyer receives.

Create

codafort attest create [path] \
  --standard asvs-l2-sast \          # or asvs-l1-sast (default: l2)
  --evidence vet.json \              # coda-evidence/1 from another tool (repeatable)
  --evidence iast-ev.json \
  --artifact dist/app.tar.gz \       # SHA-256 computed here: the declaration points at the release
  --artifact-digest "ghcr.io/org/app@sha256:<64 hex>"   # digest computed outside (OCI image)
  --supersedes previous-attestation.txt # same commit and same result: succession

What the command does:

  1. Scans the path with a fixed profile (the scan one, without --rules-dir), so the declared ruleset is the one that ran.
  2. Builds the payload: commit, standard, verdict, findings by severity, evidence (evidence[]) and artifacts (artifacts[], in in-toto shape).
  3. Counter-signs. Online, it sends the payload to codafort, which checks the licence (Verified or Platform) and whether it was revoked. Without network (air-gapped), set CODAFORT_ATTEST_KEY (sub-key) and CODAFORT_ATTEST_DELEGATION (delegation signed by the root key): the command signs locally and the delegation travels in the token, for attest verify to check.

Rules the command applies without asking:

  • An --evidence file that is not coda-evidence/1 is an error.
  • --supersedes requires the same commit and the same scan result. A different scan is a new declaration.
  • --artifact is an issuer declaration, counter-signed. It does not prove the build came from that source (that is build provenance, SLSA L2+); the verifier and the compliance map say so.
  • A tree with uncommitted changes is stamped dirty: true: the declared commit does not describe the scanned code.

Verify (free, offline)

codafort attest verify <token | file | envelope.intoto.json>

Accepts the token (payload.signature) and the DSSE envelope / in-toto Statement. Checks the signature, the kind (the older codafort-attestation/1 format remains valid) and, for a declaration signed without network, the delegation and its expiry. No CLI at hand? The codafort.com/verify page runs the same check in the browser, sending nothing.

Bundle

codafort attest bundle [path] --standard asvs-l2-sast --evidence … --artifact … \
  --format zip -o codafort-attestation.zip          # TPRM / data-room face
codafort attest bundle … --format in-toto --artifact dist/app.tar.gz \
  -o codafort-attestation.intoto.json              # policy-engine face (requires --artifact)

The .zip is what goes to whoever assesses the vendor: the token, a readable summary, COMPLIANCE-MAP.md (standard, verdict, commit, digest and modalities, with what it proves and does not) and the offline verification instructions.

The in-toto output carries the same payload in a DSSE envelope (application/vnd.in-toto+json), with a https://in-toto.io/Statement/v1 Statement and the https://codafort.com/coda-attestation/v1 predicate, so you can write policy in Kyverno or policy-controller.

The verdict rule

The rule is fixed per standard (--standard), and the repository's .codafort-gate.yaml does not change it. The verdict is fail when the result has any blocker or critical finding, any vulnerability, or when IAST evidence carries a finding confirmed at runtime. unreached and sanitized do not change the verdict. What each piece of evidence carries is in The evidence chain.

Full flow, end to end

codafort vet --evidence-out vet.json                      # the AI code was judged
codatrace collect --socket "$SOCK" --static static.json --output laudo-iast.json
codatrace evidence --report laudo-iast.json --coverage coverage.json > iast-ev.json  # IAST contribution
codaprobe evidence --report laudo-dast.json > dast-ev.json  # DAST contribution (from the codaprobe scan report)
codafort attest bundle --evidence vet.json --evidence iast-ev.json --evidence dast-ev.json \
  --artifact dist/app.tar.gz -o attestation.zip
# on the other side, with no licence:
codafort attest verify attestation.zip/token.txt