Compare commits

...

2 commits

Author SHA1 Message Date
le king fu
a14258b147 fix(deps): update postcss to 8.5.23, accept the react-router advisory
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m46s
npm update postcss moves it 8.5.13 -> 8.5.23, clearing GHSA-r28c-9q8g-f849
(path traversal in previous-source-map auto-loading via a sourceMappingURL
comment, arbitrary .map disclosure, 7.5 high). No overrides entry needed,
unlike #241: vite declares postcss ^8.5.3 and 8.5.23 is published, so the
existing range already permitted the fix and only the lockfile carried a
stale resolution. nanoid 3.3.11 -> 3.3.16 comes along as postcss's own
dependency, within its declared range.

postcss IS the CSS pipeline, so a green build only proves compilation. The
emitted stylesheet was diffed across the bump and is byte-for-byte identical
(same content hash, same asset filename).

The remaining react-router advisory (GHSA-qwww-vcr4-c8h2, RSC Mode CSRF
bypass) is accepted rather than fixed. It targets React Server Components,
which a Tauri desktop app never runs — App.tsx mounts a client-only
BrowserRouter and src/ has no createStaticHandler, StaticRouter or server
rendering. There is also nothing to move forward to: react-router-dom is
frozen at 7.18.1 since v8 merged the package into react-router, so npm's
proposed "fix" is a downgrade to 7.11.0, and leaving the affected range
means migrating to react-router v8. Re-evaluation trigger tracked in #317.

Unlike the Rust side, no CI gate is involved: check-frontend.yml runs no
npm audit step, so nothing turns red. That expectation is now written down
in docs/architecture.md and CLAUDE.md so the two permanent high findings do
not read as a regression.

npm audit: 3 findings -> 2 (high 3 -> 2), postcss cleared.
npm ci + npm run build + 871 vitest green.

Resolves #311

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:00:11 -04:00
le king fu
e3dc794a09 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
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.
2026-07-27 20:00:09 -04:00
6 changed files with 27 additions and 10 deletions

View file

@ -86,12 +86,18 @@ jobs:
# #
# CRATES must mirror the crates named in .cargo/audit.toml. Adding an # CRATES must mirror the crates named in .cargo/audit.toml. Adding an
# entry there without adding its crate here leaves it unguarded. # entry there without adding its crate here leaves it unguarded.
#
# Every check echoes its result, including the passing ones. A guard that
# is silent on success cannot be told apart in the log from a guard that
# never ran — which is the same silent-skip failure mode this step exists
# to catch, one level up.
- name: Verify suppressed advisories are still unreachable - name: Verify suppressed advisories are still unreachable
run: | run: |
set -u set -u
CRATES="quick-xml rsa" CRATES="quick-xml rsa"
TARGETS="x86_64-unknown-linux-gnu x86_64-pc-windows-msvc" TARGETS="x86_64-unknown-linux-gnu x86_64-pc-windows-msvc"
rc=0 rc=0
checks=0
for crate in $CRATES; do for crate in $CRATES; do
for target in $TARGETS; do for target in $TARGETS; do
# An absent crate exits 0 with empty stdout ("nothing to print" # An absent crate exits 0 with empty stdout ("nothing to print"
@ -104,9 +110,12 @@ jobs:
continue continue
} }
if [ -n "$out" ]; then if [ -n "$out" ]; then
echo "$crate is now compiled for $target — its .cargo/audit.toml suppression is no longer justified (see #310)." echo "FAIL: $crate is now compiled for $target — its .cargo/audit.toml suppression is no longer justified (see #310)."
rc=1 rc=1
else
echo "ok: $crate absent from $target"
fi fi
checks=$((checks + 1))
done done
done done
# Canary: a crate known to be present. If this stops being found, the # Canary: a crate known to be present. If this stops being found, the
@ -114,9 +123,12 @@ jobs:
canary=$(cargo tree --manifest-path src-tauri/Cargo.toml --locked \ canary=$(cargo tree --manifest-path src-tauri/Cargo.toml --locked \
-i tar --target x86_64-unknown-linux-gnu 2>/dev/null) || true -i tar --target x86_64-unknown-linux-gnu 2>/dev/null) || true
if [ -z "$canary" ]; then if [ -z "$canary" ]; then
echo "Canary failed: 'tar' was not found although it is a known dependency. The guard is not proving anything." echo "FAIL: canary 'tar' was not found although it is a known dependency. The guard is not proving anything."
rc=1 rc=1
else
echo "ok: canary 'tar' found for x86_64-unknown-linux-gnu"
fi fi
echo "Suppression guard: $checks checks, exit $rc"
exit $rc exit $rc
- name: cargo test - name: cargo test

View file

