fix: maak make sast weer groen zonder de regel te verbreden #534

Merged
brenno merged 1 commit from fix/sast-chmod-subproces into main 2026-07-22 11:08:21 +00:00
Owner

Summary

make sast had been red on main since disk_traces.dart landed. With #522 merged, both scanner gates are green again.

Closes #521

The judgement

The rule ocideck-subproces-buiten-de-gitlaag exists because a subprocess cannot be intercepted by NetGuard — it talks to the network outside the guard. chmod cannot: fixed argv, no shell, no external input (the path comes from path_provider), Linux only, best-effort and unawaited.

So it is a true positive for the rule's letter and a false positive for its intent. The issue offered narrowing the rule or removing the call; both are worse:

  • Narrowing the rule by example is how deny-lists rot.
  • Removing the subprocess means an FFI binding to libc chmod, since Dart has no permission API — more attack surface for a best-effort, Linux-only hardening step. And the step is not decorative: it backs a claim the documentation makes about what another user on the same machine can read.

Not a path exclusion in the rule either. lib/services/git/** is excluded wholesale, and adding disk_traces.dart next to it would let a second subprocess in that file through unseen. The suppression sits on the line.

Semgrep requires the nosemgrep note directly above the finding — eight lines of explanation in between silently does not work, which cost one round to discover. The reasoning therefore sits above the note, and the note itself is the last line before the call.

The ratchet

One suppression is a judgement; ten is a habit, and then a green make sast means nothing. check_conventions.dart now counts // nosemgrep: in lib/ with nosemgrepBaseline = 1.

Deliberately counted there and not in semgrep: make sast needs an external binary and is not part of make check, so a new suppression would otherwise only be visible to whoever happens to have semgrep installed.

Verification, four directions

  • make sast clean (3 rules, 667 files, 0 findings);
  • fires on a planted second subprocess in the same file — the whole point of a line-scoped suppression;
  • fires on a planted subprocess in another lib/ file;
  • the ratchet fails on a planted second nosemgrep.

Gates

make check green. make check-secrets green (#522). make sast green. All three aggregate gates are clean on this branch — first time in this session.

Principles

Weakens a security check in one named place. Weighed above: the alternative constructions are worse, the exception is line-scoped rather than file-scoped, and its growth is now itself gated.

## Summary `make sast` had been red on `main` since `disk_traces.dart` landed. With #522 merged, both scanner gates are green again. Closes #521 ## The judgement The rule `ocideck-subproces-buiten-de-gitlaag` exists because **a subprocess cannot be intercepted by NetGuard** — it talks to the network outside the guard. `chmod` cannot: fixed argv, no shell, no external input (the path comes from `path_provider`), Linux only, best-effort and unawaited. So it is a true positive for the rule's letter and a false positive for its intent. The issue offered narrowing the rule or removing the call; both are worse: - **Narrowing the rule by example** is how deny-lists rot. - **Removing the subprocess** means an FFI binding to libc `chmod`, since Dart has no permission API — more attack surface for a best-effort, Linux-only hardening step. And the step is not decorative: it backs a claim the documentation makes about what another user on the same machine can read. **Not a path exclusion in the rule either.** `lib/services/git/**` is excluded wholesale, and adding `disk_traces.dart` next to it would let a *second* subprocess in that file through unseen. The suppression sits on the line. Semgrep requires the `nosemgrep` note **directly above** the finding — eight lines of explanation in between silently does not work, which cost one round to discover. The reasoning therefore sits above the note, and the note itself is the last line before the call. ## The ratchet One suppression is a judgement; ten is a habit, and then a green `make sast` means nothing. `check_conventions.dart` now counts `// nosemgrep:` in `lib/` with `nosemgrepBaseline = 1`. Deliberately counted **there and not in semgrep**: `make sast` needs an external binary and is not part of `make check`, so a new suppression would otherwise only be visible to whoever happens to have semgrep installed. ## Verification, four directions - `make sast` clean (3 rules, 667 files, 0 findings); - fires on a planted second subprocess **in the same file** — the whole point of a line-scoped suppression; - fires on a planted subprocess in another `lib/` file; - the ratchet fails on a planted second `nosemgrep`. ## Gates `make check` green. `make check-secrets` green (#522). `make sast` green. All three aggregate gates are clean on this branch — first time in this session. ## Principles Weakens a security check in one named place. Weighed above: the alternative constructions are worse, the exception is line-scoped rather than file-scoped, and its growth is now itself gated.
fix(sast): onderdruk de chmod-bevinding op de regel, en tel onderdrukkingen
Some checks failed
CI / Gate (Linux) · Format · Analyze · Coverage (pull_request) Has been cancelled
CI / Test (macos-latest) (pull_request) Has been cancelled
CI / Test (windows-latest) (pull_request) Has been cancelled
CI / Web hardening (pull_request) Has been cancelled
CI / Docs links (pull_request) Has been cancelled
CI / Supply-chain (Trivy · advisory) (pull_request) Has been cancelled
CI / Gate (Linux) · Format · Analyze · Coverage (push) Has been cancelled
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Web hardening (push) Has been cancelled
CI / Docs links (push) Has been cancelled
CI / Supply-chain (Trivy · advisory) (push) Has been cancelled
7b13407c0c
make sast stond rood op main sinds disk_traces.dart landde. De regel
ocideck-subproces-buiten-de-gitlaag bewaakt netwerkverkeer dat NetGuard
niet ziet; chmod is niet netwerkvaardig — vaste argv, geen schil, geen
invoer van buiten, alleen op Linux. Dart heeft geen permissie-API, dus het
alternatief is een FFI-binding naar libc: méér aanvalsoppervlak voor
minder.

Bewust géén padd-uitsluiting in de regel zelf: dan glipt ook een tweede
subproces in dat bestand er ongemerkt door. De onderdrukking staat op de
regel, en semgrep eist dat de nosemgrep-aantekening direct boven de
bevinding staat — acht regels uitleg ertussen werkt niet.

Daarnaast een ratchet: check_conventions telt nu de nosemgrep-regels in
lib/, basislijn 1. Eén onderdrukking is een afweging, tien is een
gewoonte, en dan zegt een groene make sast niets meer. Die telling staat
in check_conventions en niet in semgrep, omdat make sast een externe
binary vraagt en niet in make check zit.

Getoetst: sast schoon; alarm op een tweede subproces in hetzelfde
bestand; alarm op een subproces in een ander bestand; en de ratchet valt
op een tweede onderdrukking.

Closes #521

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit 52c622665b into main 2026-07-22 11:08:21 +00:00
brenno deleted branch fix/sast-chmod-subproces 2026-07-22 11:08:21 +00:00
Sign in to join this conversation.
No description provided.