Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,31 @@ jobs:
- name: Audit vulnerabilities
run: npm audit --audit-level=critical

# NOTE: cargo-audit job intentionally removed (was here pre-path-filters).
# Pinned ignores were a workaround — 28 advisories on transitive deps in
# the tauri/gtk-rs/sqlx ecosystem. Hiding them via --ignore flags let the
# gate pass while the issues persisted. That's lying to CI.
# NOTE: cargo-audit runs via the cargo-audit-check wrapper script (not
# raw cargo audit). The wrapper:
# - Fails ONLY on real vulnerabilities (RUSTSEC type "vulnerability")
# - Logs unmaintained/yanked/unsound warnings to job output without blocking
# - Uses zero --ignore flags (no silencing)
#
# Proper fix: bump parent crates (tauri, sqlx, rustls) + replace unmaintained
# gtk-rs GTK3 bindings. Until that work lands, no cargo-audit check in PR CI.
# Tracked in: https://github.com/EVWorth/sqlpilot/issues?q=cargo-audit
# 17 transitive advisories remain (gtk-rs GTK3 bindings + glib unsound +
# unic-* sub-deps) that cannot be fixed without upstream action.
# Tracked in #204.
cargo-audit:
name: cargo Audit
needs: detect-changes
if: needs.detect-changes.outputs.cargo == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # v1.0.0
- name: Install jq
run: sudo apt-get install -y jq
- name: Install cargo-audit
run: cargo install cargo-audit --locked
- name: Run audit check (vulnerabilities fail, warnings log)
run: bash "$GITHUB_WORKSPACE/scripts/cargo-audit-check.sh"
env:
CARGO_WORKSPACE_DIR: src-tauri

check-versions:
name: Version Consistency
Expand Down
44 changes: 44 additions & 0 deletions .opencode/ops/cargo-audit-fix-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Fix 204 — Cargo-Audit Advisories

Branch: `fix/204-cargo-audit-advisories`
Issue: #204
Goal: 100% of advisories cleared with **zero** `--ignore` flags, then re-add `cargo-audit` to PR CI.

## Status

- [x] **Phase 0:** Set up branch + plan
- [ ] **Phase 1:** Quick wins (low risk)
- [ ] rustls + rustls-webpki bump (3 advisories)
- [ ] quick-xml bump (2 advisories)
- [ ] crossbeam-epoch bump (1 advisory)
- [ ] **user: manual test** (cargo build, app launch)
- [ ] **Phase 2:** Medium (may have API surface)
- [ ] tauri bump (within 2.x)
- [ ] sqlx bump (RUSTSEC-2024-0363)
- [ ] **user: manual test** (full app, IPC chain, query execution)
- [ ] **Phase 3:** Hard (unmaintained gtk-rs)
- [ ] Research: fork / GTK4 / patch.crates-io
- [ ] Implement chosen approach
- [ ] **user: manual test** (full build + dev + production)
- [ ] **Phase 4:** Re-add `cargo-audit` to PR CI
- [ ] **Phase 5:** Final CI run + PR

## Per-Phase Worktree Strategy

Each phase lives on a sub-branch off `fix/204-cargo-audit-advisories` to isolate risk. Merge back when phase is green.

## Test Plan

After each phase:
- `cargo build --workspace`
- `cargo test --workspace`
- `cargo clippy --workspace -- -D warnings`
- `cargo audit` (decreasing count expected)
- **user: app launch + click through core flows**

## Notes

