security(codeql): GAR-491 — Wave 2 suppressions ledger + reapply script (empirical proof PASSED)#109
Merged
michelbr84 merged 2 commits intomainfrom May 1, 2026
Conversation
Establishes the suppression convention for Rust CodeQL alerts in GarraRUST. Rust CodeQL still does NOT support inline `// codeql[...]` comments (github/codeql#21638 open without merge), so the project adopts a versioned ledger + REST API dismissal mechanism per amendment-driven plan §15. Deliverables: * docs/security/codeql-suppressions.md — human-auditable ledger (6 rows). * docs/security/codeql-suppressions.json — machine-readable source (schema 1.0.0) consumed by the reapply script. * scripts/security/codeql-reapply-dismissals.sh — POSIX bash with --dry-run/--apply/--check-md/--alert flags. Fail-closed: validates rule_id, path, and start_line against current alert before any PATCH; exit 2 on mismatch (manual re-audit), exit 3 on stale entry, exit 4 on MD/JSON drift. No automatic schedule (per amendment A8). * docs/security/codeql-setup.md — cross-link to the new ledger; replaces the "TBD suppression syntax" placeholder from PR #106. Empirical-proof status (in flight): * Alert #43 (rust/hard-coded-cryptographic-value @ credentials.rs:49, `vec![0u8; SALT_LEN]` immediately overwritten by SystemRandom::fill) dismissed via gh api PATCH at 2026-05-01T12:33:36Z with reason="false positive". State confirmed dismissed. * Pending: CodeQL re-run on this branch must preserve the dismissed state. If it does, apply remaining 5 dismissals (#40, #41, #42, #44, #45). If it does NOT, abort and open new sub-issue (no global query-filter fallback per amendment A3). Operational rules (ledger §3): * No bulk suppression — each row has per-line justification. * 90-day audit expiration (2026-08-01) forces re-triage. * Fail-closed reaplicação: any drift between live alert and ledger surfaces to human, never auto-fixes. * No global rule silencing as fallback — abort instead. Linear: GAR-491 (Wave 2 of GAR-486 umbrella). Status: In Progress. Plan file: ~/.claude/plans/voc-est-no-repo-inherited-robin.md §15-16. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
Coverage Report (cargo-llvm-cov)Generated by Excluded crates: |
Empirical proof of the REST-dismissal + versioned-ledger mechanism: the dismissal of alert #43 (credentials.rs:49, false positive) at 12:33:36Z PERSISTED across the CodeQL re-run on this branch (run 25214464719 at 12:35:44Z, success). `state=dismissed` and `dismissed_at` were unchanged when re-queried at ~12:43Z. With the mechanism proven, the batch was applied: * 5 remaining alerts (#40, #41, #42, #44, #45) dismissed via `bash scripts/security/codeql-reapply-dismissals.sh --apply` * Final state of all 6 verified — all `{"state":"dismissed"}`. Script bugfix: the idempotent skip check originally compared the ledger snake_case `dismissed_reason` against the API's space-separated form, causing HTTP 400 "Alert is already dismissed." on re-runs. Fixed to compare against the translated `api_reason` (with spaces). A second `--apply` invocation now reports `6 skipped, 0 applied, 0 errors` — proving idempotency. Ledger §5 updated with the run IDs, timestamps, and final verification results. Section §6 (failure handling) was NOT exercised because the proof passed. Linear: GAR-491 — empirical-proof gate cleared. PR ready to mark for review (next commit / `gh pr ready`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Coverage Report (cargo-llvm-cov)Generated by Excluded crates: |
michelbr84
added a commit
that referenced
this pull request
May 1, 2026
The original §1.5 line said "~90 → 71" inheriting that number from the GAR-486 umbrella description (where it was a projection of the paths-ignore effect). Empirical measurement via `gh api .../code-scanning /alerts?state=open --paginate | length` at session start (2026-05-01, Phase 0) returned 90, not 71 — paths-ignore changes the scanning surface but does NOT reduce the open count of pre-existing alerts. The post-GAR-491 measurement is 84 (90 − 6 dismissals from PR #109). This commit replaces the inherited projection with the verified numbers and explains the discrepancy honestly so the umbrella's "~90 → 71" is no longer mismatched against the ROADMAP without context. Linear: GAR-486 — same source as the discrepancy; consider amending the umbrella description or marking the projected "71" as not-materialized in a follow-up comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
michelbr84
added a commit
that referenced
this pull request
May 1, 2026
…ress (#110) * docs(roadmap): refresh 2026-05-01 — Green Security Baseline + Q6 progress Adds §1.5 capturing what changed since 2026-04-13 without rewriting the baseline §1. Updates §7 "Próximos passos imediatos" to reflect the post- sprint priority order. §1.5 covers: * Sprint umbrella GAR-486 (PRs #104..#108) with per-PR commit hashes. * Metric deltas: secret-scanning 1→0, Dependabot 20→7, CodeQL ~90→71 (paths-ignore-driven, not triage), default-setup not-configured, continue-on-error reductions per Lote 2/4. * GAR-491 (Wave 2) in flight via PR #109 with the REST-dismissal + versioned-ledger mechanism — links to the new ledger artifacts. * GAR-490 (Wave 1) Backlog with the `validate_skill_name` + `sanitise_key` (single-segment) + `set_config` plan-of-attack noted so future sessions can pick up without context loss. * Q6 mutation-testing progress: GAR-436 baseline 85.04% → 90.78% killed (PR #94), GAR-463 Q6.1 ✅, GAR-468 Q6.6 ✅, GAR-469 Q6.7 ✅, GAR-481 Q6.8 (Node 24 migration) ✅. * CI Lote 2 (GAR-438) + Lote 4 (GAR-443 data-testid convention) as durable infrastructure improvements. §7 prioritization now leads with closing GAR-491 → GAR-490 → GAR-486 before the Phase 3.4 OpenAPI work resumes; older bullets re-numbered. Linear: GAR-486 (umbrella) — refresh, no status change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(roadmap): correct CodeQL count to empirical 90→84 The original §1.5 line said "~90 → 71" inheriting that number from the GAR-486 umbrella description (where it was a projection of the paths-ignore effect). Empirical measurement via `gh api .../code-scanning /alerts?state=open --paginate | length` at session start (2026-05-01, Phase 0) returned 90, not 71 — paths-ignore changes the scanning surface but does NOT reduce the open count of pre-existing alerts. The post-GAR-491 measurement is 84 (90 − 6 dismissals from PR #109). This commit replaces the inherited projection with the verified numbers and explains the discrepancy honestly so the umbrella's "~90 → 71" is no longer mismatched against the ROADMAP without context. Linear: GAR-486 — same source as the discrepancy; consider amending the umbrella description or marking the projected "71" as not-materialized in a follow-up comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
michelbr84
added a commit
that referenced
this pull request
May 4, 2026
- §1.2.1: cross-link 9 GarraMaxPower sub-issues (GAR-493..501) to the GAR-492 epic. Heading switched from "sugeridas" to "filhas" since the issues already exist in Linear. - §1.5: promote umbrella GAR-486 to Done after GAR-490 (PR #112, 2026-05-04) and GAR-491 (PR #109, 2026-05-01) merged. - §1.5: add 3 short pointers to newly filed follow-ups — GAR-503 (CARGO_BIN_EXE_garraia removal), GAR-504 (benchmark evidence run on DO droplet), GAR-505 (Q6.10 mutation triage of 2026-05-04 run). Detailed scope lives in the Linear issues. ROADMAP keeps short pointers only. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Establishes Rust CodeQL suppression convention for GarraRUST. Rust CodeQL still does NOT support inline
// codeql[...]comments in 2026 (PR github/codeql#21638 open without merge), so the project adopts a versioned ledger + REST API dismissal mechanism.This is GAR-491 (Wave 2) — sub-issue 5/5 of the umbrella GAR-486 (Green Security Baseline 2026-04-30). It unblocks GAR-490 (Wave 1, production triage) by defining the suppression mechanism Wave 1 will use.
What this PR ships
docs/security/codeql-suppressions.md— human-auditable ledger (6 rows, per-line justifications).docs/security/codeql-suppressions.json— machine-readable source (schema 1.0.0) consumed by the script. Per amendment A1, the script never parses Markdown.scripts/security/codeql-reapply-dismissals.sh— POSIX bash, flags--dry-run/--apply/--check-md/--alert <N>. Fail-closed: validatesrule_id+path+start_linefrom the live alert against the ledger before any PATCH; exit 2 on mismatch. Idempotency proven empirically (script bugfix inb455e5dcorrected snake_case vs API space-form comparison).docs/security/codeql-setup.md— cross-link replacing the "TBD suppression syntax" placeholder from PR security(codeql): PR C — advanced setup excluding garraia-desktop (Tauri) #106.Mechanism (ledger §2)
The 280-char comment limit (GitHub API constraint) is handled by truncation in the script; the full justification lives in the ledger. Dismissed reason values use spaces (per the API contract), but the JSON keeps snake_case for shell-friendliness.
Empirical proof — PASSED ✅
Per amendment A3, no global query-filter fallback. The mechanism was proven empirically before the batch was applied: a dismissal must persist across a CodeQL re-run.
state=dismissed,reason="false positive", bymichelbr8434b155b, trigger CodeQL re-runstate=dismissedPERSISTED —dismissed_atunchanged--apply){"state":"dismissed"}✅--apply6 skipped, 0 applied, 0 errorsb455e5dVerdict: ✅ mechanism approved. All 6 dismissals applied, idempotent, persistent across CodeQL re-runs. Final state of all 6 alerts:
Section §6 (failure handling — abort + new sub-issue, no global filter fallback) was NOT exercised because the proof passed.
Scope (6 alerts)
#[tokio::test]Argon2id roundtrip — placeholder salt arg#[tokio::test]lazy upgrade test fixturevec![0u8; SALT_LEN]overwritten bySystemRandom::fill#[test]length-validation negative case#[test]length-validation positive caseMetrics (empirical, before/after this PR)
rust/hard-coded-cryptographic-valueopenOut of scope
rust/hard-coded-cryptographic-valuealerts inadmin/store.rs,admin/handlers.rs,migrate_workspace.rs, and the remaining 6 inmobile_auth.rs:618-736— all look like test fixtures but each needs individual review. Follow-up sub-issueGAR-491.1.actions/missing-workflow-permissions+ 10cleartext-storage-database+ 6 cleartext-logging + 4 cleartext-transmission + 4js/*— separate triage.GAR-491.2after at least one weekly CodeQL cycle without regression.Test plan (all completed)
bash scripts/security/codeql-reapply-dismissals.sh --check-md→ exits 0 (6 entries in sync)bash scripts/security/codeql-reapply-dismissals.sh --dry-run --alert 43→ fail-closed validation passesbash scripts/security/codeql-reapply-dismissals.sh --apply --alert 43→ PATCH succeeded (12:33:36Z)gh api repos/michelbr84/GarraRUST/code-scanning/alerts/43 --jq '.state'returned"dismissed"← empirical proof gate cleared--apply(no--alertfilter) — 5/5 successfor n in 40 41 42 43 44 45; do gh api ... ; done--applyrun reported6 skipped, 0 applied, 0 errorsb455e5d(run 25215027790 CI + 25215027800 CodeQL)Linear
Policy guardrails active
--no-verify/ hook bypass🤖 Generated with Claude Code