Skip to main content

Python CI

cddl-verifier

Validate CBOR (RFC 8949) data against CDDL (RFC 8610) schemas, render it as annotated EDN (Extended Diagnostic Notation), and convert between CBOR and JSON. It is built for attestation formats such as CoRIM and CoSWID.

Scope. cddl-verifier parses the whole CDDL grammar (RFC 8610 as updated by RFC 9682) and enforces every construct and control operator in the conformance matrix, which lists each one with its tests. A corpus of real schemas and CBOR from RFCs and IETF drafts is checked against it, and the few places where it differs on purpose are listed there. See also Limitations and docs/CDDL_SUPPORT.md. The public API is stable from 1.0: see docs/COMPATIBILITY.md.

Surface Name
PyPI distribution cddl-verifier
Python import package cddl_verifier
Command-line tool cddl-verify

Installation

pip install cddl-verifier

Requires Python 3.9 or newer. There are no runtime dependencies: CBOR encoding and decoding are bundled. Extras for contributors: pip install "cddl-verifier[test]" (pytest, Hypothesis, pycddl) and [dev] (the same plus build, twine).

Quick start

New here? docs/GETTING_STARTED.md walks from installation to reading a failed validation, with a triage flow for each kind of failure. For copy-pasteable workflows (validation, debugging, JSON conversion, CI), see the task-oriented recipes.

Command line

cddl-verify schema.cddl data.cbor --type corim-map                     # validate, print annotated EDN
cddl-verify schema.cddl data.cbor --type corim-map --output data.edn   # write EDN to a file
cddl-verify schema.cddl data.cbor --show-types                         # list the parsed CDDL types
cddl-verify schema.cddl data.cbor -M modules/ --module rfc9393=coswid.cddl  # load imported CDDL modules

The exit status is 1 when the CBOR cannot be decoded or, with --type, when validation fails. Without --type the first rule is used and validation errors are only warnings (exit status 0). python -m cddl_verifier takes the same arguments. See docs/CLI.md.

Python

from pathlib import Path
from cddl_verifier import validate

result = validate(Path("schema.cddl"), Path("data.cbor").read_bytes(),
                  root_type="corim-map")
if result.valid:
    print("valid")
else:
    for diagnostic in result.diagnostics:
        print(diagnostic.code, diagnostic.path_text, diagnostic.message)
  • schema is CDDL text (str) or a path (pathlib.Path).
  • data is CBOR bytes or an already-decoded Python value.
  • root_type defaults to the first rule in the schema.
  • CBOR that cannot be decoded gives an invalid result with a "decode" diagnostic and its byte offset; it does not raise.
  • Each diagnostic also has the data path, the byte offset and bytes of the item, the rule, and what was expected and found. result.to_json() and render_text(result.diagnostics, verbose=True) render them. See docs/API.md.

To check many items against one schema, or to render EDN, use Validator:

from cddl_verifier import Validator

validator = Validator(Path("schema.cddl"))
result = validator.validate(cbor_bytes, root_type="corim-map")
print(validator.to_edn(cbor_bytes, root_type="corim-map"))

CBOR and JSON helpers:

from cddl_verifier.cbor import encode, decode
from cddl_verifier.json_codec import cbor_to_json

raw = encode({0: "Alice", 1: b"\x01"}, canonical=True)
assert decode(raw) == {0: "Alice", 1: b"\x01"}
print(cbor_to_json(raw, typed=True, pretty=True))

Decoding is strict: the input must be exactly one complete CBOR item. Empty, truncated or trailing-byte input raises CBORDecodeError with the byte offset of the problem. decode_sequence reads a CBOR sequence (RFC 8742) as the list of its items. See docs/API.md for the full API.

