fix(deps): update rustls to 0.23.45 to clear RUSTSEC-2026-0285 #349

Merged
maximus merged 2 commits from issue-348-rustls-rustsec-2026-0285 into main 2026-09-22 00:33:54 +00:00
Owner

Corrige l'unique vulnérabilité qui rougit audit.yml tous les matins depuis le 2026-09-15 (runs 405 → 411, 7 rouges consécutifs ; dernier vert le run 404). Aucun push sur main dans la fenêtre — l'advisory est parue le 09-14, après le tir de ce matin-là.

Le diff

4 lignes dans src-tauri/Cargo.lock, 2 strophes. Cargo.toml intouché, 666 paquets avant et après.

crate avant après
rustls 0.23.36 0.23.45
rustls-webpki 0.103.13 0.103.15

Le mouvement de rustls-webpki est requis, pas opportuniste : rustls 0.23.45 resserre sa borne de ^0.103.5 à ^0.103.14, et 0.103.13 ne la satisfait plus. Même forme que le http ^1 → ^1.1 relevé par la revue de #344 sur h2, mais cette fois contraignante. La 0.103.15 est un mouvement vers l'avant depuis la 0.103.13 posée par #310 : ces quatre correctifs sont conservés. Les listes dependencies des deux strophes sont inchangées.

Plus deux entrées de CHANGELOG (EN + FR) sous [Unreleased] / [Non publié].

Atteignabilité — un seul chemin, plus étroit qu'en #343

Par triple explicite, jamais --target all. Arbre identique sur les deux cibles livrées :

rustls 0.23.36 → hyper-rustls / rustls-platform-verifier / tokio-rustls
               → reqwest 0.13.2 → tauri-plugin-updater 2.10.0 → simpl-result

C'est la couche TLS de la mise à jour automatique uniquement. Le reqwest que l'app déclare elle-même (Cargo.toml:43, 0.12.28) passe par hyper-tls → native-tls → openssl : licence, authentification, cours et rétroaction n'ont jamais été sur ce chemin, contrairement à ce qui était vrai pour h2.

Règle 1 de .cargo/audit.toml — correctif publié + crate atteignable = corriger, pas supprimer. Le fichier de suppressions et le garde-fou de check-rust.yml (CRATES="rsa") sont inchangés.

La dérive windows-sys ne s'est pas déclenchée — #345 est à corriger

#345 énonce que tout bump atteignant le sous-arbre réseau/TLS fait redescendre les 7 pointeurs windows-sys de 0.61.2. rustls est au cœur de ce sous-arbre et rien n'a bougé : les 6 versions présentes sont identiques avant/après, et un diff sur toutes les lignes mentionnant windows-sys est vide. Le déclencheur tient à hyper et à ce qu'il tire, pas à la couche TLS en général.

Conséquence : pas de strophe écrite à la main ici, contrairement à #344. Cargo a écrit le fichier lui-même, donc les checksums viennent de l'index plutôt que du rédacteur de la PR.

Le corps de #345 mérite d'être corrigé sur ce point ; sa décision de fond (garde-fou + ADR) reste entière — c'est justement l'absence de garde qui oblige à re-mesurer à chaque fois.

Vérifications

Contrôle Résultat
cargo-audit 0.22.2 sur le lock d'avant exit 1, error: 1 vulnerability found! — l'outil local reproduit le rouge de la CI
cargo-audit 0.22.2 sur le lock corrigé exit 0, 12 warnings autorisés, zéro vulnérabilité
cargo metadata --locked exit 0, lock non réécrit
Checksums sha256sum des .crate téléchargés = lock, pour les deux crates ; Compiling rustls v0.23.45 / Checking rustls-webpki v0.103.15 prouvent que ces archives ont servi
cargo check --locked exit 0
cargo test --locked 111 passed, 0 failed
Garde-fou des suppressions rejoué Suppression guard: 2 checks, exit 0, canari tar trouvé

Le contrôle sur le lock d'avant est là pour que le vert veuille dire quelque chose : sans lui, un exit 0 pourrait aussi bien venir d'un outil mal configuré.

