Skip to content

v1.20.1

Choose a tag to compare

@luisgf luisgf released this 14 Jul 06:09
· 40 commits to main since this release

Added

  • External-audit pack (docs/audit/) — audit-readiness groundwork for the
    funded external review: a code-cited
    threat-model annex
    (per-suite and per-parser attack-surface tables, the fail-closed invariants
    catalog I1–I15, and a residual-risk register R1–R8), an
    assurance report
    (property-based fuzz coverage, the harden-next gap map, and the
    adversarial-review history), and a
    reviewer index
    with the suggested review scope and EU funding routes. No code change — the
    external audit itself stays gated on funding.
    (#75)

Security

  • Fail closed on hostile deeply-nested JSON across the verify pipeline. A
    deeply-nested (but valid) JSON credential — an SD-JWT header/payload/disclosure, a
    chain of SD-JWT disclosures each carrying the next _sd digest, a VC-JWT
    header/payload, or an enveloped VC's data: payload — made json.loads (or the
    SD-JWT _unpack recursion) raise RecursionError (a RuntimeError, not an
    OpenvcError). On the untrusted peek/unwrap path that escaped verify_many's
    per-credential isolation and aborted the whole batch (denial-of-service; not a
    wrong-accept) — reachable unauthenticated and, on CPython 3.10–3.13, with ~1 KB of
    input. SD-JWT _unpack now caps recursion at depth 100 (parity with cbor=64 /
    _jcs=100), the did:webvh genesis SCID walk (_deep_replace_scid) is depth-bounded
    too, and every attacker-facing json.loads — SD-JWT, VC-JWT peek/verify, _jws,
    the enveloped unwrap, jwe, and the did:jwk / did:webvh / fetch / status-resolver
    paths — now maps RecursionError to a typed error, so hostile input fails closed and
    verify_many isolates it across all formats. Resolves the R1 residual risk from
    the audit pack. (#117)