security: Content Security Policy et headers HTTP sécurité
- Renomme next.config.js → next.config.mjs (ESM, satisfait unicorn/prefer-module)
- Ajout de headers() avec CSP stricte :
script/style-src 'unsafe-inline' (requis Next.js + Emotion/MUI)
connect-src dynamique depuis les env vars Directus (API + WebSocket)
object-src 'none', frame-ancestors 'none', base-uri 'self'
img-src 'self' data: blob: (html2canvas / export PDF)
- Ajout X-Frame-Options, X-Content-Type-Options, Referrer-Policy,
Permissions-Policy sur toutes les routes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
|
||||||
const nextConfig = {
|
|
||||||
experimental: {
|
|
||||||
// Optimiser les imports pour réduire la mémoire
|
|
||||||
optimizePackageImports: ['@mui/material', '@mui/icons-material', '@emotion/react', '@emotion/styled'],
|
|
||||||
},
|
|
||||||
// Réduire l'utilisation mémoire
|
|
||||||
compress: true,
|
|
||||||
// Désactiver les source maps en dev pour économiser la mémoire
|
|
||||||
productionBrowserSourceMaps: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = nextConfig
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
|
||||||
|
// Les URL Directus sont lues à l'exécution — elles s'adaptent à l'environnement
|
||||||
|
// (dev local ou production) sans rebuild.
|
||||||
|
const apiUrl = process.env.NEXT_PUBLIC_DIRECTUS_API_URL ?? ''
|
||||||
|
const wsUrl = process.env.NEXT_PUBLIC_DIRECTUS_API_WS_URL ?? ''
|
||||||
|
|
||||||
|
// Tokens CSP — les guillemets simples font partie de la spec CSP, pas de JS
|
||||||
|
const SELF = '\'self\''
|
||||||
|
const NONE = '\'none\''
|
||||||
|
const UNSAFE_INLINE = '\'unsafe-inline\''
|
||||||
|
|
||||||
|
// Content Security Policy
|
||||||
|
// - unsafe-inline sur script-src : requis par Next.js App Router (hydratation inline)
|
||||||
|
// - unsafe-inline sur style-src : requis par Emotion/MUI (styles injectés dynamiquement)
|
||||||
|
// - data: blob: sur img-src : requis par html2canvas (export PDF)
|
||||||
|
// - frame-ancestors 'none' : anti-clickjacking (complète X-Frame-Options)
|
||||||
|
const cspDirectives = [
|
||||||
|
`default-src ${SELF}`,
|
||||||
|
`script-src ${SELF} ${UNSAFE_INLINE}`,
|
||||||
|
`style-src ${SELF} ${UNSAFE_INLINE}`,
|
||||||
|
`connect-src ${SELF} ${apiUrl} ${wsUrl}`.trim(),
|
||||||
|
`img-src ${SELF} data: blob:`,
|
||||||
|
`font-src ${SELF}`,
|
||||||
|
`object-src ${NONE}`,
|
||||||
|
`base-uri ${SELF}`,
|
||||||
|
`form-action ${SELF}`,
|
||||||
|
`frame-ancestors ${NONE}`,
|
||||||
|
]
|
||||||
|
|
||||||
|
const securityHeaders = [
|
||||||
|
{
|
||||||
|
key: 'Content-Security-Policy',
|
||||||
|
value: cspDirectives.join('; '),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'X-Frame-Options',
|
||||||
|
value: 'DENY',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'X-Content-Type-Options',
|
||||||
|
value: 'nosniff',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Referrer-Policy',
|
||||||
|
value: 'strict-origin-when-cross-origin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Permissions-Policy',
|
||||||
|
value: 'camera=(), microphone=(), geolocation=()',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const nextConfig = {
|
||||||
|
experimental: {
|
||||||
|
// Optimiser les imports pour réduire la mémoire
|
||||||
|
optimizePackageImports: ['@mui/material', '@mui/icons-material', '@emotion/react', '@emotion/styled'],
|
||||||
|
},
|
||||||
|
// Réduire l'utilisation mémoire
|
||||||
|
compress: true,
|
||||||
|
// Désactiver les source maps en dev pour économiser la mémoire
|
||||||
|
productionBrowserSourceMaps: false,
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/(.*)',
|
||||||
|
headers: securityHeaders,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default nextConfig
|
||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
## Améliorations hautes (P2)
|
## Améliorations hautes (P2)
|
||||||
|
|
||||||
- [ ] **Headers CSP** — ajouter dans `next.config.js`
|
- [x] **Headers CSP** — `next.config.mjs` (renommé depuis .js) avec CSP + 4 headers sécurité
|
||||||
- [ ] **Tests unitaires** — Vitest sur `lib/format.js`, `lib/version-utils.js`, `lib/rate-limit.js`
|
- [ ] **Tests unitaires** — Vitest sur `lib/format.js`, `lib/version-utils.js`, `lib/rate-limit.js`
|
||||||
- [ ] **Tests extensions Directus** — mocks VersionsService
|
- [ ] **Tests extensions Directus** — mocks VersionsService
|
||||||
- [ ] **Refresh token explicite** — callback `jwt` dans NextAuth options
|
- [ ] **Refresh token explicite** — callback `jwt` dans NextAuth options
|
||||||
|
|||||||
Reference in New Issue
Block a user