Security
Integrity, with explicit boundaries.
Avow is a small cryptographic primitive. The useful security review is not “is it encrypted?” but “what exactly does a valid receipt prove, and what is still the operator’s job?”
What a valid receipt proves
- The payload is byte-for-byte the payload that was signed, after RFC 8785 canonicalisation.
- The Ed25519 signature matches the payload.
- The signer key matches the public key the verifier supplied, not the key embedded in the receipt.
A receipt carries its own public_key for convenience. That field is not a trust anchor. A verifier must obtain the expected key through configuration or a distribution channel it already trusts; otherwise an attacker can supply both a forged payload and the matching key.
What it does not prove
| Not provided | Why |
|---|---|
| Confidentiality | The payload is plain text in the receipt. Encrypt or redact before signing. |
| Truth or correctness | A signature proves who signed, not whether the signed claim is true. |
| Freshness or wall-clock time | There is no trusted timestamp in the receipt. |
| Replay protection | A valid receipt verifies every time it is presented. |
| Key management | The operator generates, stores, rotates, and distributes keys. |
Key handling
Python’s key loader refuses key files that are readable by group or others and reports avow.key_permissions_insecure. The TypeScript package does not read key files; the signing seed is unencrypted hex held by the caller, so storage is the integrating application’s responsibility.
- Generate keys on the machine that signs.
- Distribute only the public key, through a channel independent of the receipts.
- Keep an offline backup of the private key; losing it prevents new signatures with that identity.
- Plan rotation: a new key needs a new pinned public key at every verifier.
Replay protection is caller-owned
A receipt carries no nonce, audience, or expiry that Avow enforces. If replay matters, sign your own nonce, audience, and expires_at claims into the payload, then check them after verify against your own trusted clock and seen-nonce store. The repository’s operations guide includes the recipe.
Supply chain
Release workflows use short-lived PyPI and npm OIDC identities rather than stored registry write tokens. Eligibility, tests, dependency and secret scans, artifact builds, and clean-install checks run before either publishing job can request an OIDC identity. Each registry is checked independently; an existing mismatch stops the workflow instead of overwriting it.
Supported versions
0.5.3 of both the Python package and @gainratio/avow is the supported release. Python releases 0.1.0 through 0.4.1 shipped stray top-level packages and are unsupported.
Report a vulnerability
Report suspected vulnerabilities privately through GitHub’s private vulnerability reporting for gainratio/avow. Include:
- the affected operation and version;
- a minimal reproduction using non-sensitive data;
- the security impact;
- any mitigation you have already tested.
Do not include private keys, production payloads, or other secrets. Allow time to reproduce and assess before public disclosure.