1 Security Policy
kamal edited this page 2026-04-23 12:35:52 +00:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.