btclib

Logo

A Python library for 'bitcoin cryptography'

View the Project on GitHub btclib-org/btclib

Security policy

Reporting a vulnerability

If you have found a security vulnerability, please do not open a GitHub issue: an issue is public from the moment it is filed, and so is the window between filing it and a fix being released.

Report it privately instead, by opening a security advisory. Only the maintainers can see it, the discussion stays private until an advisory is published, and a CVE can be requested from it if the vulnerability warrants one.

If you have no GitHub account, or would rather not use it for this, responsible disclosure by email to security at btclib dot org is equally welcome.

What belongs here, and what belongs upstream

Signing, verification and generator multiplication on secp256k1 are delegated to btclib_secp256k1, the Python bindings, and through them to libsecp256k1 itself, which has its own security policy and its own address. A flaw in the elliptic curve arithmetic, or in how the bindings drive it, most likely belongs to one of those.

What belongs here is everything btclib does around them:

Report it wherever you found it, though: routing a report is the maintainers’ job, not the reporter’s, and a doubt about which of three projects owns a flaw is not a reason to keep it to yourself.

Supported versions

Only the latest release is supported. Versions are calendar-based (YYYY.M.D), a fix is published as a new release, and nothing is backported.

Wheels and sdist are published to PyPI with PEP 740 attestations, through a workflow that no long-lived token can authenticate for (PyPI Trusted Publishing), so a distribution can be traced back to the workflow run and the commit it was built from.

The same files are attached to the GitHub release, and those copies carry a build provenance attestation of their own, signed in the run that built them:

gh attestation verify btclib-<version>-py3-none-any.whl \
  --repo btclib-org/btclib \
  --signer-workflow btclib-org/btclib/.github/workflows/release.yml

--signer-workflow is what makes that say which workflow signed, rather than accepting any attestation this repository has. The signed statement is attached to the release as well, as <tag>.attestation.jsonl, so --bundle <tag>.attestation.jsonl runs the same check reading it from disk instead of asking GitHub for it; one attestation covers every asset of the release. Either file can also be rebuilt from its tag and verified without being downloaded at all, the build being reproducible: RELEASING.md has that command and the bounds on it.

A CycloneDX 1.6 bill of materials is attached beside them, btclib-<version>.cdx.json: the two files with their SHA-256, the licence, and one component per dependency the wheel’s metadata declares. It is generated from the built wheel rather than from the source tree, so it describes the files it is attached to, and it is covered by the same attestation — a bill of materials whose provenance nobody can check says only what whoever wrote it wanted said. What it records of a dependency is the requirement as published, so a component carries a version only where that requirement is an exact pin.

What may be inside those two files is stated in the package-content policy, and a build carrying anything else is refused before it can be published: an allowlist of the members of a wheel and an sdist, the suffixes and names neither may ever hold, and — named as policy, because no list of members can show them — the rules about what runs while the package is built and installed.

Limitations, not vulnerabilities

These are known and inherent. They are worth stating because btclib is used to teach and to prototype as much as to build: