| Version | Supported |
|---|---|
| 0.0.x | Yes |
Report security vulnerabilities by emailing sebastian.rousseau@gmail.com.
Do not open a public issue for security reports.
Include:
- A description of the vulnerability.
- Steps to reproduce.
- Affected versions.
- Any suggested fix (optional).
Expect an initial response within 48 hours. A fix or mitigation plan will follow within 7 days of confirmation.
noyalib enforces safety at the compiler level:
#![forbid(unsafe_code)]— zero unsafe blocks, guaranteed.- No C dependencies, no FFI calls. Pure Rust only.
- No network I/O, no file system writes, no environment variable reads.
Configurable limits protect against denial-of-service attacks:
| Limit | Default | Purpose |
|---|---|---|
max_depth |
128 | Prevents stack exhaustion from deep nesting |
max_document_length |
64 MB | Rejects oversized input |
max_alias_expansions |
1,024 | Prevents billion-laughs amplification |
max_mapping_keys |
65,536 | Caps mapping size |
max_sequence_length |
65,536 | Caps sequence size |
Use ParserConfig::strict() for a hardened preset suitable for untrusted input.
The three opt-in modules added in v0.0.6 (recovery, sval,
tokio) inherit every limit above and add their own DoS
mitigations:
| Surface | Guard | Knob |
|---|---|---|
noyalib::recovery::parse_lenient |
----marker count cap (defeats marker-spam OOM) |
ParserConfig::max_documents |
noyalib::recovery::parse_lenient |
Cumulative byte budget across line-truncation retries (defeats O(n²) re-parse on 10k-line malformed input) | LenientConfig::truncation_event_budget (default 1 MiB) |
noyalib::tokio_async::from_async_reader |
Bounded AsyncReadExt::take(max_document_length) drain (defeats slow-drip OOM) |
ParserConfig::max_document_length |
noyalib::tokio_async::YamlDecoder |
Optional inter-frame buffer cap (defeats codec buffer pinning by adversarial producer) | YamlDecoder::max_frame_size(usize) |
Untrusted-input deployments driving YamlDecoder over a network
stream should call max_frame_size(_) to a sane upper bound;
the default None matches the trust contract of a process-local
in-memory consumer.
The max_depth guard above relies on balanced increment /
decrement of the parser's internal depth counter on every
code path. Two correctness bugs were patched in v0.0.6 — one
that made from_str::<Value> falsely report
RecursionLimitExceeded on shallow pnpm-lock.yaml inputs,
and one in the no-span loader path that incremented depth
without ever checking the limit. See
doc/POLICIES.md § Resource-limit gates
for the full treatment.
- Runtime deps audited (
cargo-denyin CI): license validation, advisory checks, source verification. Cargo.lockcommitted for deterministic builds.- All GitHub Actions SHA-pinned.
Every tagged release goes through three layers of supply-chain integrity:
-
SLSA Level 3 build provenance. The
release.ymlworkflow usesactions/attest-build-provenanceto record the source commit, the builder identity, and the workflow invocation into the public Rekor transparency log. Verifiable from any clone of the repo:gh attestation verify --owner sebastienrousseau noyalib-0.0.1.crate
-
Keyless sigstore signing. The same workflow uses
cosignkeyless signing (Fulcio + Rekor) to produce a.sigand.pemalongside every artefact. The certificate identity is bound to this repo and this workflow; verifiers should pin both:cosign verify-blob \ --certificate-identity-regexp '^https://github\.com/sebastienrousseau/noyalib/' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ --signature noyalib-0.0.1.crate.sig \ --certificate noyalib-0.0.1.crate.pem \ noyalib-0.0.1.crate -
Software bill of materials (SBOM). Generated by
cargo treeat build time, signed alongside the.crate, attached to the GitHub Release. Lets downstream consumers reproduce the dependency closure used at release time.
All commits on the main branch must be signed. CI rejects unsigned pull request commits.