Après merge

Rejouer audit.yml en workflow_dispatch sur main pour prouver le vert plutôt que le déduire du run de PR — l'étape cargo audit de check-rust.yml est continue-on-error: true, un job vert n'y prouve rien.

Resolves #348

🤖 Generated with Claude Code

Corrige l'unique vulnérabilité qui rougit `audit.yml` tous les matins depuis le 2026-09-15 (runs 405 → 411, 7 rouges consécutifs ; dernier vert le run 404). Aucun push sur `main` dans la fenêtre — l'advisory est parue le 09-14, après le tir de ce matin-là. ## Le diff 4 lignes dans `src-tauri/Cargo.lock`, 2 strophes. `Cargo.toml` intouché, 666 paquets avant et après. | crate | avant | après | |---|---|---| | `rustls` | 0.23.36 | **0.23.45** | | `rustls-webpki` | 0.103.13 | **0.103.15** | Le mouvement de `rustls-webpki` est **requis**, pas opportuniste : rustls 0.23.45 resserre sa borne de `^0.103.5` à `^0.103.14`, et 0.103.13 ne la satisfait plus. Même forme que le `http ^1 → ^1.1` relevé par la revue de #344 sur `h2`, mais cette fois contraignante. La 0.103.15 est un mouvement vers l'avant depuis la 0.103.13 posée par #310 : ces quatre correctifs sont conservés. Les listes `dependencies` des deux strophes sont inchangées. Plus deux entrées de CHANGELOG (EN + FR) sous `[Unreleased]` / `[Non publié]`. ## Atteignabilité — un seul chemin, plus étroit qu'en #343 Par triple explicite, jamais `--target all`. Arbre identique sur les deux cibles livrées : ``` rustls 0.23.36 → hyper-rustls / rustls-platform-verifier / tokio-rustls → reqwest 0.13.2 → tauri-plugin-updater 2.10.0 → simpl-result ``` C'est la couche TLS de la **mise à jour automatique** uniquement. Le `reqwest` que l'app déclare elle-même (`Cargo.toml:43`, 0.12.28) passe par `hyper-tls → native-tls → openssl` : licence, authentification, cours et rétroaction n'ont jamais été sur ce chemin, contrairement à ce qui était vrai pour `h2`. Règle 1 de `.cargo/audit.toml` — correctif publié + crate atteignable = corriger, pas supprimer. Le fichier de suppressions et le garde-fou de `check-rust.yml` (`CRATES="rsa"`) sont inchangés. ## La dérive `windows-sys` ne s'est pas déclenchée — #345 est à corriger #345 énonce que tout bump atteignant le sous-arbre réseau/TLS fait redescendre les 7 pointeurs `windows-sys` de `0.61.2`. `rustls` est au cœur de ce sous-arbre et **rien n'a bougé** : les 6 versions présentes sont identiques avant/après, et un `diff` sur toutes les lignes mentionnant `windows-sys` est vide. Le déclencheur tient à `hyper` et à ce qu'il tire, pas à la couche TLS en général. Conséquence : **pas de strophe écrite à la main** ici, contrairement à #344. Cargo a écrit le fichier lui-même, donc les checksums viennent de l'index plutôt que du rédacteur de la PR. Le corps de #345 mérite d'être corrigé sur ce point ; sa décision de fond (garde-fou + ADR) reste entière — c'est justement l'absence de garde qui oblige à re-mesurer à chaque fois. ## Vérifications | Contrôle | Résultat | |---|---| | `cargo-audit 0.22.2` sur le lock **d'avant** | exit **1**, `error: 1 vulnerability found!` — l'outil local reproduit le rouge de la CI | | `cargo-audit 0.22.2` sur le lock corrigé | exit **0**, 12 warnings autorisés, zéro vulnérabilité | | `cargo metadata --locked` | exit 0, lock **non réécrit** | | Checksums | `sha256sum` des `.crate` téléchargés = lock, pour les deux crates ; `Compiling rustls v0.23.45` / `Checking rustls-webpki v0.103.15` prouvent que ces archives ont servi | | `cargo check --locked` | exit 0 | | `cargo test --locked` | **111 passed, 0 failed** | | Garde-fou des suppressions rejoué | `Suppression guard: 2 checks, exit 0`, canari `tar` trouvé | Le contrôle sur le lock d'avant est là pour que le vert veuille dire quelque chose : sans lui, un exit 0 pourrait aussi bien venir d'un outil mal configuré. ## Après merge Rejouer `audit.yml` en `workflow_dispatch` **sur `main`** pour prouver le vert plutôt que le déduire du run de PR — l'étape `cargo audit` de `check-rust.yml` est `continue-on-error: true`, un job vert n'y prouve rien. Resolves #348 🤖 Generated with [Claude Code](https://claude.com/claude-code)
maximus added the
status:review
type:security
source:analyste
labels 2026-09-22 00:10:11 +00:00
maximus added 1 commit 2026-09-22 00:10:12 +00:00
fix(deps): update rustls to 0.23.45 to clear RUSTSEC-2026-0285
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 9m17s
8ea3410c82
The daily audit has failed every morning since 2026-09-15 (runs 405 to
411, 7 consecutive reds). Nothing was pushed to main in that window —
the last commit is 97ee3c3 from 09-13. RUSTSEC-2026-0285 was published
on 09-14, after that morning's run, and the first red is the next day's.
Rustls accepted TLS 1.3 handshake messages sent at the wrong encryption
level when they followed a key-changing message inside the same record,
where RFC 8446 section 5.1 requires closing the connection instead.
Medium severity, confidentiality only: the handshake transcript stays
authenticated, so this cannot be used to alter or complete a handshake
from a network position. Patched in 0.23.45.

