{"version":3,"file":"security.mjs","sources":["../../src/middlewares/security.ts"],"sourcesContent":["import { defaultsDeep, mergeWith } from 'lodash/fp';\nimport helmet, { KoaHelmet } from 'koa-helmet';\n\nimport type { Common } 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      'connect-src': [\"'self'\", 'https:'],\n      'img-src': [\"'self'\", 'data:', 'blob:', 'https://market-assets.strapi.io'],\n      'media-src': [\"'self'\", 'data:', 'blob:'],\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: Common.MiddlewareFactory<Config> =\n  (config, { strapi }) =>\n  (ctx, next) => {\n    let helmetConfig: Config = defaultsDeep(defaults, config);\n\n    const specialPaths = ['/documentation'];\n\n    if (strapi.plugin('graphql')) {\n      const { config: gqlConfig } = strapi.plugin('graphql');\n      specialPaths.push(gqlConfig('endpoint'));\n    }\n\n    if (ctx.method === 'GET' && specialPaths.some((str) => ctx.path.startsWith(str))) {\n      helmetConfig = mergeConfig(helmetConfig, {\n        contentSecurityPolicy: {\n          directives: {\n            'script-src': [\"'self'\", \"'unsafe-inline'\", 'cdn.jsdelivr.net'],\n            'img-src': [\"'self'\", 'data:', 'cdn.jsdelivr.net', 'strapi.io'],\n          },\n        },\n      });\n    }\n\n    if (ctx.method === 'GET' && ['/admin'].some((str) => ctx.path.startsWith(str))) {\n      helmetConfig = mergeConfig(helmetConfig, {\n        contentSecurityPolicy: {\n          directives: {\n            'script-src': [\"'self'\", \"'unsafe-inline'\"],\n            'connect-src': [\"'self'\", 'https:', 'ws:'],\n          },\n        },\n      });\n    }\n\n    return helmet(helmetConfig)(ctx, next);\n  };\n"],"names":[],"mappings":";;AAOA,MAAM,WAAmB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,yBAAyB;AAAA,EACzB,2BAA2B;AAAA,EAC3B,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,IACrB,aAAa;AAAA,IACb,YAAY;AAAA,MACV,eAAe,CAAC,UAAU,QAAQ;AAAA,MAClC,WAAW,CAAC,UAAU,SAAS,SAAS,iCAAiC;AAAA,MACzE,aAAa,CAAC,UAAU,SAAS,OAAO;AAAA,MACxC,yBAAyB;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,WAAW;AAAA,EACX,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,mBAAmB;AAAA,EACrB;AAAA,EACA,YAAY;AAAA,IACV,QAAQ;AAAA,EACV;AACF;AAEA,MAAM,cAAc,CAAC,gBAAwB,cAAsB;AAC1D,SAAA;AAAA,IACL,CAAC,KAAK,QAAS,MAAM,QAAQ,GAAG,KAAK,MAAM,QAAQ,GAAG,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA,IAC5E;AAAA,IACA;AAAA,EAAA;AAEJ;AAEa,MAAA,WACX,CAAC,QAAQ,EAAE,aACX,CAAC,KAAK,SAAS;AACT,MAAA,eAAuB,aAAa,UAAU,MAAM;AAElD,QAAA,eAAe,CAAC,gBAAgB;AAElC,MAAA,OAAO,OAAO,SAAS,GAAG;AAC5B,UAAM,EAAE,QAAQ,UAAA,IAAc,OAAO,OAAO,SAAS;AACxC,iBAAA,KAAK,UAAU,UAAU,CAAC;AAAA,EACzC;AAEA,MAAI,IAAI,WAAW,SAAS,aAAa,KAAK,CAAC,QAAQ,IAAI,KAAK,WAAW,GAAG,CAAC,GAAG;AAChF,mBAAe,YAAY,cAAc;AAAA,MACvC,uBAAuB;AAAA,QACrB,YAAY;AAAA,UACV,cAAc,CAAC,UAAU,mBAAmB,kBAAkB;AAAA,UAC9D,WAAW,CAAC,UAAU,SAAS,oBAAoB,WAAW;AAAA,QAChE;AAAA,MACF;AAAA,IAAA,CACD;AAAA,EACH;AAEA,MAAI,IAAI,WAAW,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,WAAW,GAAG,CAAC,GAAG;AAC9E,mBAAe,YAAY,cAAc;AAAA,MACvC,uBAAuB;AAAA,QACrB,YAAY;AAAA,UACV,cAAc,CAAC,UAAU,iBAAiB;AAAA,UAC1C,eAAe,CAAC,UAAU,UAAU,KAAK;AAAA,QAC3C;AAAA,MACF;AAAA,IAAA,CACD;AAAA,EACH;AAEA,SAAO,OAAO,YAAY,EAAE,KAAK,IAAI;AACvC;"}