Skip to content

fix(security): durcissement pré-prod — auth, DoS rendu, headers/CSP, rate-limit - #24

Merged
Tbeaumont79 merged 4 commits into
mainfrom
fix/security-hardening
Jul 2, 2026
Merged

Tbeaumont79 merged 4 commits into
mainfrom
fix/security-hardening

Conversation

@Tbeaumont79

Copy link
Copy Markdown
Owner

Audit sécurité complet avant mise en prod (rapport détaillé dans SECURITY-AUDIT.md) + correctifs des findings à faible risque, testés end-to-end.

Findings corrigés

# Finding Correctif
1 🔴 Secret d'auth fallback en dur Plugin Nitro fail-fast : refuse de booter en prod si BETTER_AUTH_SECRET absent/faible ou APP_URL non-https
2 🔴 Export PDF non authentifié (DoS Chromium) requireUserId + gate quota + metering sur export-pdf ; requireUserId sur preview
3 🟠 Magic-link loggé en clair Plus aucun log en prod ; échec explicite si SMTP absent
4 🟠 Aucun header de sécurité nuxt-security : HSTS, X-Frame-Options DENY, nosniff, Referrer-Policy, Permissions-Policy + CSP à nonce en Report-Only
5 🟠 Pas de rate-limit Magic-link bridé à 3/min (Better Auth) ; requestSizeLimiter (préserve l'upload 8 Mo)
6 🟡 Cookies non-Secure useSecureCookies en prod + trustedOrigins explicite
9 🟡 TOCTOU crédits → 500 catch InsufficientCreditsError → 403 propre
10 🟡 Rendu CV sans bornes Bornes Zod (sections/bullets/textes)

Tests réalisés (serveur + DB locaux)

  • ✅ POST /api/cv/export-pdf et /api/cv/preview sans session → 401
  • ✅ Headers de sécurité présents sur les routes API et pages
  • ✅ CSP émise en Content-Security-Policy-Report-Only (n'applique rien)
  • ✅ Rate-limit magic-link : 3×200 puis 429 sur le vrai chemin /api/auth/sign-in/magic-link
  • ✅ pnpm typecheck OK, 124/124 tests verts

À faire ensuite (hors PR — nécessite décision/tests)

  • Passer la CSP en mode bloquant après validation navigateur (retirer contentSecurityPolicyReportOnly)
  • Limite /analyze par utilisateur (abus coût LLM) — seuil + stockage à décider
  • Bump nodemailer 8→9, update better-auth, sandbox Chromium (infra)

Notes

🤖 Generated with Claude Code

Tbeaumont79 and others added 2 commits July 2, 2026 16:00
Corrige les findings à faible risque de l'audit sécurité (SECURITY-AUDIT.md) :

- Fail-fast au boot (plugin Nitro) : refuse de démarrer en prod si
  BETTER_AUTH_SECRET absent/faible ou APP_URL non-https (anti forge de session).
- cv/export-pdf + cv/preview : exigent désormais l'auth (requireUserId).
  export-pdf gate le quota export_pdf et enregistre l'usage — ferme un DoS
  Chromium non authentifié + le bypass de quota.
- mailer : ne logge plus jamais le magic-link en prod ; échec explicite si SMTP
  absent (le jeton d'auth ne fuite plus dans les logs).
- auth : cookies de session forcés Secure en prod + trustedOrigins explicite.
- generate : capture InsufficientCreditsError (course sur le dernier crédit) →
  403 propre au lieu d'un 500.
- cv-render-input : bornes de taille Zod (sections/bullets/textes) contre les
  payloads géants (amplification DoS + JSON abusif en base).

Ajoute SECURITY-AUDIT.md (rapport complet, 12 findings + correctifs).
Typecheck OK, 124/124 tests verts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- nuxt-security : HSTS, X-Frame-Options DENY, nosniff, Referrer-Policy,
  Permissions-Policy, et CSP à nonce en **Report-Only** (n'applique rien tant
  que non validée au navigateur — retirer contentSecurityPolicyReportOnly ensuite).
- requestSizeLimiter réglé au-dessus de 8 Mo (préserve l'upload PDF de
  cv-design/extract) ; rateLimiter global désactivé (géré finement ailleurs).
- Better Auth rateLimit : magic-link bridé à 3 envois/min (anti email-bombing
  et énumération). Stockage mémoire — à passer sur store partagé en multi-instance.

Vérifié : app boote (200), en-tête Content-Security-Policy-Report-Only présent.
Typecheck OK, 124/124 tests verts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Jul 2, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for monumental-speculoos-a69398 ready!

Name Link
🔨 Latest commit 7d0f4fd
🔍 Latest deploy log https://app.netlify.com/projects/monumental-speculoos-a69398/deploys/6a467aa17ed7ee00085ff6ee
😎 Deploy Preview https://deploy-preview-24--monumental-speculoos-a69398.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Tbeaumont79, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b3c8b103-ce11-4042-af63-71eaf831cb91

📥 Commits

Reviewing files that changed from the base of the PR and between 8f6e4aa and 7d0f4fd.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • SECURITY-AUDIT.md
  • apps/app/nuxt.config.ts
  • apps/app/package.json
  • apps/app/server/api/candidature/generate.post.ts
  • apps/app/server/api/csp-report.post.ts
  • apps/app/server/api/cv/export-pdf.post.ts
  • apps/app/server/api/cv/preview.post.ts
  • apps/app/server/plugins/00.validate-env.ts
  • apps/app/server/utils/auth.ts
  • apps/app/server/utils/cv-render-input.ts
  • apps/app/server/utils/mailer.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/security-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Tbeaumont79 and others added 2 commits July 2, 2026 16:49
CSP validée au navigateur via un collecteur /api/csp-report (directive report-uri)
en mode Report-Only : seule violation = les Google Fonts du rendu CV (cv-html.ts),
autorisées explicitement (fonts.googleapis.com / fonts.gstatic.com). 0 violation
résiduelle → bascule en Content-Security-Policy bloquante.

- server/api/csp-report.post.ts : logge les violations (monitoring, conservé en prod).
- font-src/style-src : allowlist Google Fonts (suivi #3 : auto-héberger pour retirer
  ces hôtes distants).

Smoke-test navigateur OK (pages, aperçu CV iframe, export PDF).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Tbeaumont79
Tbeaumont79 merged commit cf6ef8f into main Jul 2, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant