fix(deps): clear 6 reachable RustSec advisories, accept 3 unreachable ones #316

Merged
maximus merged 2 commits from issue-310-rustsec-advisories into main 2026-07-28 00:38:12 +00:00
Owner

Resolves #310

cargo audit passe de 9 vulnérabilités à 0 sur src-tauri/Cargo.lock, sans toucher Cargo.toml.

Ce que fait la PR

Six advisories atteignables — corrigées. cargo update -p rustls-webpki -p tar : rustls-webpki 0.103.9 → 0.103.13 (RUSTSEC-2026-0049 / -0098 / -0099 / -0104) et tar 0.4.44 → 0.4.46 (RUSTSEC-2026-0067 / -0068). Les deux tiennent dans les bornes existantes du manifeste. Elles sont sous tauri-plugin-updater — téléchargement et décompression des mises à jour — donc réellement dans le binaire livré.

Trois advisories ni corrigeables ni atteignables — acceptées explicitement, dans un .cargo/audit.toml versionné, lu par les deux workflows sans qu'aucun n'ait à le savoir :

Advisory Crate Pourquoi acceptée
RUSTSEC-2026-0194 / -0195 quick-xml 0.38.4 (7.5 high ×2) Compilé sur aucune cible livrée — tiré par plist, dont tauri ne dépend que pour le bundling Apple. Corrigé en >= 0.41.0 alors que plist exige ^0.38 : [patch.crates-io] ne franchit pas cette frontière.
RUSTSEC-2023-0071 rsa 0.9.10 (5.9 medium) Aucun correctif publié (patched vide) et jamais compilé : seul parent sqlx-mysql, artefact du graphe multi-backend de sqlx sur un projet SQLite.

Laisser ces trois-là rougir le gate quotidien pour toujours reproduirait la perte de signal que #232 avait supprimée en retirant le || true — une alarme toujours rouge n'est plus une alarme. C'est le raisonnement de l'ADR 0018.

Preuves, contre le lock d'après le bump

$ cargo tree -i quick-xml --target x86_64-pc-windows-msvc     -> (vide)
$ cargo tree -i quick-xml --target x86_64-unknown-linux-gnu   -> (vide)
$ cargo tree -i quick-xml --target x86_64-apple-darwin        -> quick-xml <- plist <- tauri
$ cargo tree -i rsa --target all                              -> (vide)

$ cargo-audit audit --file src-tauri/Cargo.lock
    Scanning src-tauri/Cargo.lock for vulnerabilities (666 crate dependencies)
warning: 23 allowed warnings found
$ echo $?
0

cargo-audit 0.22.2, advisory-db 0bfde9d6 (2026-07-27). Les 23 warning sont inchangés — mesuré, pas supposé : les advisories supprimées sont retirées, pas requalifiées en warning.

Le garde-fou, et pourquoi il existe

L'atteignabilité est une propriété du graphe résolu aujourd'hui. Un bump tauri/plist rendant quick-xml inconditionnel laisserait la suppression masquer une advisory vivante, et l'audit resterait vert : l'inverse exact du rouge permanent qu'on corrige ici.

check-rust.yml gagne donc une étape bloquante qui rejoue la preuve pour chaque crate supprimé, sur les deux cibles livrées. Le scénario qui périmerait la liste est lui-même une modification de src-tauri/, soit précisément ce qui déclenche ce workflow. Trois détails la rendent fiable plutôt que décorative :

  • le code de sortie de cargo tree est testé séparément de sa sortie — un crate absent sort en 0 avec un stdout vide, et un cargo tree en échec aussi ; sans cette distinction, une panne de l'outil se lirait comme une preuve d'absence ;
  • un canari (tar, réellement présent) doit être trouvé à chaque run, sinon le silence de la boucle ne prouve rien ;
  • --locked, pour que cargo tree ne réécrive pas le lock contre lequel l'audit a été pris.

Testé localement dans les deux sens : sort en 0 sur le graphe actuel, et détecte bien tar quand on le lui donne comme cible.

Dérive de Cargo.lock à expliquer

Le diff du lock fait 11+/11−, dont 7 lignes qui ne sont pas le bump. Ce n'est pas un artefact de mon invocation : --precise donne exactement le même résultat.

Sept crates repointent leur dépendance windows-sys de 0.61.2 vers 0.48.0 ou 0.59.0 — des versions déjà présentes dans le lock. Vérifié :

  • 666 paquets avant, 666 après : aucun ajout, aucun retrait ;
  • l'ensemble des versions de windows-sys présentes est identique avant/après ;
  • les crates concernés (colored, dirs-sys, errno, rustix, tempfile, winapi-util, winapi-i686-pc-windows-gnu) portent une dépendance windows-sys conditionnelle Windows — sur Linux le changement est un no-op complet.

C'est la re-résolution de cargo 1.94.1 sur des bornes larges, pas une dérive de dépendances.

Portée additionnelle, et pourquoi

  • .cargo/** ajouté aux paths de check-rust.yml — le répertoire entier, pas le chemin exact : un futur .cargo/config.toml (rustflags, linker) changerait le build Rust et sauterait la CI Rust sans que personne ne le voie. Argument repris du propre en-tête de check-frontend.yml.
  • .cargo/** ajouté aux paths-ignore de check-frontend.yml — une PR d'audit ne doit pas consommer un job frontend sur un runner à capacité 1.
  • audit.yml, docs/architecture.md et CLAUDE.md disent maintenant explicitement qu'un run vert signifie « zéro advisory hors liste », pas « zéro advisory ». Le contrat du gate a changé, il doit se lire comme tel.
  • Entrée ### Security / ### Sécurité dans les deux CHANGELOG, sur le modèle de #235-#238 / #241. À noter pour la revue : .claude/rules/changelog.md ne liste que Added/Changed/Fixed/Removed — la catégorie Security repose sur ce précédent, pas sur la règle écrite.

Suivis ouverts, pas traités ici

  • #312 — retirer les suppressions quick-xml quand plist/tauri passera à >= 0.41.0. C'est le pendant du garde-fou : celui-ci attrape la suppression devenue injustifiée, #312 attrape la suppression devenue inutile, que rien ne signale.
  • #313tauri-plugin-deep-link 2.4.8 est yanked, et c'est une dépendance directe (src-tauri/Cargo.toml:28). Les crates yanked remontent en warning et ne comptent pas dans le code de sortie : ils ne font pas partie de ce qui rend l'audit vert.
  • #314audit.yml n'a jamais été déclenché : zéro run d'événement schedule sur les 420 tâches de l'historique Actions. Un workflow_dispatch vert prouve que la commande sort en 0, pas que l'alarme quotidienne existe. À ne pas confondre en relisant cette PR.
  • #315tar et rustls-webpki ne sont ici que compilés. Une régression de comportement (le correctif tar touche justement unpack_in et les en-têtes PAX) ne se verrait qu'à la mise à jour, chez l'utilisateur. Le skill /release ne teste aujourd'hui aucun vrai cycle téléchargement+extraction.

Validation locale

  • cargo check --all-targets vert
  • cargo test --all-targets : 106 passed, 0 failed
  • npm run build (tsc + vite) vert
  • npm test : 871 passed (54 fichiers)
  • cargo audit : exit 0
  • garde-fou : exit 0, canari trouvé

Signal pré-merge

audit.yml n'a pas de trigger pull_request et l'étape cargo audit de check-rust.yml est continue-on-error — le workflow dont on modifie la configuration ne tourne donc pas sur cette PR. La preuve pré-merge à lire est le log de cette étape non bloquante, plus le workflow_dispatch lancé sur la branche. Ajouter un trigger pull_request à audit.yml a été écarté : ça ferait tourner deux fois l'audit sur chaque PR Rust, à contre-courant de #232 sur un runner à capacité 1.

Resolves #310 `cargo audit` passe de **9 vulnérabilités à 0** sur `src-tauri/Cargo.lock`, sans toucher `Cargo.toml`. ## Ce que fait la PR **Six advisories atteignables — corrigées.** `cargo update -p rustls-webpki -p tar` : `rustls-webpki` 0.103.9 → **0.103.13** (RUSTSEC-2026-0049 / -0098 / -0099 / -0104) et `tar` 0.4.44 → **0.4.46** (RUSTSEC-2026-0067 / -0068). Les deux tiennent dans les bornes existantes du manifeste. Elles sont sous `tauri-plugin-updater` — téléchargement et décompression des mises à jour — donc réellement dans le binaire livré. **Trois advisories ni corrigeables ni atteignables — acceptées explicitement**, dans un `.cargo/audit.toml` versionné, lu par les deux workflows sans qu'aucun n'ait à le savoir : | Advisory | Crate | Pourquoi acceptée | |---|---|---| | RUSTSEC-2026-0194 / -0195 | `quick-xml` 0.38.4 (7.5 high ×2) | Compilé sur aucune cible livrée — tiré par `plist`, dont `tauri` ne dépend que pour le bundling Apple. Corrigé en `>= 0.41.0` alors que `plist` exige `^0.38` : `[patch.crates-io]` ne franchit pas cette frontière. | | RUSTSEC-2023-0071 | `rsa` 0.9.10 (5.9 medium) | Aucun correctif publié (`patched` vide) **et** jamais compilé : seul parent `sqlx-mysql`, artefact du graphe multi-backend de sqlx sur un projet SQLite. | Laisser ces trois-là rougir le gate quotidien pour toujours reproduirait la perte de signal que #232 avait supprimée en retirant le `|| true` — une alarme toujours rouge n'est plus une alarme. C'est le raisonnement de l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). ## Preuves, contre le lock d'après le bump ``` $ cargo tree -i quick-xml --target x86_64-pc-windows-msvc -> (vide) $ cargo tree -i quick-xml --target x86_64-unknown-linux-gnu -> (vide) $ cargo tree -i quick-xml --target x86_64-apple-darwin -> quick-xml <- plist <- tauri $ cargo tree -i rsa --target all -> (vide) $ cargo-audit audit --file src-tauri/Cargo.lock Scanning src-tauri/Cargo.lock for vulnerabilities (666 crate dependencies) warning: 23 allowed warnings found $ echo $? 0 ``` `cargo-audit` **0.22.2**, advisory-db **0bfde9d6** (2026-07-27). Les 23 `warning` sont **inchangés** — mesuré, pas supposé : les advisories supprimées sont retirées, pas requalifiées en warning. ## Le garde-fou, et pourquoi il existe L'atteignabilité est une propriété du graphe **résolu aujourd'hui**. Un bump `tauri`/`plist` rendant `quick-xml` inconditionnel laisserait la suppression masquer une advisory vivante, et l'audit resterait vert : l'inverse exact du rouge permanent qu'on corrige ici. `check-rust.yml` gagne donc une étape **bloquante** qui rejoue la preuve pour chaque crate supprimé, sur les deux cibles livrées. Le scénario qui périmerait la liste est lui-même une modification de `src-tauri/`, soit précisément ce qui déclenche ce workflow. Trois détails la rendent fiable plutôt que décorative : - le **code de sortie** de `cargo tree` est testé séparément de sa sortie — un crate absent sort en 0 avec un stdout vide, et un `cargo tree` en échec aussi ; sans cette distinction, une panne de l'outil se lirait comme une preuve d'absence ; - un **canari** (`tar`, réellement présent) doit être trouvé à chaque run, sinon le silence de la boucle ne prouve rien ; - `--locked`, pour que `cargo tree` ne réécrive pas le lock contre lequel l'audit a été pris. Testé localement dans les deux sens : sort en 0 sur le graphe actuel, et détecte bien `tar` quand on le lui donne comme cible. ## Dérive de `Cargo.lock` à expliquer Le diff du lock fait 11+/11−, dont **7 lignes qui ne sont pas le bump**. Ce n'est pas un artefact de mon invocation : `--precise` donne exactement le même résultat. Sept crates repointent leur dépendance `windows-sys` de 0.61.2 vers 0.48.0 ou 0.59.0 — des versions **déjà présentes dans le lock**. Vérifié : - **666 paquets avant, 666 après** : aucun ajout, aucun retrait ; - l'ensemble des versions de `windows-sys` présentes est **identique** avant/après ; - les crates concernés (`colored`, `dirs-sys`, `errno`, `rustix`, `tempfile`, `winapi-util`, `winapi-i686-pc-windows-gnu`) portent une dépendance `windows-sys` **conditionnelle Windows** — sur Linux le changement est un no-op complet. C'est la re-résolution de cargo 1.94.1 sur des bornes larges, pas une dérive de dépendances. ## Portée additionnelle, et pourquoi - `.cargo/**` ajouté aux `paths` de `check-rust.yml` — le répertoire entier, pas le chemin exact : un futur `.cargo/config.toml` (rustflags, linker) changerait le build Rust et sauterait la CI Rust sans que personne ne le voie. Argument repris du propre en-tête de `check-frontend.yml`. - `.cargo/**` ajouté aux `paths-ignore` de `check-frontend.yml` — une PR d'audit ne doit pas consommer un job frontend sur un runner à capacité 1. - `audit.yml`, `docs/architecture.md` et `CLAUDE.md` disent maintenant explicitement qu'**un run vert signifie « zéro advisory hors liste »**, pas « zéro advisory ». Le contrat du gate a changé, il doit se lire comme tel. - Entrée `### Security` / `### Sécurité` dans les deux CHANGELOG, sur le modèle de #235-#238 / #241. À noter pour la revue : `.claude/rules/changelog.md` ne liste que Added/Changed/Fixed/Removed — la catégorie Security repose sur ce précédent, pas sur la règle écrite. ## Suivis ouverts, pas traités ici - **#312** — retirer les suppressions `quick-xml` quand `plist`/`tauri` passera à `>= 0.41.0`. C'est le pendant du garde-fou : celui-ci attrape la suppression devenue *injustifiée*, #312 attrape la suppression devenue *inutile*, que rien ne signale. - **#313** — `tauri-plugin-deep-link 2.4.8` est **yanked**, et c'est une dépendance directe (`src-tauri/Cargo.toml:28`). Les crates yanked remontent en `warning` et **ne comptent pas dans le code de sortie** : ils ne font pas partie de ce qui rend l'audit vert. - **#314** — `audit.yml` **n'a jamais été déclenché** : zéro run d'événement `schedule` sur les 420 tâches de l'historique Actions. Un `workflow_dispatch` vert prouve que la commande sort en 0, **pas** que l'alarme quotidienne existe. À ne pas confondre en relisant cette PR. - **#315** — `tar` et `rustls-webpki` ne sont ici que *compilés*. Une régression de comportement (le correctif `tar` touche justement `unpack_in` et les en-têtes PAX) ne se verrait qu'à la mise à jour, chez l'utilisateur. Le skill `/release` ne teste aujourd'hui aucun vrai cycle téléchargement+extraction. ## Validation locale - `cargo check --all-targets` vert - `cargo test --all-targets` : **106 passed, 0 failed** - `npm run build` (tsc + vite) vert - `npm test` : **871 passed** (54 fichiers) - `cargo audit` : exit 0 - garde-fou : exit 0, canari trouvé ## Signal pré-merge `audit.yml` n'a pas de trigger `pull_request` et l'étape `cargo audit` de `check-rust.yml` est `continue-on-error` — le workflow dont on modifie la configuration ne tourne donc pas sur cette PR. La preuve pré-merge à lire est le **log de cette étape non bloquante**, plus le `workflow_dispatch` lancé sur la branche. Ajouter un trigger `pull_request` à `audit.yml` a été écarté : ça ferait tourner deux fois l'audit sur chaque PR Rust, à contre-courant de #232 sur un runner à capacité 1.
maximus added 1 commit 2026-07-27 23:46:12 +00:00
fix(deps): clear 6 reachable RustSec advisories, accept 3 unreachable ones
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m38s
PR Check — Rust / rust (pull_request) Successful in 8m40s
f4b09b028e
cargo update -p rustls-webpki -p tar moves rustls-webpki 0.103.9 -> 0.103.13
and tar 0.4.44 -> 0.4.46, both within the existing Cargo.toml bounds. They sit
under tauri-plugin-updater, which downloads and unpacks application updates, so
all six of their advisories were reachable in the shipped binary.

The remaining three can neither be fixed nor reached. quick-xml (2x 7.5 high)
is pulled by plist, which tauri only needs for Apple bundling: its per-target
trees are empty for both shipped targets and it appears solely under
x86_64-apple-darwin. Its fix is >= 0.41.0 while plist requires ^0.38, a
semver-incompatible boundary [patch.crates-io] cannot cross. rsa has no
published fix at all and is never compiled — its only parent is sqlx-mysql, an
artifact of sqlx's multi-backend graph on a SQLite project.

Leaving those three to red the daily gate forever would reproduce the signal
loss that #232 removed the `|| true` to fix, so they move into a versioned
.cargo/audit.toml. Entries are keyed by advisory ID, never by crate, so a new
advisory against the same crate still reds the gate; each carries its
reachability proof and its removal condition.

A blocking step in check-rust.yml re-proves that justification on every PR
touching src-tauri/ or .cargo/, and fails if a suppressed crate enters a
shipped target's graph — the scenario that would rot the list is itself a
src-tauri change. It separates cargo tree's exit status from its output (an
absent crate and a failed invocation both print nothing) and asserts a canary
crate is still found, so its silence proves something.

cargo audit: 9 vulnerabilities -> 0, warnings unchanged at 23
(cargo-audit 0.22.2, advisory-db 0bfde9d6 of 2026-07-27).
cargo check + cargo test green (106 tests); npm build + 871 vitest green.

Resolves #310

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
maximus added 1 commit 2026-07-28 00:00:12 +00:00
ci: make the suppression guard log every check, not just failures
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m54s
PR Check — Rust / rust (pull_request) Successful in 9m3s
e3dc794a09
The guard emitted nothing when it passed, so its success was indistinguishable
in the CI log from the step never running at all — the same silent-skip failure
mode it exists to catch, one level up. Confirmed on run 332: the job was green
and the log carried no trace of the step either way.

Each crate/target check and the canary now echo their result, followed by a
count and the exit code, so a reader can see the guard ran and what it proved.

Verified by extracting the run: block from the workflow and executing it
verbatim under bash -e: 4 checks, canary found, exit 0.
maximus merged commit e3dc794a09 into main 2026-07-28 00:38:12 +00:00
maximus deleted branch issue-310-rustsec-advisories 2026-07-28 00:38:12 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#316
No description provided.