@ -13,6 +13,7 @@
### Sécurité ### Sécurité
- Mise à jour de deux dépendances Rust situées sur le chemin de la mise à jour automatique, corrigeant six advisories RustSec : `rustls-webpki` 0.103.9 → 0.103.13 (traitement des contraintes de nom de certificat et analyse des listes de révocation, dont une panique atteignable) et `tar` 0.4.44 → 0.4.46 (`chmod` de répertoires arbitraires en suivant des liens symboliques pendant l'extraction, et en-têtes de taille PAX mal pris en compte). Les deux sont tirées par `tauri-plugin-updater`, qui télécharge et décompresse les mises à jour de l'application : ce sont donc de vrais chemins de code du produit livré. Aucun changement de comportement. Trois autres advisories restent signalées sur le fichier de verrouillage mais ne s'appliquent pas au produit livré — `quick-xml` n'est compilé que pour des cibles Apple que nous ne livrons pas, et `rsa` n'est jamais compilé — elles sont désormais consignées comme acceptées, avec leur justification et les conditions de leur retrait, plutôt que de laisser l'audit de sécurité quotidien rouge en permanence (#310). - Mise à jour de deux dépendances Rust situées sur le chemin de la mise à jour automatique, corrigeant six advisories RustSec : `rustls-webpki` 0.103.9 → 0.103.13 (traitement des contraintes de nom de certificat et analyse des listes de révocation, dont une panique atteignable) et `tar` 0.4.44 → 0.4.46 (`chmod` de répertoires arbitraires en suivant des liens symboliques pendant l'extraction, et en-têtes de taille PAX mal pris en compte). Les deux sont tirées par `tauri-plugin-updater`, qui télécharge et décompresse les mises à jour de l'application : ce sont donc de vrais chemins de code du produit livré. Aucun changement de comportement. Trois autres advisories restent signalées sur le fichier de verrouillage mais ne s'appliquent pas au produit livré — `quick-xml` n'est compilé que pour des cibles Apple que nous ne livrons pas, et `rsa` n'est jamais compilé — elles sont désormais consignées comme acceptées, avec leur justification et les conditions de leur retrait, plutôt que de laisser l'audit de sécurité quotidien rouge en permanence (#310).
- Mise à jour de la dépendance de build `postcss` (8.5.13 → 8.5.23), corrigeant GHSA-r28c-9q8g-f849 (traversée de chemin lors du chargement automatique d'une source map précédente depuis un commentaire `sourceMappingURL`, menant à la divulgation de fichiers `.map` arbitraires). Outillage de build uniquement, aucun changement runtime ni de comportement — le CSS généré est identique octet pour octet. Une advisory reste signalée sur `react-router` et est volontairement laissée en l'état : elle vise le mode React Server Components, qu'une application de bureau locale n'exécute jamais, et aucun correctif n'existe vers lequel avancer puisque `react-router-dom` est figé en 7.18.1 (sortir de la plage concernée demanderait une migration vers react-router v8, pas un changement de version) (#311).
## [0.14.0] - 2026-07-18 ## [0.14.0] - 2026-07-18

View file

@ -13,6 +13,7 @@
### Security ### Security
- Updated two Rust dependencies sitting on the automatic-update path, clearing six RustSec advisories: `rustls-webpki` 0.103.9 → 0.103.13 (certificate name-constraint handling and certificate-revocation-list parsing, including a reachable panic) and `tar` 0.4.44 → 0.4.46 (arbitrary directory `chmod` by following symlinks during extraction, and mishandled PAX size headers). Both are pulled in by `tauri-plugin-updater`, which downloads and unpacks application updates, so these are real code paths in the shipped app. No behaviour change. Three further advisories are still reported against the lockfile but do not apply to the shipped product — `quick-xml` is only compiled for Apple targets we do not ship, and `rsa` is never compiled at all — so they are now recorded as accepted, together with their justification and the conditions for removing them, instead of leaving the daily security audit permanently red (#310). - Updated two Rust dependencies sitting on the automatic-update path, clearing six RustSec advisories: `rustls-webpki` 0.103.9 → 0.103.13 (certificate name-constraint handling and certificate-revocation-list parsing, including a reachable panic) and `tar` 0.4.44 → 0.4.46 (arbitrary directory `chmod` by following symlinks during extraction, and mishandled PAX size headers). Both are pulled in by `tauri-plugin-updater`, which downloads and unpacks application updates, so these are real code paths in the shipped app. No behaviour change. Three further advisories are still reported against the lockfile but do not apply to the shipped product — `quick-xml` is only compiled for Apple targets we do not ship, and `rsa` is never compiled at all — so they are now recorded as accepted, together with their justification and the conditions for removing them, instead of leaving the daily security audit permanently red (#310).
- Updated the build-time dependency `postcss` (8.5.13 → 8.5.23), clearing GHSA-r28c-9q8g-f849 (path traversal while auto-loading a previous source map from a `sourceMappingURL` comment, leading to arbitrary `.map` file disclosure). Build tooling only, no runtime or behaviour change — the generated CSS is byte-for-byte identical. One advisory remains reported against `react-router`, and is deliberately left as is: it targets the React Server Components mode, which a local desktop app never runs, and no fix exists to move forward to since `react-router-dom` is frozen at 7.18.1 (leaving the affected range would mean migrating to react-router v8, not bumping a version) (#311).
## [0.14.0] - 2026-07-18 ## [0.14.0] - 2026-07-18

View file

@ -162,7 +162,7 @@ Pour maintenir l'éligibilité aux crédits d'impôt R&D (RS&DE fédéral + CRIC
Workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **capacité 1** — les jobs se suivent, ils ne tournent pas en parallèle. Workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **capacité 1** — les jobs se suivent, ils ne tournent pas en parallèle.
- **`check-rust.yml`** — déclenché sur les PR touchant `src-tauri/**` ou `.cargo/**`. Lance `cargo check`, une vérification bloquante que les advisories acceptées restent non atteignables, `cargo test` et un `cargo audit` informatif. Doit être vert avant tout merge. - **`check-rust.yml`** — déclenché sur les PR touchant `src-tauri/**` ou `.cargo/**`. Lance `cargo check`, une vérification bloquante que les advisories acceptées restent non atteignables, `cargo test` et un `cargo audit` informatif. Doit être vert avant tout merge.
- **`check-frontend.yml`** — déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown. Lance `npm run build` (tsc + vite) et `npm test` (vitest). Doit être vert avant tout merge. - **`check-frontend.yml`** — déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown. Lance `npm run build` (tsc + vite) et `npm test` (vitest). Doit être vert avant tout merge. **Aucune étape `npm audit`** : les advisories npm ne sont pas un gate de CI. `npm audit` remonte 2 high en permanence — une seule advisory `react-router` (mode RSC, inatteignable dans une app de bureau sans serveur), acceptée et suivie en [#317](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/317).
- **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant. **Un run vert signifie « zéro advisory hors de la liste acceptée »**, pas « zéro advisory » : cette liste est dans `.cargo/audit.toml` (preuve de non-atteignabilité et condition de retrait par entrée), encadrée par l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). Ne jamais y ajouter une advisory atteignable ni élargir une entrée à un crate entier. - **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant. **Un run vert signifie « zéro advisory hors de la liste acceptée »**, pas « zéro advisory » : cette liste est dans `.cargo/audit.toml` (preuve de non-atteignabilité et condition de retrait par entrée), encadrée par l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). Ne jamais y ajouter une advisory atteignable ni élargir une entrée à un crate entier.
- **`release.yml`** — déclenché par les tags `v*`. Build Windows (NSIS `.exe`) + Linux (`.deb`, `.rpm`), signe les binaires et publie le JSON d'updater pour les mises à jour automatiques. - **`release.yml`** — déclenché par les tags `v*`. Build Windows (NSIS `.exe`) + Linux (`.deb`, `.rpm`), signe les binaires et publie le JSON d'updater pour les mises à jour automatiques.

View file

@ -432,6 +432,8 @@ Aucun `branches:` : une PR stackée sur une autre branche de feature — ce que
Déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown (`paths-ignore`). Lance `npm ci`, `npm run build` (tsc + vite) et `npm test` (vitest). Le cache npm est retiré pour la même raison que côté Rust. Déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown (`paths-ignore`). Lance `npm ci`, `npm run build` (tsc + vite) et `npm test` (vitest). Le cache npm est retiré pour la même raison que côté Rust.
**Aucune étape `npm audit`** — contrairement au Rust, les advisories npm ne sont donc pas un gate de CI. Conséquence à connaître : `npm audit` remonte **2 high en permanence**, les deux clés d'une même advisory `react-router` ([GHSA-qwww-vcr4-c8h2](https://github.com/advisories/GHSA-qwww-vcr4-c8h2), mode React Server Components). Elle est acceptée : l'app est un client de bureau sans serveur — `App.tsx` monte un `BrowserRouter` client-only — et `react-router-dom` étant figé en 7.18.1, sortir de la plage vulnérable demanderait une migration vers react-router v8, pas un bump. Déclencheur de re-évaluation : [#317](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/317). `npm audit` n'a pas de mécanisme d'exclusion natif, il n'y a donc pas d'équivalent du `.cargo/audit.toml` côté npm.
### `audit.yml` — Audit RustSec quotidien ### `audit.yml` — Audit RustSec quotidien
`schedule` quotidien (06:00 UTC) + `workflow_dispatch`. `check-rust.yml` ne tournant que sur les PR qui touchent le Rust — environ 1 PR sur 40 — ce workflow garantit qu'un avis de sécurité publié sur une dépendance inchangée ne passe pas inaperçu. Échec bloquant : c'est le canal de notification. `schedule` quotidien (06:00 UTC) + `workflow_dispatch`. `check-rust.yml` ne tournant que sur les PR qui touchent le Rust — environ 1 PR sur 40 — ce workflow garantit qu'un avis de sécurité publié sur une dépendance inchangée ne passe pas inaperçu. Échec bloquant : c'est le canal de notification.

15
package-lock.json generated
View file

@ -2889,9 +2889,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.11", "version": "3.3.16",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2899,6 +2899,7 @@
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ],
"license": "MIT",
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs" "nanoid": "bin/nanoid.cjs"
}, },
@ -2959,9 +2960,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.5.13", "version": "8.5.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
"integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==", "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2979,7 +2980,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.11", "nanoid": "^3.3.16",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
}, },