-
Notifications
You must be signed in to change notification settings - Fork 0
Status Lists
A status list is a bitstring an issuer publishes; each credential points at
one bit of it (credentialStatus), and flipping the bit revokes (or suspends)
the credential without reissuing anything. openvc implements both wire
encodings behind one interface — the W3C
Bitstring Status List
(a W3C Recommendation since 2025-05) and
the IETF Token Status List
(draft-21, IESG-approved and in the RFC Editor queue as of 2026-07) — and can
check and issue either. The Token Status List codec is pinned byte-for-byte to
the draft's §4.1 worked examples, and the Bitstring codec to the W3C REC's own
encodedList example (plus a third-party Digital Bazaar vector).
The Bitstring encodedList is multibase-encoded (a leading u, base64url) as the
REC mandates: decode_bitstring consumes real W3C lists that carry the u prefix and
still reads legacy prefix-less lists, and encode_bitstring emits the conformant u.
from openvc.status import (
build_status_list_credential,
build_status_list_entry,
check_credential_status,
new_bitstring,
set_status_bit,
)
LIST_URL = "https://issuer.example/status/1"
INDEX = 17
# A credential the issuer hands out, pointing at bit 17 of the list.
credential = {
"@context": ["https://www.w3.org/ns/credentials/v2"],
"type": ["VerifiableCredential"], "issuer": "did:example:issuer",
"credentialStatus": build_status_list_entry(
status_list_credential=LIST_URL, index=INDEX),
"credentialSubject": {"id": "did:example:alice"},
}
def status_list(revoked: bool):
"""The (unsigned) status-list credential a resolver would fetch + verify."""
bits = new_bitstring(1024)
if revoked:
set_status_bit(bits, INDEX, 1)
return build_status_list_credential(
id=LIST_URL, issuer="did:example:issuer", bitstring=bits)
live, dead = status_list(revoked=False), status_list(revoked=True)
print(check_credential_status(credential, resolve_status_list=lambda _u: live).revoked)
print(check_credential_status(credential, resolve_status_list=lambda _u: dead).revoked)In production, sign the status-list credential like any other credential and
serve it at LIST_URL.
verify_credential treats a declared status it cannot check as a
rejection: if the credential carries credentialStatus and you supplied no
resolver, it fails. Supply one of the blessed resolvers — they fetch through
the SSRF guard and verify the fetched list's own proof before trusting a
single bit:
from openvc import verify_credential
from openvc.resolvers import (
default_status_list_resolver, # W3C Bitstring status lists
default_status_list_token_resolver, # IETF Token Status List (JWT)
)
result = verify_credential(
token,
resolve_status_list=default_status_list_resolver(),
resolve_status_list_token=default_status_list_token_resolver(),
)Opting out (accepting a credential without checking its declared status) is an explicit policy decision, not a default.
-
Anti-swap: a status-list token's
submust equal the URI it was fetched from, so a valid list cannot vouch for a different one. -
Decompression bomb cap: lists decompress incrementally with a hard
output bound, so a tiny malicious payload cannot OOM the verifier
(fail-closed
StatusListError). -
Issuer binding (opt-in): by default a status list is authenticated but its
issuer is unconstrained — delegation of status hosting is spec-legal. If your
issuers self-host their status lists, set
VerificationPolicy(require_status_issuer_binding=True)to require the resolved list's issuer to be the credential's issuer (add trusted delegates viastatus_issuer_allowlist); a mismatch raisesStatusListIssuerUntrusted. See ADR-0006. -
SD caveat: keep the
credentialStatuspointer non-selectively disclosable, or a holder can withhold it — see SD-JWT VC and the Security model.
📖 Published automatically from the wiki/ directory of the main repository — edits made directly on the wiki are overwritten by the next sync. To change a page, open a PR against wiki/. Every python block on these pages is executed by CI. · API reference · LGPL-3.0-or-later
Start
Proof formats
Verifying in practice
- Presentations & OpenID4VP
- Resolving issuer keys
- Relying-party certificates
- Credential schemas
- Status lists
- Trust anchors: EU TL & EBSI
- Async verification
Walkthroughs
Operating
Reference