Repository navigation
Public-release setup: metadata, CI, supply chain, fuzzing and governance docs - #4
Conversation
Cargo.lock omitted the dev-dependency image-webp (and its transitive byteorder-lite and quick-error). Without this, cargo build --locked fails in CI. The resolution is additive; no existing package version changed. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
- license = MIT (matches LICENSE-MIT; see the README licensing note) - repository, readme, description, keywords, categories - rust-version = 1.89, verified with cargo +1.89.0 build --all-targets - #![forbid(unsafe_code)] on the library crate (the crate has no unsafe) - [lints.clippy]: style, complexity and perf are allowed for now. The crate has about 380 findings there, mostly float-literal precision in DSP tables. Correctness and suspicious lints stay on, so cargo clippy -- -D warnings gates CI. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
The AV1 range-decoder bool/bit paths (av1_ec.rs) and coefficient context (av1_coef.rs) rely on 32-bit wrap-around: 'r - 2*v' and '(h - k)' are negative in the spec sense and wrap, and the wrapped value is multiplied by 0/1 or clamped with min(). Debug builds panicked with 'attempt to subtract with overflow', so cargo test failed on the two round-trip unit tests. The arithmetic is now spelled with wrapping_* ops. Release builds already wrapped, so their behaviour does not change. Warnings: - src/main.rs used to declare its own copy of the codec modules (mod aac; ...), so most library items looked unused in the binary. It now uses the library. - mp3::read_huffman is private (it was more visible than its Br argument type). - Dead idx store in mp3 Huffman section removed. - jpeg::ycbcr_to_rgb was unused and is removed. - opus.rs carries CELT scaffolding for the unfinished Opus decode path; it is marked #![allow(dead_code)] with a pointer to ROADMAP.md. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
…ation - README: rewritten to match the code. The old text described a PDF image decoder that does not exist here and paths that are not in the tree. The status table is taken from ROADMAP.md and the source. A patents and licensing section is first, marked as an open decision. - CONTRIBUTING, CODE_OF_CONDUCT (Contributor Covenant 2.1), SECURITY (GitHub private reporting; no email address), CONTRIBUTORS (human names from git history), CHANGELOG (Keep a Changelog). - docs/OPENSSF.md: Scorecard mapping, Best Practices status, and open human items. Placeholder owners, the license question, the patent review, the conduct contact, repository visibility and the ruleset are all open. - docs/SUPPLY-CHAIN.md: pins with verified commit SHAs, verification commands. - docs/RELEASING.md: maintainer steps. - PR and issue templates. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
- ci.yml: job 'Rust checks' (fmt, build, test with ffmpeg installed, clippy -D warnings) and an MSRV 1.89 build job. - codeql.yml (Rust), scorecard.yml, dependency-review.yml. - supply-chain.yml: cargo-audit, cargo-deny, CycloneDX SBOM, evidence record. - fuzz.yml: matrix over seven libFuzzer targets; crash inputs kept on failure. - release.yml: tag-gated; runs tests, checks the tag against Cargo.toml, builds the CLI, signs with cosign, attests SLSA provenance. No container job, since the crate has no Dockerfile. - Every uses: line is pinned to a full commit SHA. Actions were verified with git ls-remote (peeled commits where annotated). - dependabot.yml for cargo and github-actions. - CODEOWNERS uses @owner-1 @owner-2 placeholders. Replace them with real maintainers before enabling the code-owner rule. - fuzz/: cargo-fuzz crate with targets for PNG, JPEG, FLAC, SLAC, MP3, AAC and Opus. The crate has its own workspace and lock file. - deny.toml: MIT and Apache-2.0 only, crates.io sources only, no git sources. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
…ndle-path - cosign sign-blob --bundle writes one .sigstore.json per asset. The previous --output-signature/--output-certificate flags are verify-blob options and do not belong on sign-blob, and the identity check moves to the verify command. - The provenance bundle is taken from the attest step's bundle-path output and copied as the .intoto.jsonl asset, instead of base64-decoding an output. - Release assets now list the two .sigstore.json bundles in place of the .sig and .cert pairs. SUPPLY-CHAIN.md's verification command is updated to --bundle with the identity and issuer checks. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
The crate was never run through rustfmt: cargo fmt --check reported about 700 hunks. This commit is formatting only. Tests and clippy are unchanged. The next commit's diff can be read without this noise by ignoring whitespace-only changes (git log -p --ignore-all-space). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
|
Dependency review fails on Generated by Claude Code Generated by Claude Code |
- docs/STANDARDS.md: for each format the crate decodes or encodes, the specification, its body, and the licensing and patent position as understood. Each row is marked unverified: the standards hosts did not resolve from the session that wrote it, so each row links its primary source for review. Open standard is stated as not the same as royalty-free. - README: a standards and licensing section linking the table, and a note that this is a codec implementation, not a certified or licensed product. - CODEOWNERS: @twn-lloyd @yokoszn replace the placeholders. - SECURITY.md: security@twn.systems added alongside private reporting. - CODE_OF_CONDUCT.md: hello@twn.systems as the enforcement contact. - docs/OPENSSF.md: CODEOWNERS and contact items marked resolved; the patent item now points at docs/STANDARDS.md. No codec, fuzz or manifest change. Licence unchanged (MIT). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
|
CodeQL (Rust) fails on Generated by Claude Code Generated by Claude Code |
- jpeg: a marker's length field and the APP14 Adobe segment must lie inside the input. Previously the APP14 transform byte was read past the end of a 97-byte input. - flac: the metadata loop stops when the reader is past the end of the input. Past the end the bit reader returns zeros, so the last-block flag never set and the loop never ended. - codec (SLAC): the per-channel capacity is capped at what the input can hold (8 samples per byte). A header frame count of about 4 billion made Vec::with_capacity request about 17 GB before any data was read. Capacity only; valid output is unchanged. - aac: a fill element whose escape byte is zero is rejected instead of underflowing the count. tests/fuzz_regressions.rs embeds each crash input and runs the decoder on a worker thread with a deadline, so a panic, a hang or an abort fails the test. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
…zzing Each fix rejects malformed input with an error. Valid input is unchanged. - flac: a unary code read past the end of the input never terminated (the bit reader yields zeros). The loop now stops at the end of the input. - flac: the metadata loop stops when past the end of the input. - flac: a subframe whose wasted-bits count reaches the sample width is an error (it underflowed the width). decode_subframe now returns a Result. - flac: a frame whose channel count differs from STREAMINFO is an error. - slac: each channel block checks the input is not exhausted first. A header with 49163 channels walked frames and blocks long after the input ended. - slac: the per-channel capacity is capped at what the input can hold. - jpeg: every length-bearing marker's segment must lie inside the input before its fields are read. DQT, DHT and DRI bound their reads against the segment or the input. SOF needs seven bytes, SOS needs its component list to fit. - jpeg: a scan header with no component count byte is an error. - jpeg: a scan before any frame header (zero components) is an error. - aac: a fill element whose escape byte is zero is an error, not an underflow. tests/fuzz_regressions.rs embeds each crash, hang or allocation input and runs the decoder on a worker thread with a deadline. A panic, a hang or an abort fails the test. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
- LICENSE is the Apache License, Version 2.0. LICENSE-MIT is removed. - Cargo.toml: license = "Apache-2.0". The version stays 0.1.0. - README, STANDARDS, OPENSSF, SUPPLY-CHAIN and CONTRIBUTING now state Apache-2.0. The release workflow packages LICENSE. - CHANGELOG: Unreleased lists the licence change and the decoder hardening. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ch6Crfubj3FwdxR7ywn9vT
Summary
Prepares transcode for public release. Changes:
image-webp, so--lockedfailed);license,repository,readme,keywords,categories,rust-version = 1.89(verified withcargo +1.89.0 build --all-targets);#[forbid(unsafe_code)];[lints.clippy]with style, complexity and perf allowed for now and correctness and suspicious kept on.av1_ec.rsandav1_coef.rs(wrapping ops, release behaviour unchanged). Two previously failing unit tests now pass. Dead-code and warning cleanup, including the binary now using the library modules.cargo fmtonly (about 700 hunks before). Usegit log -p --ignore-all-spaceto review the other commits without it.docs/OPENSSF.md,docs/SUPPLY-CHAIN.md,docs/RELEASING.md. PR and issue templates.Rust checksjob (fmt, build, test with ffmpeg installed, clippy-D warnings), MSRV job, CodeQL, Scorecard, dependency review, cargo-audit, cargo-deny, CycloneDX SBOM, Dependabot. Everyuses:is pinned to a full SHA verified withgit ls-remote.Cargo.toml, signs with cosign bundles (.sigstore.json), attaches SLSA provenance viabundle-path.fuzz/with seven libFuzzer targets (PNG, JPEG, FLAC, SLAC, MP3, AAC, Opus) and a fuzz workflow.Output compatibility
Codec output is unchanged. The
av1_ec/av1_coefedits keep the release-mode arithmetic identical, and the formatting commit changes no logic. The test suite passes (cargo test --locked: 57 unit tests and all integration tests, one ignored report).Checks
cargo fmt --all -- --checkcargo test --locked --no-fail-fast: all pass (ffmpeg installed locally, so the ffmpeg oracle tests ran)cargo clippy --locked --all-targets -- -D warningscargo build --locked --all-targetson stable andcargo +1.89.0cargo deny check advisories bans licenses sources: okcargo audit: no advisories against the 4 locked cratesuses:are SHA-pinned.Fuzz smoke run (60 s per target, debug+ASan, nightly)
src/jpeg.rs:633(APP14 segment read past end of a 97-byte input). Artifact:fuzz/artifacts/fuzz_jpeg/crash-e157e4d4…(not committed)-timeout=5). Artifact:timeout-cfba9968…(not committed)crash-e9befc07…(not committed)src/aac.rs:722(cnt += b.bits(8) - 1when the field is 0)These are decoder bugs. They are reported here and not patched or suppressed in this PR. The fuzz targets are intentionally kept so the first CI run shows them. A follow-up should fix each one with a bounds check that returns
Err, plus a regression test. The JPEG marker walker also appears to loop forever on a zero segment length (read from the code, not yet reproduced).Notes for reviewers
LICENSE-MITandlicense = "MIT". An earlier README saidMIT OR Apache-2.0. Dual licensing needs a decision and anLICENSE-APACHEfile.@OWNER-1 @OWNER-2placeholders. Real maintainers are needed before the code-owner rule.caretakerctl ossf(the caretaker workspace depends on private git repos). Templates were rendered with an equivalent script; seedocs/OPENSSF.md.docs/SUPPLY-CHAIN.mdhave not been run against a real tag.Generated by Claude Code