{"version":3,"file":"security.mjs","sources":["../../src/middlewares/security.ts"],"sourcesContent":["import { defaultsDeep, mergeWith } from 'lodash/fp';\nimport helmet, { KoaHelmet } from 'koa-helmet';\nimport { CSP_DEFAULTS } from '@strapi/utils';\n\nimport type { Core } from '@strapi/types';\n\nexport type Config = NonNullable<Parameters<KoaHelmet>[0]>;\n\nconst defaults: Config = {\n  crossOriginEmbedderPolicy: false,\n  crossOriginOpenerPolicy: false,\n  crossOriginResourcePolicy: false,\n  originAgentCluster: false,\n  contentSecurityPolicy: {\n    useDefaults: true,\n    directives: {\n      ...CSP_DEFAULTS,\n      upgradeInsecureRequests: null,\n    },\n  },\n  xssFilter: false,\n  hsts: {\n    maxAge: 31536000,\n    includeSubDomains: true,\n  },\n  frameguard: {\n    action: 'sameorigin',\n  },\n};\n\nconst mergeConfig = (existingConfig: Config, newConfig: Config) => {\n  return mergeWith(\n    (obj, src) => (Array.isArray(obj) && Array.isArray(src) ? obj.concat(src) : undefined),\n    existingConfig,\n    newConfig\n  );\n};\n\nexport const security: Core.MiddlewareFactory<Config> =\n  (config, { strapi }) =>\n  (ctx, next) => {\n    let helmetConfig: Config = defaultsDeep(defaults, config);\n    const specialPaths = ['/documentation'];\n\n    const directives: {\n      'script-src': string[];\n      'img-src': string[];\n      'manifest-src': string[];\n      'frame-src': string[];\n    } = {\n      'script-src': [\"'self'\", \"'unsafe-inline'\", 'cdn.jsdelivr.net'],\n      'img-src': [\"'self'\", 'data:', 'cdn.jsdelivr.net', 'strapi.io'],\n      'manifest-src': [],\n      'frame-src': [],\n    };\n\n    // if apollo graphql playground is enabled, add exceptions for it\n    if (strapi.plugin('graphql')?.service('utils').playground.isEnabled()) {\n      const { config: gqlConfig } = strapi.plugin('graphql');\n      specialPaths.push(gqlConfig('endpoint'));\n\n      directives['script-src'].push(`https: 'unsafe-inline'`);\n      directives['img-src'].push(`'apollo-server-landing-page.cdn.apollographql.com'`);\n      directives['manifest-src'].push(`'self'`);\n      directives['manifest-src'].push('apollo-server-landing-page.cdn.apollographql.com');\n      directives['frame-src'].push(`'self'`);\n      directives['frame-src'].push('sandbox.embed.apollographql.com');\n    }\n\n    // TODO: we shouldn't combine playground exceptions with documentation for all routes, we should first check the path and then return exceptions specific to that\n    if (ctx.method === 'GET' && specialPaths.some((str) => ctx.path.startsWith(str))) {\n      helmetConfig = mergeConfig(helmetConfig, {\n        crossOriginEmbedderPolicy: false, // TODO: only use this for graphql playground\n        contentSecurityPolicy: {\n          directives,\n        },\n      });\n    }\n\n    /**\n     * These are for vite's watch mode so it can accurately\n     * connect to the HMR websocket & reconnect on failure\n     * or when the server restarts.\n     *\n     * It only applies in development, and only on GET requests\n     * that are part of the admin route.\n     */\n\n    if (\n      ['development', 'test'].includes(process.env.NODE_ENV ?? '') &&\n      ctx.method === 'GET' &&\n      ctx.path.startsWith(strapi.config.get('admin.path'))\n    ) {\n      helmetConfig = mergeConfig(helmetConfig, {\n        contentSecurityPolicy: {\n          directives: {\n            'script-src': [\"'self'\", \"'unsafe-inline'\"],\n            'connect-src': [\"'self'\", 'http:', 'https:', 'ws:'],\n          },\n        },\n      });\n    }\n\n    return helmet(helmetConfig)(ctx, next);\n  };\n"],"names":["defaults","crossOriginEmbedderPolicy","crossOriginOpenerPolicy","crossOriginResourcePolicy","originAgentCluster","contentSecurityPolicy","useDefaults","directives","CSP_DEFAULTS","upgradeInsecureRequests","xssFilter","hsts","maxAge","includeSubDomains","frameguard","action","mergeConfig","existingConfig","newConfig","mergeWith","obj","src","Array","isArray","concat","undefined","security","config","strapi","ctx","next","helmetConfig","defaultsDeep","specialPaths","plugin","service","playground","isEnabled","gqlConfig","push","method","some","str","path","startsWith","includes","process","env","NODE_ENV","get","helmet"],"mappings":"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"}