Security follow-up #343: state-validatie, image-allowlist & readOnlyRootFilesystem#347
Open
robbertbos wants to merge 1 commit into
Open
Security follow-up #343: state-validatie, image-allowlist & readOnlyRootFilesystem#347robbertbos wants to merge 1 commit into
robbertbos wants to merge 1 commit into
Conversation
Contributor
🚀 Preview DeploymentYour changes have been deployed to a preview environment: api: https://pr-347-asses-k2n.rig.prd1.gn2.quattro.rijksapps.nl frontend: https://pr-347-asses-k2n.rig.prd1.gn2.quattro.rijksapps.nl This deployment will be automatically cleaned up when the PR is closed. |
e77139a to
85a78c4
Compare
85a78c4 to
88047d9
Compare
6 tasks
88047d9 to
f75740e
Compare
f75740e to
5df972e
Compare
…lyRootFilesystem (#343) Volgt de security-audit-follow-up #343 (resterende low/info-hardening) op met drie defense-in-depth-maatregelen op de boekhouding-backend. F8 — opaak state-schema: PUT /assessments/:id valideert de volledige state server-side tegen schemas/assessment-output.v2.schema.json (ajv, fail-fast). Het schema wordt bij startup gelezen en via de Containerfile in de image gekopieerd (één bron van waarheid). De client-paden die state opslaan (clearSavedState en beide versie-herstel-paden) sturen nu een canonieke state ($schema + metadata.urn), zodat strikte validatie geen legitieme save weigert. Aanbeveling #6 — data:-URI-validatie: een recursieve scan weigert embedded afbeeldingen die niet aan de raster-allowlist voldoen (^data:image/(webp|png|jpe?g|gif);base64,...), inclusief data:image/svg+xml (XSS-vector die de losse ^data:image/ schema-pattern zou doorlaten). De check draait op zowel de save (PUT) als de aanmaak (POST — geen create-bypass), met een volledig geankerde regex en een dieptegrens tegen stack-overflow. Aanbeveling #3 (deel 2) — readOnlyRootFilesystem: de backend draait non-root en schrijft niets naar het root-filesystem (logs → stdout, migraties → Postgres). docs/deployment.md beschrijft de ZAD-runtime-config (readOnlyRootFilesystem: true + expliciete writable /tmp); de Containerfile is hierop voorbereid. 100% testdekking behouden in alle workspaces.
5df972e to
3bfc27b
Compare
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.
Volgt #343 (security-audit-follow-up, resterende low/info-hardening) op. Drie defense-in-depth-maatregelen op de boekhouding-backend, plus de client-aanpassingen die nodig zijn om strikte validatie veilig te kunnen aanzetten zonder legitieme saves te breken.
Wat & waarom
F8 — server-side state-validatie (strikt)
PUT /assessments/:idvalideert de volledigestatetegenschemas/assessment-output.v2.schema.json(ajv, fail-fast) en weigert met400bij afwijking. Het schema blijft één bron van waarheid in de repo-root en wordt bij startup gelezen + via deContainerfilein de image gekopieerd.Omdat strikt valideren een legitieme save zou kunnen weigeren (data-verlies in een overheidsformulier), sturen alle client-paden nu een canonieke state (
$schema+metadata.urn):clearSavedState(formulier resetten)handleRestore(volledige versie herstellen)handleFieldRestore(veld-niveau herstellen) — incl. fallback-$schemavoor legacy-data van vóór commitc8a08afAanbeveling #6 —
data:-URI-allowlist voor afbeeldingenEen recursieve scan weigert embedded afbeeldingen die niet aan de raster-allowlist voldoen:
^data:image/(webp|png|jpe?g|gif);base64,...(volledig geankerd). Dit blokkeert o.a.data:image/svg+xml— de XSS-vector die de losse^data:image/-pattern in het schema zou doorlaten. De check draait op zowel save (PUT) als aanmaak (POST), zodat er geen create-bypass is, en heeft een dieptegrens tegen stack-overflow op diep geneste payloads.Aanbeveling #3 (deel 2) —
readOnlyRootFilesystemDe backend draait al non-root (#332) en schrijft niets naar het root-filesystem (logs → stdout, migraties → Postgres, schema read-only).
docs/deployment.mdbeschrijft de ZAD-runtime-config (readOnlyRootFilesystem: true+ writable/tmp); deContainerfileis hierop voorbereid. De feitelijke toggle staat in de ZAD Operations Manager (buiten deze repo).Adversariële review verwerkt
Een 4-agent review (security / NL-standaarden / correctheid / tests) draaide over de diff; de bevindingen zijn verwerkt:
ajv allErrors→ fail-fast (geen event-loop-blokkade / multi-MB logregel).handleFieldRestoremiste$schema→ opgelost.Standaarden
Testen
tsc+ beidevue-tscschoon;pnpm audit --prod --audit-level highschoon (ajv/ajv-formats geen kwetsbaarheden).dist/).