rustls is reachable on both shipped targets, checked per triple rather
than with --target all, by a single path: tauri-plugin-updater ->
reqwest 0.13.2, the automatic update check and download. That is
narrower than h2 in #343 — the app's own reqwest 0.12.28 goes through
hyper-tls and native-tls, so the licence, auth, price and feedback calls
were never on this path. A published fix plus a reachable crate is rule
1 of .cargo/audit.toml, so this gets fixed rather than suppressed; the
suppression list and the check-rust guard are both untouched.

rustls-webpki moves with it, 0.103.13 to 0.103.15, because 0.23.45
tightens its bound from ^0.103.5 to ^0.103.14. That is required rather
than collateral, and it keeps the four advisories #310 cleared by
pinning 0.103.13.

Unlike #344, no stanza was hand-written: `cargo update -p rustls
--precise 0.23.45` left the seven windows-sys pointers on 0.61.2
untouched, so cargo's own output was kept. That also narrows the premise
of #345 — the drift is triggered by hyper and what it pulls, not by the
TLS subtree at large, since rustls sits squarely in it and moved
nothing. 666 packages before and after, Cargo.toml untouched, and
`cargo metadata --locked` accepts the result without rewriting it.

Verified: cargo check --locked and cargo test --locked green (111
passed), cargo-audit 0.22.2 exits 0 with 12 allowed warnings, and the
same binary still exits 1 on the previous lockfile — so the green is a
real change of state, not a differently configured tool. Both checksums
match the sha256 of the downloaded .crate archives, and compiling rustls
0.23.45 and rustls-webpki 0.103.15 proves those archives were the ones
actually used.

Resolves #348

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
Owner

Verdict : APPROVE

Revue adversariale : chaque affirmation structurante du corps a été re-tracée depuis la source plutôt que relayée, et le contrôle sur le lock d'avant a été rejoué avec le même binaire. Aucune n'a été prise en défaut.

Ce qui a été re-prouvé indépendamment

Affirmation Vérification Résultat
RUSTSEC-2026-0285 rougit le lock d'avant cargo-audit 0.22.2 -f sur origin/main:Cargo.lock, advisory-db du 09-21 17:17 exit 1, rustls 0.23.36, Severity: 5.3 (medium), Solution: Upgrade to >=0.23.45
Le lock corrigé est propre même binaire, .cargo/audit.toml lu depuis la racine exit 0, 12 warnings autorisés, zéro vulnérabilité
Checksums comparés à l'index crates.io (index.crates.io/ru/st/rustls), pas au sha256sum du rédacteur identiques pour les deux crates, aucune des deux versions n'est yanked
Borne ^0.103.5 → ^0.103.14 champ deps des deux versions dans l'index (dépendance renommée webpki, package = "rustls-webpki") exact — 0.103.13 ne satisfait plus la borne, le mouvement est contraint et non opportuniste
Chemin unique cargo tree -i rustls par triple explicite, Linux et Windows arbre inverse identique sur les deux, seule racine tauri-plugin-updater → reqwest 0.13.2
« licence / auth / cours / rétroaction jamais sur ce chemin » reqwest@0.12.28 → hyper-tls → native-tls → openssl, et absent de l'arbre inverse complet de rustls sur les deux cibles prouvé, pas seulement affirmé
Aucune dérive windows-sys diff sur toutes les lignes mentionnant windows-sys dans les deux locks vide ; les 6 versions présentes (0.45 / 0.48 / 0.52 / 0.59 / 0.60.2 / 0.61.2) sont inchangées
Aucune nouvelle dépendance transitive diff des listes dependencies des 2 strophes ; 666 paquets et 7279 lignes avant/après listes identiques
cargo metadata --locked ne réécrit pas md5 du lock avant / après identique

Les deux versions retenues sont par ailleurs les dernières stables publiées (0.23.45, 0.103.15), et l'advisory locale confirme la sévérité annoncée : CVSS:3.1/…/C:L/I:N/A:N, soit confidentialité seulement.

CI — le log prouve les étapes, pas seulement le vert

Run 412 (task 552, workflow rust, Job succeeded). Log lu ligne à ligne parce que l'étape cargo audit de check-rust.yml est continue-on-error: true et qu'un job vert n'y prouve rien :

  • garde-fou exécuté et tracé : ok: rsa absent from x86_64-unknown-linux-gnu, idem x86_64-pc-windows-msvc, ok: canary 'tar' found, Suppression guard: 2 checks, exit 0 ;
  • test result: ok. 111 passed; 0 failed ;
  • Downloaded rustls v0.23.45 → Compiling rustls v0.23.45, idem rustls-webpki v0.103.15 : les archives derrière les checksums du lock sont bien celles qui ont servi ;
  • Scanning src-tauri/Cargo.lock for vulnerabilities (666 crate dependencies), aucune ligne error:.

check-frontend a été correctement sauté par sa denylist (2 .md + Cargo.lock) et check-rust déclenché par le glob src-tauri/** — même forme de cas test isolé qu'en #344.

Chronologie vérifiée

Runs 405 → 411 = 7 échecs consécutifs d'audit (09-15 → 09-21), dernier vert 404 (09-14) ; dernier commit sur main = 97ee3c3 du 09-13. La fenêtre est bien vide de push et l'advisory est datée du 09-14. Le corps est exact au numéro de run près.

Resolves #348 figure dans le message de commit, pas seulement dans le corps de la PR — la fermeture aura bien lieu. Format conventionnel respecté (fix(deps): …).

Suggestions (non bloquantes)

  1. Le correctif n'atteint aucun poste avant un tag. Le composant vulnérable est le chemin de mise à jour lui-même : les installations en v0.15.0 restent sur rustls 0.23.36 tant qu'aucune version n'est publiée. Sans urgence (5.3, confidentialité seulement, transcription toujours authentifiée, et le serveur de release n'émet pas de poignée de main non conforme), mais le choix mérite d'être tranché explicitement plutôt que par défaut : v0.15.1 ou attente du prochain lot.
  2. CLAUDE.md ne liste pas la catégorie Security / Sécurité (il n'énonce que « Added/Ajouté, Changed/Modifié, Fixed/Corrigé, Removed/Supprimé »), alors que les deux fichiers en comptent déjà 5 usages chacun, et 6 avec celui-ci. Dérive de doc préexistante, à corriger la prochaine fois que CLAUDE.md est touché.
  3. « Aucun changement de comportement » est vrai du code de l'app, pas de la couche TLS : une poignée de main qui viole la RFC 8446 §5.1 est désormais fermée au lieu d'être acceptée. Sans effet pratique ici, la nuance vaut une demi-phrase si l'entrée est relue au moment du tag.

Rendu in-app contrôlé au passage : ChangelogContent affiche l'intitulé de section tel quel (donc déjà localisé par le choix du fichier) et UpdateCard rend les ### en sous-titre dans une boîte scrollable. La puce de 1058 caractères reste sous le maximum déjà présent dans la section v0.15.0 (1180) et loin du maximum du fichier (2396) — la verbosité est dans le précédent du projet.

Après merge, le workflow_dispatch d'audit.yml sur main annoncé dans le corps est la bonne étape finale : le vert du run de PR ne prouve rien.


🤖 Revue générée par /pr-review

## Verdict : APPROVE Revue adversariale : chaque affirmation structurante du corps a été re-tracée depuis la source plutôt que relayée, et le contrôle sur le lock d'avant a été rejoué avec le même binaire. Aucune n'a été prise en défaut. ### Ce qui a été re-prouvé indépendamment | Affirmation | Vérification | Résultat | |---|---|---| | RUSTSEC-2026-0285 rougit le lock d'avant | `cargo-audit 0.22.2 -f` sur `origin/main:Cargo.lock`, advisory-db du 09-21 17:17 | exit **1**, `rustls 0.23.36`, `Severity: 5.3 (medium)`, `Solution: Upgrade to >=0.23.45` | | Le lock corrigé est propre | même binaire, `.cargo/audit.toml` lu depuis la racine | exit **0**, 12 warnings autorisés, zéro vulnérabilité | | Checksums | comparés à l'**index crates.io** (`index.crates.io/ru/st/rustls`), pas au `sha256sum` du rédacteur | identiques pour les deux crates, aucune des deux versions n'est *yanked* | | Borne `^0.103.5` → `^0.103.14` | champ `deps` des deux versions dans l'index (dépendance renommée `webpki`, `package = "rustls-webpki"`) | exact — 0.103.13 ne satisfait plus la borne, le mouvement est **contraint** et non opportuniste | | Chemin unique | `cargo tree -i rustls` par triple explicite, Linux **et** Windows | arbre inverse identique sur les deux, seule racine `tauri-plugin-updater → reqwest 0.13.2` | | « licence / auth / cours / rétroaction jamais sur ce chemin » | `reqwest@0.12.28` → `hyper-tls → native-tls → openssl`, et absent de l'arbre inverse **complet** de `rustls` sur les deux cibles | prouvé, pas seulement affirmé | | Aucune dérive `windows-sys` | `diff` sur **toutes** les lignes mentionnant `windows-sys` dans les deux locks | vide ; les 6 versions présentes (0.45 / 0.48 / 0.52 / 0.59 / 0.60.2 / 0.61.2) sont inchangées | | Aucune nouvelle dépendance transitive | `diff` des listes `dependencies` des 2 strophes ; 666 paquets et 7279 lignes avant/après | listes identiques | | `cargo metadata --locked` ne réécrit pas | md5 du lock avant / après | identique | Les deux versions retenues sont par ailleurs les dernières stables publiées (`0.23.45`, `0.103.15`), et l'advisory locale confirme la sévérité annoncée : `CVSS:3.1/…/C:L/I:N/A:N`, soit confidentialité seulement. ### CI — le log prouve les étapes, pas seulement le vert Run **412** (task 552, workflow `rust`, `Job succeeded`). Log lu ligne à ligne parce que l'étape `cargo audit` de `check-rust.yml` est `continue-on-error: true` et qu'un job vert n'y prouve rien : - garde-fou **exécuté et tracé** : `ok: rsa absent from x86_64-unknown-linux-gnu`, idem `x86_64-pc-windows-msvc`, `ok: canary 'tar' found`, `Suppression guard: 2 checks, exit 0` ; - `test result: ok. 111 passed; 0 failed` ; - `Downloaded rustls v0.23.45` → `Compiling rustls v0.23.45`, idem `rustls-webpki v0.103.15` : les archives derrière les checksums du lock sont bien celles qui ont servi ; - `Scanning src-tauri/Cargo.lock for vulnerabilities (666 crate dependencies)`, aucune ligne `error:`. `check-frontend` a été correctement sauté par sa denylist (2 `.md` + `Cargo.lock`) et `check-rust` déclenché par le glob `src-tauri/**` — même forme de cas test isolé qu'en #344. ### Chronologie vérifiée Runs **405 → 411** = 7 échecs consécutifs d'`audit` (09-15 → 09-21), dernier vert **404** (09-14) ; dernier commit sur `main` = `97ee3c3` du 09-13. La fenêtre est bien vide de push et l'advisory est datée du 09-14. Le corps est exact au numéro de run près. `Resolves #348` figure dans le **message de commit**, pas seulement dans le corps de la PR — la fermeture aura bien lieu. Format conventionnel respecté (`fix(deps): …`). ### Suggestions (non bloquantes) 1. **Le correctif n'atteint aucun poste avant un tag.** Le composant vulnérable est le chemin de mise à jour lui-même : les installations en v0.15.0 restent sur `rustls 0.23.36` tant qu'aucune version n'est publiée. Sans urgence (5.3, confidentialité seulement, transcription toujours authentifiée, et le serveur de release n'émet pas de poignée de main non conforme), mais le choix mérite d'être tranché explicitement plutôt que par défaut : v0.15.1 ou attente du prochain lot. 2. **`CLAUDE.md` ne liste pas la catégorie `Security` / `Sécurité`** (il n'énonce que « Added/Ajouté, Changed/Modifié, Fixed/Corrigé, Removed/Supprimé »), alors que les deux fichiers en comptent déjà 5 usages chacun, et 6 avec celui-ci. Dérive de doc préexistante, à corriger la prochaine fois que `CLAUDE.md` est touché. 3. **« Aucun changement de comportement »** est vrai du code de l'app, pas de la couche TLS : une poignée de main qui viole la RFC 8446 §5.1 est désormais fermée au lieu d'être acceptée. Sans effet pratique ici, la nuance vaut une demi-phrase si l'entrée est relue au moment du tag. Rendu in-app contrôlé au passage : `ChangelogContent` affiche l'intitulé de section tel quel (donc déjà localisé par le choix du fichier) et `UpdateCard` rend les `### ` en sous-titre dans une boîte scrollable. La puce de 1058 caractères reste sous le maximum déjà présent dans la section v0.15.0 (1180) et loin du maximum du fichier (2396) — la verbosité est dans le précédent du projet. Après merge, le `workflow_dispatch` d'`audit.yml` **sur `main`** annoncé dans le corps est la bonne étape finale : le vert du run de PR ne prouve rien. --- 🤖 Revue générée par `/pr-review`
maximus added 1 commit 2026-09-22 00:24:13 +00:00
docs(changelog): scope the "no behaviour change" claim to the app's own code
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 8m57s
9abf4743e5
Review note on #349: the entry said "no behaviour change", which holds
for this application's code but not for the TLS layer it links. rustls
0.23.45 closes a handshake that breaks RFC 8446 section 5.1 where 0.23.36
accepted it — that change of behaviour is the fix itself, and saying
otherwise understates what a reader is being told.

Changelog text only, in both languages. The lockfile is untouched, so
the CI evidence gathered on run 412 still stands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
maximus merged commit 9abf4743e5 into main 2026-09-22 00:33:54 +00:00
maximus deleted branch issue-348-rustls-rustsec-2026-0285 2026-09-22 00:33:54 +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#349
No description provided.