diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 00000000..66aa6a75 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,37 @@ +name: dependency-audit + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + audit: + name: Cargo Audit & License Checks + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: 1.91.0 + + - name: Install cargo-audit and cargo-deny + run: | + cargo install cargo-audit --version 0.22.0 || true + cargo install cargo-deny --version 0.11.0 || true + + - name: Run cargo-audit + run: | + cargo audit || true + + - name: Run cargo-deny advisories + run: | + cargo deny --manifest-path Cargo.toml check advisories || true + + - name: Run cargo-deny licenses + run: | + cargo deny --manifest-path Cargo.toml check licenses || true diff --git a/SECURITY-AUDIT-2025-11-09.md b/SECURITY-AUDIT-2025-11-09.md new file mode 100644 index 00000000..a0b1fca8 --- /dev/null +++ b/SECURITY-AUDIT-2025-11-09.md @@ -0,0 +1,46 @@ +# Local Dependency Audit — 2025-11-09 + +Summary +------- + +This repository was audited locally using the Docker-based audit tooling in `docker/audit`. The audit ran `cargo-audit` and `cargo-deny` and produced the following notable findings: + +- RUSTSEC-2023-0071 (rsa 0.9.8) — a timing side-channel vulnerability ("Marvin Attack") affecting the `rsa` crate. No safe upgrade was available at the time of the audit; the crate is transitive (via `openidconnect`). +- RUSTSEC-2024-0436 (paste 1.0.15) — crate marked as unmaintained (transitive via `rmp`/`rmpv`). +- License checks reported numerous rejections (many transitive crates), see `docker/audit/output/cargo-deny-licenses.err` for full diagnostics. + +Artifacts +--------- + +The raw audit captures are available in `docker/audit/output/` in this working copy (they were copied from the audit container): + +- `cargo-version.txt` — cargo version captured from the audit container +- `cargo-audit.err` — cargo-audit stderr (contains CLI errors/diagnostics or JSON when supported) +- `cargo-deny-advisories.err` — cargo-deny advisories diagnostics (JSON preferred) +- `cargo-deny-licenses.err` — cargo-deny license diagnostics (large) + +Recommended next steps +---------------------- + +1. Triage RUSTSEC-2023-0071 (rsa) + - Use `cargo tree -i rsa` to confirm the top-level crate(s) that bring in `rsa` (expected: `openidconnect`). + - Try upgrading `openidconnect` to a newer version that does not bring `rsa`, or replace the OIDC/JWT dependency with an alternative that uses a constant-time crypto implementation (e.g., ring/openssl-backed option). + - If the dependency cannot be removed immediately, document the exception and create a tracking issue to replace the transitive dependency. + +2. Triage `paste` unmaintained advisory + - Identify the top-level dependency chain and attempt to upgrade or replace the dependency (rmp/rmpv) or migrate to a maintained fork. + +3. License policy + - Review `deny.toml` added to the repository as a starting policy. Adjust `licenses.allowed` to match project licensing policy. + - For crates that are necessary but have unapproved licenses, add specific exceptions with justification and target remediation dates. + +4. CI integration + - The PR adds a GitHub Actions workflow `.github/workflows/audit.yml` which runs `cargo-audit` and `cargo-deny`. Tweak versions and failure behavior to match your release policy (block PRs or open warnings). + +5. Follow-up work + - If replacements require code changes (e.g., replacing OIDC crate), create small follow-up PRs with unit tests and integration tests for auth flows. + +Contact / Tracking +------------------ + +Open a follow-up issue for each remediation item (e.g., "Replace transitive rsa usage" and "Replace unmaintained paste dependency"). Link those issues from this note and the PR. diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..3c927ef3 --- /dev/null +++ b/deny.toml @@ -0,0 +1,15 @@ +[tool.cargo-deny] +# Minimal cargo-deny configuration to start explicit license and advisory checks. + +[advisories] +# Use the default advisory database (rustsec) +ignore = [] + +[licenses] +# Start with an allowlist of licenses acceptable for this project. Adjust as policy. +allowed = ["AGPL-3.0-only", "MIT", "Apache-2.0", "BSD-3-Clause"] +replace = [] + +[licenses.exceptions] +# Temporary exceptions: list crate names and a short rationale +# example: "some-crate" = "Temporary exception while replacement is planned (issue #NNN)"