spiffe-compliance-checker

module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2026 License: Apache-2.0

README

spiffe-compliance-checker logo

spiffe-compliance-checker

English | 日本語

ci

demo

A static compliance checker for SPIFFE artifacts. Pass scc a SPIFFE ID, an X.509-SVID certificate, a JWT-SVID or WIT-SVID token, a trust bundle, or a bundle map, and it tells you which MUST / MUST NOT clauses from the SPIFFE spec the artifact satisfies or violates. Every output line cites the source document and section so a failed check reads as a spec walkthrough.

SPIFFE is the CNCF spec set that defines spiffe://... workload identities and the SVIDs that carry them. It backs SPIRE, Istio's mTLS layer, Cilium's mutual auth, and many in-house implementations. The spec lives across eleven markdown files in spiffe/spiffe and ships without an official conformance suite. scc covers the slice of compliance that is checkable from outside: the shape of the artifacts themselves. Runtime concerns (workload attestation, key rotation, Workload API endpoint behaviour, signature verification against a specific bundle) are out of scope.

Install

Pick whichever fits your setup. Each one installs the same scc binary on PATH.

# Homebrew (macOS + Linux, prebuilt binary)
brew install kanywst/tap/spiffe-compliance-checker

# go install (any platform with Go 1.26+)
go install github.com/kanywst/spiffe-compliance-checker/cmd/scc@latest

# Prebuilt archive
# https://github.com/kanywst/spiffe-compliance-checker/releases

The CLI depends on charm.land/lipgloss/v2 for colored terminal output and golang.org/x/term for TTY detection. No other runtime dependencies.

Verifying a release

Every release ships an SPDX 2.3 SBOM per archive (<archive>.tar.gz.sbom.json) and a keyless cosign signature over checksums.txt, as a Sigstore bundle (checksums.txt.sigstore.json). Keyless means there is no public key to fetch: the signing identity is the release workflow itself, recorded in the Sigstore transparency log.

# 1. Verify that checksums.txt was signed by this repo's release workflow
cosign verify-blob checksums.txt \
  --bundle checksums.txt.sigstore.json \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp '^https://github\.com/kanywst/spiffe-compliance-checker/\.github/workflows/release\.yml@refs/tags/v'

# 2. Then check the archive against the now-trusted checksum list
sha256sum --check --ignore-missing checksums.txt   # macOS: shasum -a 256 -c

Usage

scc id         [--format text|json|sarif] <spiffe-id-string>
scc x509-svid  [--format text|json|sarif] <cert.pem | cert.der>
scc jwt-svid   [--format text|json|sarif] <token>
scc wit-svid   [--format text|json|sarif] <token>
scc bundle     [--format text|json|sarif] <bundle.json>
scc bundle-map [--format text|json|sarif] <bundle-map.json>

Each subcommand prints one line per checked clause and exits non-zero if any MUST clause fails. SHOULD violations surface as WARN and do not change the exit code. Colors render only when stdout is a TTY and NO_COLOR is unset, so the same binary is safe in scripts and CI logs.

Output formats

--format selects how results are rendered. The exit code is identical across all three, so json and sarif are safe to gate CI on:

Format Use case
text (default) Human-readable, optionally colored report.
json Stable object for automation (jq, scripts). Carries every assertion + summary.
sarif SARIF 2.1.0 for GitHub Code Scanning and other aggregators. Only violations become results.
# Fail a pipeline and upload findings to GitHub Code Scanning
scc x509-svid --format sarif leaf.pem > scc.sarif
$ scc id 'spiffe://Example.com/payments/web-fe'

scc id  spiffe://Example.com/payments/web-fe

  ✓ PASS  SPIFFE-ID.md §2    SPIFFE ID MUST NOT include query or fragment
  ✓ PASS  SPIFFE-ID.md §2    scheme MUST be "spiffe"
  ✓ PASS  SPIFFE-ID.md §2.1  trust domain MUST NOT be empty
  ✗ FAIL  SPIFFE-ID.md §2.1  trust domain MUST be lowercase
         → trust_domain="Example.com"
  ✗ FAIL  SPIFFE-ID.md §2.1  trust domain MUST contain only [a-z0-9.-_], no percent-encoding
         → trust_domain="Example.com"
  ✓ PASS  SPIFFE-ID.md §2.3  trust domain MUST be at most 255 bytes
  ✓ PASS  SPIFFE-ID.md §2.2  path segments MUST contain only [a-zA-Z0-9.-_]
  ✓ PASS  SPIFFE-ID.md §2.3  SPIFFE ID MUST be supported up to 2048 bytes

  ────────────────────────────────────
  11 passed  ·  2 failed  ·  0 warnings

$ echo $?
1

Coverage

Spec What scc checks
SPIFFE-ID.md scheme, trust domain charset / length / case, path segments, total length, query / fragment
X509-SVID.md URI SAN count, leaf vs signing Basic Constraints, Key Usage flags, EKU, leaf SPIFFE ID rules
JWT-SVID.md alg whitelist, JWS Compact Serialization, sub / aud / exp presence, SPIFFE ID in sub
WIT-SVID.md mandatory kid / typ=wit+jwt / alg, cnf.jwk shape and algorithm, forbidden aud, nbf / iss rules
SPIFFE_Trust_Domain_and_Bundle.md JWKS shape, kty / use per key, spiffe_sequence / spiffe_refresh_hint, x5c for x509, bundle-wide kid uniqueness
SPIFFE_Trust_Domain_and_Bundle.md §5 bundle map: trust_domains presence, trust domain name validity and uniqueness, each embedded bundle, omitted spiffe_refresh_hint

