The favicon service used to show a merchant's icon in the price comparison UI (www.google.com/s2/favicons) redirects to Google's gstatic CDN (t0-t3.gstatic.com), which wasn't allowlisted — CSP silently blocked the redirected image request (reported by some browsers as an opaque response block rather than a clear CSP violation), so the 'Compare prices' cheapest-offer favicon never rendered. Added https://*.gstatic.com to img-src.
135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
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
|