What is supported

  • CDDL maps, arrays, type aliases, groups, type choices (a / b and /=), sockets (//=), optional fields, occurrence indicators, IANA-registered parameters (&(name: n)), CBOR tags (#6.n(...)), numeric ranges (0..255, 0.0...1.0), and the controls .size, .cbor, .cborseq, .regexp, .bits, .ge, .gt, .le, .lt, .eq, .ne, .and, .within and the RFC 9165 / RFC 9741 controls (.plus, .cat, .det, .abnf, the text conversions, .printf, .json, .join). Details: docs/CDDL_SUPPORT.md.
  • Real CoRIM and CoSWID schemas: docs/CORIM_SUPPORT.md.
  • CBOR encoding and strict decoding with byte offsets in errors; duplicate map keys, invalid UTF-8 and excessive nesting are rejected.
  • Annotated EDN output with field names from the schema. A member is named by its key or its &(name: 0) label; with comment_names=True (--comment-names) a trailing comment (0: tstr ; name) names a member that has no &(name: 0) label (a label always wins).
  • CBOR ↔ JSON conversion. typed=True keeps byte strings, tags and non-string map keys (such as the integer keys in CoRIM maps), so typed JSON converts back to the same CBOR data. Without it, map keys become JSON strings, and keys that would collide (0 and "0") raise an error.

Limitations

  • CDDL: the whole RFC 8610 grammar (as updated by RFC 9682) is parsed, and schemas that are not valid CDDL raise SchemaError with a line and column. So do schemas that parse but do not make sense, such as an undefined name, a misused generic or an unknown control operator (#70). Validation covers a practical subset of what the grammar can express; the RFC 9165 and RFC 9741 controls are enforced (.plus, .cat, .det, .abnf, .abnfb, the base64, base32, base16 and base45 conversions, .base10, .json, .printf and .join), with the limits in CDDL_SUPPORT.md. The conformance matrix has the full list.
  • Canonical encoding: implements the RFC 8949 §4.2.1 core deterministic profile (see CANONICAL_AND_JSON.md). The optional §4.2.2 reduction of integral floats to integers is not applied, and floats are written in their shortest exact width in both modes (RFC 8949 §4.1); float_width(value, 64) fixes the width of one value.
  • CBOR: indefinite-length items, undefined and the other simple values decode; the encoder writes definite-length items. decode rejects a CBOR sequence; decode_sequence reads one.
  • Value types: tags decode to CBORTag(tag, value); a (tag, value) tuple is not a tag (the encoder raises TypeError for one, since 0.24.0). Map keys that are booleans, floats, arrays, maps or tags decode to CBORKey, so {1: a, true: b} keeps both entries and re-encodes to the same bytes.

Documentation

Document Contents
docs/GETTING_STARTED.md Install, write a schema, validate, and triage each kind of failure, with example commands and output
docs/RECIPES.md End-to-end CLI, Python, debugging, JSON/CBOR, CoRIM, and CI recipes
docs/CLI.md cddl-verify and JSON converter options, input rules, EDN output formats
docs/API.md Python API: validate, Validator, CBOR and JSON helpers
docs/CDDL_SUPPORT.md Supported CDDL syntax, types, and validation behaviour
docs/CONFORMANCE.md Conformance matrix: every construct, control and CBOR item by layer, with status and tests
docs/CORPUS.md Conformance corpus: real schemas and CBOR from RFC 8610, COSE, CoRIM, CoSWID, EDHOC and SUIT with the verdict each source gives, and what this library gets wrong
docs/divergences.json Where this library and the independent cddl crate (pycddl) disagree on the conformance corpus, and who is right (Differential testing)
docs/CORIM_SUPPORT.md CoRIM / CoSWID schema support
docs/CBOR_BUILDER_QUICK_REF.md, docs/ITERATIVE_CONSTRUCTION.md CBOR builder API in depth
docs/CBOR_DIAGNOSTIC_DUMP.md Diagnostic dump format
docs/CANONICAL_AND_JSON.md Canonical encoding and JSON round-trips
docs/EDN_FORMATTING_IMPROVEMENTS.md, docs/IANA_ANNOTATIONS_STATUS.md What the annotated EDN looks like, and registered parameters
docs/ Tag notation and other notes
docs/COMPATIBILITY.md What the 1.x compatibility promise covers, and what it does not; deprecation and Python version policy
docs/BENCHMARKS.md Benchmarks and profiling: how to run them and what they found
docs/CDDL_AST_DESIGN.md Contributor design: CDDL AST, parser and how it was introduced
TESTING.md Running and writing tests, CI setup
CONTRIBUTING.md Pull request checklist, versioning and releases
Releases Release notes

Development

git clone https://github.com/sahebbiswas/cddl_verifier
cd cddl_verifier
pip install -e ".[test]"
pytest

The package source is in src/cddl_verifier/. Modules whose names start with an underscore are internal. See TESTING.md.

Versioning and releases

Every pull request merged to main bumps the version in src/cddl_verifier/_version.py, following Semantic Versioning 2.0.0: a patch bump for fixes and docs, a minor bump for new features, and a major bump only for an incompatible change to the public API (cddl_verifier, cddl_verifier.cbor, cddl_verifier.json_codec and the cddl-verify CLI). What is covered, and what is not (message wording, EDN layout, internal modules), is in docs/COMPATIBILITY.md. Releases are cut from main when it is stable, so not every version is published. Each release's notes are on the GitHub releases page; there is no changelog file. See CONTRIBUTING.md for the rules and the release steps.

Metadata

Release files for cddl-verifier 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cddl-verifier 1.0.2
File Size Uploaded
cddl_verifier-1.0.2.tar.gz 544.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cddl-verifier 1.0.2
File Interpreter ABI Platform
cddl_verifier-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 745.9 kB

Release files / cddl_verifier-1.0.2.tar.gz

Download URL cddl_verifier-1.0.2.tar.gz
Size 544.6 kB
Tags Source
SHA-256 checksum
How to use checksums
41459901f1b0a32cb3d05471f1452d5028cc7b69fe735ea9774a6602224e36a6
BLAKE2b-256 checksum
How to use checksums
1beb1bf51e4db304d9a5699c8d97c153c5cacb23deb374e2cb01c0f81dd103cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / cddl_verifier-1.0.2-py3-none-any.whl

Download URL cddl_verifier-1.0.2-py3-none-any.whl
Size 201.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7c6c3ebb9b385d2da466ce5ed8917557f9798a66c5fedf18d314e35d8b2a1113
BLAKE2b-256 checksum
How to use checksums
faf8458d4a856125cd692991284f798fe1303bf11e09a82658c7e31d94ee689d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page