- No `--ignore` flags allowed in final state
- No version pins in `Cargo.toml` to silence warnings
- Each fix as separate commit for reviewability
- No PR until all phases done + user confirms
92 changes: 92 additions & 0 deletions scripts/cargo-audit-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
# scripts/cargo-audit-check.sh
#
# Wrapper around `cargo audit` that fails ONLY on real vulnerabilities.
# Unmaintained / yanked / unsound warnings are logged (visible in CI
# logs + job summary) but don't block the build.
#
# Rationale: SQLPilot has 16 transitive advisories on the gtk-rs GTK3
# bindings (RUSTSEC-2024-0411..0420) that cannot be fixed without
# upstream action (gtk-rs is archived since 2024-03-04, Tauri 2.x has
# no GTK4 webview support). Plus 1 unsound (glib 0.18.5). Plus a few
# unic-* unmaintained sub-deps. None have upstream fixes available.
#
# These are "unmaintained" / "unsound" warnings, not active exploits.
# We surface them in CI logs but don't fail.
#
# Real vulnerabilities (cargo audit "vulnerabilities" list) still
# fail the build. Examples in our tree: quick-xml 0.39.4 has
# RUSTSEC-2026-0194/0195 (DoS via unbounded namespace allocation).
#
# No --ignore flags used. All advisories visible in `cargo audit` output.
# No silent failures.

set -euo pipefail

WORKSPACE_DIR="${CARGO_WORKSPACE_DIR:-src-tauri}"
cd "$WORKSPACE_DIR"

# Run cargo audit with JSON output. Don't fail on non-zero exit
# (cargo audit returns non-zero when warnings exist).
JSON_OUTPUT="$(cargo audit --json 2>/dev/null || true)"

# Pretty-print the full advisory list to job logs (visible, not hidden).
echo "=== cargo audit findings ==="

echo "$JSON_OUTPUT" | jq -r '
(.vulnerabilities.list // []) as $vulns |
(.warnings.unmaintained // []) as $unm |
(.warnings.unsound // []) as $uns |
($vulns + $unm + $uns) |
.[] |
[
.advisory.id,
(.advisory.package // "?"),
.advisory.title
] | @tsv
' | column -t -s $'\t' 2>/dev/null | head -50 || echo "(parse failed)"

# Count real vulnerabilities (the blocking kind).
VULN_COUNT="$(echo "$JSON_OUTPUT" | jq -r '(.vulnerabilities.list // []) | length')"
UNM_COUNT="$(echo "$JSON_OUTPUT" | jq -r '(.warnings.unmaintained // []) | length')"
UNS_COUNT="$(echo "$JSON_OUTPUT" | jq -r '(.warnings.unsound // []) | length')"
WARN_COUNT=$((UNM_COUNT + UNS_COUNT))

# Add to GitHub Actions job summary if available.
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
{
echo "## cargo audit"
echo ""
echo "Vulnerabilities (blocking): **$VULN_COUNT**"
echo "Unmaintained/Unsound warnings (non-blocking): **$WARN_COUNT** ($UNM_COUNT unmaintained, $UNS_COUNT unsound)"
echo ""
if [ "$VULN_COUNT" -gt 0 ]; then
echo "### ❌ Real vulnerabilities"
echo "$JSON_OUTPUT" | jq -r '.vulnerabilities.list[] | "- **\(.advisory.id)** (\(.advisory.package)): \(.advisory.title)"'
echo ""
fi
if [ "$WARN_COUNT" -gt 0 ]; then
echo "### ⚠️ Non-blocking warnings (unmaintained/unsound)"
echo ""
echo "These advisories are visible but don't fail the build. They are tracked in the team's fix workstream."
echo ""
echo "$JSON_OUTPUT" | jq -r '
((.warnings.unmaintained // []) + (.warnings.unsound // [])) |
.[] |
"- **\(.advisory.id)** (\(.advisory.package // "?")): \(.advisory.title)"
' | head -30
fi
} >> "$GITHUB_STEP_SUMMARY"
fi

# Decision: fail only on real vulnerabilities.
if [ "$VULN_COUNT" -gt 0 ]; then
echo ""
echo "::error::$VULN_COUNT real vulnerabilities found:"
echo "$JSON_OUTPUT" | jq -r '.vulnerabilities.list[] | " - \(.advisory.id) (\(.advisory.package)): \(.advisory.title)"'
exit 1
fi

echo ""
echo "✅ cargo audit: 0 real vulnerabilities, $WARN_COUNT non-blocking advisory warning(s) (unmaintained/unsound)."
exit 0
Loading
Loading