import { defineConfig } from '@adonisjs/shield' import app from '@adonisjs/core/services/app' /** * In development, Vite's dev server assets (scripts, styles, /@vite/client) * are proxied through AdonisJS on the same origin, so 'self' already covers * them — there is no working "@viteDevUrl"/"@viteHmrUrl" CSP keyword in this * version of @adonisjs/shield (only "@viteUrl" exists, and it resolves to an * empty string here since assetsUrl is a relative path, not an absolute * dev-server URL). The one thing that truly lives on a different origin is * the Vite HMR websocket, which runs on its own port (see VITE_HMR_PORT, * default 24678) and therefore needs an explicit connect-src entry. */ const viteHmrPort = process.env.VITE_HMR_PORT ?? '24678' const devConnectSrc = app.inDev ? [`ws://localhost:${viteHmrPort}`] : [] const shieldConfig = defineConfig({ /** * Configure CSP policies for your app. Refer documentation * to learn more. */ csp: { /** * Enable the Content-Security-Policy header. */ enabled: true, /** * Per-resource CSP directives. */ directives: { defaultSrc: [`'self'`], connectSrc: [`'self'`, ...devConnectSrc], scriptSrc: [`'self'`], // Some client-side dependencies (e.g. Vite's HMR client / the Tuyau // API client) spawn a Web Worker from a `blob:` URL built at // runtime from already same-origin-loaded code. Without an explicit // worker-src, browsers fall back to script-src ('self' only), which // blocks the blob: worker outright — this was observed to break the // dev HMR connection and leave the Vue app in an inconsistent state // (lost TuyauProvider context after a failed hot reload). workerSrc: [`'self'`, 'blob:'], styleSrc: [`'self'`, `'unsafe-inline'`, 'https://fonts.googleapis.com'], // The favicon service (used to show a merchant's icon in the price // comparison UI) is requested from www.google.com but actually // serves/redirects to Google's gstatic CDN (t0-t3.gstatic.com), // hence the wildcard. imgSrc: [ `'self'`, 'data:', 'https://fr.pc-builder.io', 'https://www.google.com', 'https://*.gstatic.com', ], fontSrc: [`'self'`, 'data:', 'https://fonts.gstatic.com'], }, /** * Report violations without blocking resources. */ reportOnly: false, }, /** * Configure CSRF protection options. Refer documentation * to learn more. */ csrf: { /** * Enable CSRF token verification for state-changing requests. */ enabled: true, /** * Route patterns to exclude from CSRF checks. * Useful for external webhooks or API endpoints. */ exceptRoutes: [], /** * Expose an encrypted XSRF-TOKEN cookie for frontend HTTP clients. */ enableXsrfCookie: true, /** * HTTP methods protected by CSRF validation. */ methods: ['POST', 'PUT', 'PATCH', 'DELETE'], }, /** * Control how your website should be embedded inside * iframes. */ xFrame: { /** * Enable the X-Frame-Options header. */ enabled: true, /** * Block all framing attempts. Default value is DENY. */ action: 'DENY', }, /** * Force browser to always use HTTPS. */ hsts: { /** * Enable the Strict-Transport-Security header. */ enabled: true, /** * HSTS policy duration remembered by browsers. */ maxAge: '180 days', }, /** * Disable browsers from sniffing content types and rely only * on the response content-type header. */ contentTypeSniffing: { /** * Enable X-Content-Type-Options: nosniff. */ enabled: true, }, }) export default shieldConfig