Add Security Policy

kamal 2026-04-23 12:35:52 +00:00
commit d869cfdac6

93
Security-Policy.md Normal file

@ -0,0 +1,93 @@
# Security Policy
## Reporting a vulnerability
Email **security@lo.sh** with a description and, if possible, a minimal
reproduction. Please do **not** file public issues or PRs for security
reports — give us a chance to ship a fix before the details are
public.
You can expect an acknowledgement within **72 hours** and a status
update (triage outcome, target fix date, coordinated disclosure window)
within **7 days**.
## Supported versions
Pre-1.0, only the latest 0.1.x patch release receives security fixes.
Once 1.0 ships, the current major version plus the immediately
preceding major (if still within 6 months of its last release) will
receive backported fixes.
| Version | Status | Receives fixes? |
|---------|----------------------|-----------------|
| 0.1.x | Current development | Yes |
| < 0.1.0 | Not published | — |
## Disclosure timeline
Default coordinated-disclosure window is **90 days** from the first
response, extendable by mutual agreement if a fix is complex. We'll
credit reporters in the security advisory unless they prefer to remain
anonymous.
CVE numbers are requested for any issue that meets the MITRE criteria
(i.e. remote, unauthenticated, or affects multiple downstream users).
## In-scope issues
LAC is a codec library with a deliberately narrow attack surface. The
following are all taken seriously:
- **Decoder panics on crafted input.** Any byte sequence that causes
`decode_frame` / `decode_frame_into` / `parse_header` to panic,
abort, hang, or enter an unbounded loop is a security bug. The
decoder's contract (spec §6) is "reject cleanly or produce defined
output; never panic."
- **Encoder misbehaviour on in-contract input.** Any `samples: &[i32]`
with `|sample| ≤ 2²³ 1` that causes `encode_frame` to panic,
corrupt memory, or produce a frame that does not round-trip is a
security bug. Out-of-contract input (spec §1 violation) is
documented to panic; that is not a bug.
- **Memory-safety issues.** LAC is `#![forbid(unsafe_code)]` in
intent; any path that could trigger undefined behaviour, uninitialised
reads, out-of-bounds access, or similar is a critical bug regardless
of triggering conditions.
- **CPU / memory amplification attacks.** Any input shape that causes
the decoder to consume disproportionate CPU or memory relative to
input size, beyond the buffer-size-proportional bound documented in
the README's *Input-size caps on untrusted channels* section.
## Out of scope
- **Compression-ratio regressions.** Not a security issue; file a
regular issue with a reproducer.
- **Bit-exactness deviations on malformed input.** Spec §6.2 explicitly
permits the decoder to produce any i32 value on adversarial
bitstreams. Callers that re-feed decoder output into `encode_frame`
without clamping are responsible for clamping; the resulting panic
is documented behaviour.
- **Silence-substitution amplification at the application layer.**
The README's *Silence-substitution amplification* section documents
this class and the mitigation (cap `frame_sample_count` to the
session-negotiated frame size). An application that ignores this
guidance and lets an attacker request 65 535 silence samples per
crafted frame is not vulnerable to LAC — it's vulnerable to its own
lack of input validation.
- **Timing / side-channel attacks.** LAC is a lossless codec, not a
cryptographic primitive; no constant-time guarantees are made. If
your deployment requires constant-time audio processing, LAC is not
the right component.
- **FLAC CLI comparison script** (`benches/compare-flac.sh`). Dev
tooling, not part of the published crate.
## Security-relevant design notes
- **Wire-format versioning** is the sync-word cluster (spec §8). A v2
decoder encountering a v1 frame or vice versa rejects cleanly; this
is a correctness property rather than a security one, but it is
the mechanism by which a future format revision can be deployed
without breaking old decoders on the same channel.
- **Fuzz coverage** runs in CI for every push, replaying the
repository's seeded corpus for both `decode_arbitrary` and
`roundtrip_arbitrary` targets. A regression that adds a new
panic-on-crafted-input path will fail CI before reaching a release.