The MUST clauses are pulled directly from the spiffe/spiffe main branch at commit dc4e9d9 (2026-08-03).

WIT-SVID

The WIT-SVID is the third SVID type, added to the spec set in July 2026. It is a SPIFFE sub-profile of the IETF WIMSE Workload Identity Token: a JWS-signed JWT whose cnf claim binds the workload's public key to its SPIFFE ID. Unlike a JWT-SVID it is not a bearer token, so several rules invert — most visibly aud, which a JWT-SVID must carry and a WIT-SVID must not.

scc checks the token's shape only. The proof of possession that a WIT-SVID must always be presented with is a runtime concern and stays out of scope, as does signature verification.

WIT-SVID.md is marked Stability: Incubating in spiffe/spiffe, meaning breaking changes are avoided but may still be made in response to implementation experience. The other specs above are marked Stable. Expect the WIT-SVID clauses to move more than the rest.

A trust bundle publishes WIT signing keys as JWK entries with use set to wit-svid (WIT-SVID.md §6.1), so scc bundle accepts that value alongside x509-svid and jwt-svid, requires a kid on each such entry, and checks that no two keyed entries share a kid.

Bundle maps

A SPIFFE Bundle Map (SPIFFE_Trust_Domain_and_Bundle.md §5) is a trust_domains object holding one bundle per trust domain. scc bundle-map runs the full scc bundle sweep over every embedded bundle, attributing each assertion to the trust domain it came from, and layers the map's own clauses on top:

  • trust_domains MUST be set, and MAY be empty.
  • Each key MUST be a valid trust domain name. §5.1.1 defers to SPIFFE-ID.md §2 for that, so the same clauses that check the authority of a SPIFFE ID are reused verbatim on the keys.
  • Trust domain names MUST be unique. This is the one clause a plain JSON unmarshal cannot enforce — most parsers, Go's included, silently keep the last of a duplicated key — so scc re-walks the raw bytes at token level. §6.3 explains the stakes: a duplicate name means the wrong trust anchors can end up validating an SVID.
  • Bundles inside a map SHOULD omit spiffe_refresh_hint, the inverse of the standalone rule, because the hint applies to the map as a whole.

kid uniqueness stays scoped to a single bundle, so two trust domains reusing the same kid is not a collision.

  • spiffe/spiffe — the spec set this tool validates against
  • spiffe/go-spiffe — the Go library to use when you need to consume SVIDs in production code, not just check their shape
  • spiffe/spire — the reference implementation of the Workload API

License

Apache-2.0. See LICENSE.

Directories

Path Synopsis
cmd
scc command
Command scc (SPIFFE Compliance Checker) evaluates SPIFFE spec MUST clauses against artifacts supplied on the command line.
Command scc (SPIFFE Compliance Checker) evaluates SPIFFE spec MUST clauses against artifacts supplied on the command line.
internal
bundle
Package bundle checks a SPIFFE Trust Bundle (a JWK Set with SPIFFE extensions) against the MUST clauses of SPIFFE_Trust_Domain_and_Bundle.md plus the per-SVID-spec requirements layered on top of bundle entries.
Package bundle checks a SPIFFE Trust Bundle (a JWK Set with SPIFFE extensions) against the MUST clauses of SPIFFE_Trust_Domain_and_Bundle.md plus the per-SVID-spec requirements layered on top of bundle entries.
bundlemap
Package bundlemap checks a SPIFFE Bundle Map — the JSON structure defined in SPIFFE_Trust_Domain_and_Bundle.md §5 that carries several SPIFFE Bundles keyed by trust domain name.
Package bundlemap checks a SPIFFE Bundle Map — the JSON structure defined in SPIFFE_Trust_Domain_and_Bundle.md §5 that carries several SPIFFE Bundles keyed by trust domain name.
id
Package id implements MUST-clause validation of a SPIFFE ID string against SPIFFE-ID.md.
Package id implements MUST-clause validation of a SPIFFE ID string against SPIFFE-ID.md.
jose
Package jose decodes a JWS Compact Serialization token into its JOSE header and claim set.
Package jose decodes a JWS Compact Serialization token into its JOSE header and claim set.
jwtsvid
Package jwtsvid checks a JWT-SVID token against the MUST clauses of JWT-SVID.md.
Package jwtsvid checks a JWT-SVID token against the MUST clauses of JWT-SVID.md.
report
Package report aggregates PASS/FAIL/WARN outcomes from compliance checks and renders them as a colored, emoji-tagged human report.
Package report aggregates PASS/FAIL/WARN outcomes from compliance checks and renders them as a colored, emoji-tagged human report.
spec
Package spec is the citation table for SPIFFE spec MUST / MUST NOT / SHOULD clauses.
Package spec is the citation table for SPIFFE spec MUST / MUST NOT / SHOULD clauses.
witsvid
Package witsvid checks a WIT-SVID token against the MUST clauses of WIT-SVID.md — a JWS-signed JWT whose cnf claim binds the workload's public key to its SPIFFE ID.
Package witsvid checks a WIT-SVID token against the MUST clauses of WIT-SVID.md — a JWS-signed JWT whose cnf claim binds the workload's public key to its SPIFFE ID.
x509svid
Package x509svid checks an X.509 certificate against the MUST clauses of X509-SVID.md.
Package x509svid checks an X.509 certificate against the MUST clauses of X509-SVID.md.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL