@forge/csp 4.2.0-experimental-959d7b9 → 4.2.0-experimental-8191ad1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # @forge/csp
2
2
 
3
- ## 4.2.0-experimental-959d7b9
3
+ ## 4.2.0-experimental-8191ad1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - aebd633: Patch @forge/csp IC frame ancestors csp bug
8
+ - abf0bb1: Add support for custom getICDomain option in CSPInjectionService
9
+ - e33aba7: Bumped a large number of vulnerable dependencies within forge templates via automatic upgrade
10
+ - 8191ad1: Use cheerio/slim to reduce client bundle size and improve performance
8
11
 
9
12
  ## 4.2.0
10
13
 
@@ -1,9 +1,14 @@
1
1
  import type { LambdaEnvironment } from '@forge/cli-shared';
2
2
  import { CSPDetails } from '../types';
3
- declare type IcOptions = {
3
+ declare type StandardIcOptions = {
4
4
  icLabel: string;
5
5
  serviceName: string;
6
6
  };
7
+ declare type GetICDomainIcOptions = {
8
+ serviceName?: string;
9
+ getICDomain: () => string;
10
+ };
11
+ declare type IcOptions = StandardIcOptions | GetICDomainIcOptions;
7
12
  export declare const getAtlassianImageHost: (microsEnv: LambdaEnvironment, icOptions?: IcOptions) => string[];
8
13
  export declare const EXTERNAL_ALLOW_LISTED_IMAGES_HOSTS: string[];
9
14
  export declare class CSPInjectionService {
@@ -1 +1 @@
1
- {"version":3,"file":"csp-injection-service.d.ts","sourceRoot":"","sources":["../../src/csp/csp-injection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAmB,MAAM,UAAU,CAAC;AAEvD,aAAK,SAAS,GAAG;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAiGF,eAAO,MAAM,qBAAqB,cAAe,iBAAiB,cAAc,SAAS,KAAG,MAAM,EAUjG,CAAC;AAMF,eAAO,MAAM,kCAAkC,UAAiE,CAAC;AAEjH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,iBAAiB;IAiDlB,gBAAgB;4BAQD,UAAU;mBACnB,iBAAiB;;;;;UAK1B,MAAM,EAAE,CA8DV;CACH"}
1
+ {"version":3,"file":"csp-injection-service.d.ts","sourceRoot":"","sources":["../../src/csp/csp-injection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAmB,MAAM,UAAU,CAAC;AAEvD,aAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAIF,aAAK,oBAAoB,GAAG;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,MAAM,CAAC;CAC3B,CAAC;AAEF,aAAK,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAyG1D,eAAO,MAAM,qBAAqB,cAAe,iBAAiB,cAAc,SAAS,KAAG,MAAM,EAUjG,CAAC;AAMF,eAAO,MAAM,kCAAkC,UAAiE,CAAC;AAEjH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,iBAAiB;IAiDlB,gBAAgB;4BAQD,UAAU;mBACnB,iBAAiB;;;;;UAK1B,MAAM,EAAE,CA8DV;CACH"}
@@ -3,7 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CSPInjectionService = exports.EXTERNAL_ALLOW_LISTED_IMAGES_HOSTS = exports.getAtlassianImageHost = void 0;
4
4
  const types_1 = require("../types");
5
5
  const isICEnvKey = (env) => env === 'ic-prod' || env === 'ic-stg';
6
- const getICDomain = (env, icLabel) => `${icLabel}.${env === 'ic-prod' ? 'atlassian-isolated.net' : 'oasis-stg.com'}`;
6
+ const makeICDomain = (env, icLabel) => `${icLabel}.${env === 'ic-prod' ? 'atlassian-isolated.net' : 'oasis-stg.com'}`;
7
+ const getICDomain = (env, icOptions) => {
8
+ if ('getICDomain' in icOptions) {
9
+ return icOptions.getICDomain();
10
+ }
11
+ return makeICDomain(env, icOptions.icLabel);
12
+ };
7
13
  const makeICHosts = (targetHostFunction) => {
8
14
  return {
9
15
  'ic-stg': (icOptions) => targetHostFunction('ic-stg', icOptions),
@@ -17,7 +23,7 @@ const ATLASSIAN_HOST = {
17
23
  prod: 'https://api.atlassian.com',
18
24
  'fedramp-stg': 'https://api.stg.atlassian-us-gov-mod.com',
19
25
  'fedramp-prod': 'https://api.atlassian-us-gov-mod.com',
20
- ...makeICHosts((env, { icLabel }) => `https://api.${getICDomain(env, icLabel)}`)
26
+ ...makeICHosts((env, icOptions) => `https://api.${getICDomain(env, icOptions)}`)
21
27
  },
22
28
  ATLASSIAN_MEDIA_GATEWAY_HOST: {
23
29
  dev: 'https://media.dev.atl-paas.net',
@@ -25,7 +31,7 @@ const ATLASSIAN_HOST = {
25
31
  prod: 'https://api.media.atlassian.com',
26
32
  'fedramp-stg': 'https://api-media.stg.atlassian-us-gov-mod.com',
27
33
  'fedramp-prod': 'https://api-media.atlassian-us-gov-mod.com',
28
- ...makeICHosts((env, { icLabel }) => `https://media-api.${getICDomain(env, icLabel)}`)
34
+ ...makeICHosts((env, icOptions) => `https://media-api.${getICDomain(env, icOptions)}`)
29
35
  },
30
36
  ATLASSIAN_AVATAR_HOST: {
31
37
  dev: 'avatar-management--avatars.us-west-2.staging.public.atl-paas.net',
@@ -42,7 +48,7 @@ const ATLASSIAN_HOST = {
42
48
  prod: 'https://ptc-directory-sited-static.us-east-1.prod.public.atl-paas.net/gradients/',
43
49
  'fedramp-stg': 'https://teams-directory-frontend.frontend.cdn.atlassian-us-gov-mod.com/assets/',
44
50
  'fedramp-prod': 'https://teams-directory-frontend.frontend.cdn.atlassian-us-gov-mod.com/assets/',
45
- ...makeICHosts((env, { icLabel }) => `https://teams-directory-frontend.services.${getICDomain(env, icLabel)}/bfa/`)
51
+ ...makeICHosts((env, icOptions) => `https://teams-directory-frontend.services.${getICDomain(env, icOptions)}/bfa/`)
46
52
  },
47
53
  ATLASSIAN_TEAM_AVATAR_HOST: {
48
54
  dev: 'https://teams-directory-frontend.stg-east.frontend.public.atl-paas.net/assets/',
@@ -50,7 +56,7 @@ const ATLASSIAN_HOST = {
50
56
  prod: 'https://teams-directory-frontend.prod-east.frontend.public.atl-paas.net/assets/',
51
57
  'fedramp-stg': 'https://teams-directory-frontend.frontend.cdn.atlassian-us-gov-mod.com/assets/',
52
58
  'fedramp-prod': 'https://teams-directory-frontend.frontend.cdn.atlassian-us-gov-mod.com/assets/',
53
- ...makeICHosts((env, { icLabel }) => `https://teams-directory-frontend.services.${getICDomain(env, icLabel)}/bfa/`)
59
+ ...makeICHosts((env, icOptions) => `https://teams-directory-frontend.services.${getICDomain(env, icOptions)}/bfa/`)
54
60
  },
55
61
  ATLASSIAN_EMOJIS_HOST: {
56
62
  dev: 'https://pf-emoji-service--cdn.ap-southeast-2.dev.public.atl-paas.net',
@@ -58,7 +64,7 @@ const ATLASSIAN_HOST = {
58
64
  prod: 'https://pf-emoji-service--cdn.us-east-1.prod.public.atl-paas.net',
59
65
  'fedramp-stg': 'https://pf-emoji-service--cdn.us-east-1.staging.cdn.atlassian-us-gov-mod.com',
60
66
  'fedramp-prod': 'https://pf-emoji-service--cdn.us-east-1.prod.cdn.atlassian-us-gov-mod.com',
61
- ...makeICHosts((env, { icLabel }) => `https://pf-emoji-service.${getICDomain(env, icLabel)}`)
67
+ ...makeICHosts((env, icOptions) => `https://pf-emoji-service.${getICDomain(env, icOptions)}`)
62
68
  }
63
69
  };
64
70
  const getAtlassianHost = (hostType, microsEnv, icOptions) => {
@@ -85,6 +91,67 @@ const getAtlassianImageHost = (microsEnv, icOptions) => {
85
91
  exports.getAtlassianImageHost = getAtlassianImageHost;
86
92
  exports.EXTERNAL_ALLOW_LISTED_IMAGES_HOSTS = ['https://secure.gravatar.com', 'https://images.unsplash.com'];
87
93
  class CSPInjectionService {
94
+ constructor() {
95
+ this.getInjectableCSP = ({ existingCSPDetails, microsEnv, tunnelCSPReporterUri, hostname, isFedRAMP, icOptions }) => {
96
+ const reportUri = tunnelCSPReporterUri || this.getCSPReportUri(microsEnv, icOptions);
97
+ const defaultSrc = `'self'`;
98
+ const frameAncestors = ["'self'", ...this.getFrameAncestors(microsEnv, hostname, icOptions)].join(' ');
99
+ const frameSrc = ["'self'", hostname, ...this.getExistingCSPDetails(types_1.ExternalCspType.FRAME_SRC, existingCSPDetails)]
100
+ .filter((a) => a)
101
+ .join(' ');
102
+ const fontSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FONT_SRC, existingCSPDetails)].join(' ');
103
+ const imgSrc = [
104
+ "'self'",
105
+ 'data:',
106
+ 'blob:',
107
+ hostname,
108
+ ...exports.EXTERNAL_ALLOW_LISTED_IMAGES_HOSTS,
109
+ ...(0, exports.getAtlassianImageHost)(microsEnv, icOptions),
110
+ ...this.getExistingCSPDetails(types_1.ExternalCspType.IMG_SRC, existingCSPDetails)
111
+ ]
112
+ .filter((a) => a)
113
+ .join(' ');
114
+ const mediaSrc = [
115
+ "'self'",
116
+ 'data:',
117
+ 'blob:',
118
+ hostname,
119
+ getAtlassianHost('ATLASSIAN_MEDIA_GATEWAY_HOST', microsEnv, icOptions),
120
+ ...this.getExistingCSPDetails(types_1.ExternalCspType.MEDIA_SRC, existingCSPDetails)
121
+ ]
122
+ .filter((a) => a)
123
+ .join(' ');
124
+ const connectSrc = [
125
+ "'self'",
126
+ ...this.getConnectSrc(microsEnv, !!tunnelCSPReporterUri, icOptions),
127
+ ...this.getExistingCSPDetails(types_1.ExternalCspType.CONNECT_SRC, existingCSPDetails)
128
+ ].join(' ');
129
+ const scriptSrc = [
130
+ "'self'",
131
+ this.getForgeGlobalCSP(microsEnv, isFedRAMP, icOptions),
132
+ ...this.getExistingCSPDetails(types_1.ExternalCspType.SCRIPT_SRC, existingCSPDetails)
133
+ ].join(' ');
134
+ const styleSrc = [
135
+ "'self'",
136
+ this.getForgeGlobalCSP(microsEnv, isFedRAMP, icOptions),
137
+ ...this.getExistingCSPDetails(types_1.ExternalCspType.STYLE_SRC, existingCSPDetails)
138
+ ].join(' ');
139
+ return [
140
+ `default-src ${defaultSrc}`,
141
+ `frame-ancestors ${frameAncestors}`,
142
+ `frame-src ${frameSrc}`,
143
+ `font-src ${fontSrc}`,
144
+ `img-src ${imgSrc}`,
145
+ `media-src ${mediaSrc}`,
146
+ `connect-src ${connectSrc}`,
147
+ `script-src ${scriptSrc}`,
148
+ `style-src ${styleSrc}`,
149
+ `form-action 'self'`,
150
+ `sandbox allow-downloads allow-forms allow-modals allow-pointer-lock allow-same-origin allow-scripts`,
151
+ `report-uri ${reportUri}`
152
+ ];
153
+ };
154
+ }
88
155
  getCSPReportUri(microsEnv, icOptions) {
89
156
  const serviceName = isICEnvKey(microsEnv) && icOptions ? icOptions.serviceName : 'forge-cdn';
90
157
  if (microsEnv === 'dev' || microsEnv === 'stg')
@@ -93,7 +160,7 @@ class CSPInjectionService {
93
160
  }
94
161
  getForgeGlobalCSP(microsEnv, isFedRAMP = false, icOptions) {
95
162
  if (isICEnvKey(microsEnv) && icOptions) {
96
- return `https://forge.forge-cdn.${getICDomain(microsEnv, icOptions.icLabel)}`;
163
+ return `https://forge.forge-cdn.${getICDomain(microsEnv, icOptions)}`;
97
164
  }
98
165
  return isFedRAMP
99
166
  ? `https://forge.cdn.${microsEnv.split('-')[1]}.atlassian-dev-us-gov-mod.net`
@@ -101,12 +168,13 @@ class CSPInjectionService {
101
168
  }
102
169
  getMetalClientCSP(microsEnv, icOptions) {
103
170
  if (isICEnvKey(microsEnv) && icOptions) {
104
- return `https://api.${getICDomain(microsEnv, icOptions.icLabel)}/metal/ingest`;
171
+ return `https://api.${getICDomain(microsEnv, icOptions)}/metal/ingest`;
105
172
  }
106
173
  return `https://api.${microsEnv === 'prod' ? '' : 'stg.'}atlassian.com/metal/ingest`;
107
174
  }
108
175
  getExistingCSPDetails(cspType, cspDetails) {
109
- return cspDetails[cspType] ?? [];
176
+ var _a;
177
+ return (_a = cspDetails[cspType]) !== null && _a !== void 0 ? _a : [];
110
178
  }
111
179
  getConnectSrc(microsEnv, isTunnelling, icOptions) {
112
180
  const allowed = [];
@@ -142,7 +210,7 @@ class CSPInjectionService {
142
210
  case 'ic-stg':
143
211
  case 'ic-prod':
144
212
  if (icOptions) {
145
- frameAncestors = [`*.${getICDomain(microsEnv, icOptions.icLabel)}`];
213
+ frameAncestors = [`*.${getICDomain(microsEnv, icOptions)}`];
146
214
  }
147
215
  break;
148
216
  case 'prod':
@@ -161,64 +229,5 @@ class CSPInjectionService {
161
229
  }
162
230
  return frameAncestors;
163
231
  }
164
- getInjectableCSP = ({ existingCSPDetails, microsEnv, tunnelCSPReporterUri, hostname, isFedRAMP, icOptions }) => {
165
- const reportUri = tunnelCSPReporterUri || this.getCSPReportUri(microsEnv, icOptions);
166
- const defaultSrc = `'self'`;
167
- const frameAncestors = ["'self'", ...this.getFrameAncestors(microsEnv, hostname, icOptions)].join(' ');
168
- const frameSrc = ["'self'", hostname, ...this.getExistingCSPDetails(types_1.ExternalCspType.FRAME_SRC, existingCSPDetails)]
169
- .filter((a) => a)
170
- .join(' ');
171
- const fontSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FONT_SRC, existingCSPDetails)].join(' ');
172
- const imgSrc = [
173
- "'self'",
174
- 'data:',
175
- 'blob:',
176
- hostname,
177
- ...exports.EXTERNAL_ALLOW_LISTED_IMAGES_HOSTS,
178
- ...(0, exports.getAtlassianImageHost)(microsEnv, icOptions),
179
- ...this.getExistingCSPDetails(types_1.ExternalCspType.IMG_SRC, existingCSPDetails)
180
- ]
181
- .filter((a) => a)
182
- .join(' ');
183
- const mediaSrc = [
184
- "'self'",
185
- 'data:',
186
- 'blob:',
187
- hostname,
188
- getAtlassianHost('ATLASSIAN_MEDIA_GATEWAY_HOST', microsEnv, icOptions),
189
- ...this.getExistingCSPDetails(types_1.ExternalCspType.MEDIA_SRC, existingCSPDetails)
190
- ]
191
- .filter((a) => a)
192
- .join(' ');
193
- const connectSrc = [
194
- "'self'",
195
- ...this.getConnectSrc(microsEnv, !!tunnelCSPReporterUri, icOptions),
196
- ...this.getExistingCSPDetails(types_1.ExternalCspType.CONNECT_SRC, existingCSPDetails)
197
- ].join(' ');
198
- const scriptSrc = [
199
- "'self'",
200
- this.getForgeGlobalCSP(microsEnv, isFedRAMP, icOptions),
201
- ...this.getExistingCSPDetails(types_1.ExternalCspType.SCRIPT_SRC, existingCSPDetails)
202
- ].join(' ');
203
- const styleSrc = [
204
- "'self'",
205
- this.getForgeGlobalCSP(microsEnv, isFedRAMP, icOptions),
206
- ...this.getExistingCSPDetails(types_1.ExternalCspType.STYLE_SRC, existingCSPDetails)
207
- ].join(' ');
208
- return [
209
- `default-src ${defaultSrc}`,
210
- `frame-ancestors ${frameAncestors}`,
211
- `frame-src ${frameSrc}`,
212
- `font-src ${fontSrc}`,
213
- `img-src ${imgSrc}`,
214
- `media-src ${mediaSrc}`,
215
- `connect-src ${connectSrc}`,
216
- `script-src ${scriptSrc}`,
217
- `style-src ${styleSrc}`,
218
- `form-action 'self'`,
219
- `sandbox allow-downloads allow-forms allow-modals allow-pointer-lock allow-same-origin allow-scripts`,
220
- `report-uri ${reportUri}`
221
- ];
222
- };
223
232
  }
224
233
  exports.CSPInjectionService = CSPInjectionService;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CSPProcessingService = exports.InvalidConnectSrc = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const cheerio_1 = require("cheerio");
5
+ const slim_1 = require("cheerio/slim");
6
6
  const content_security_policy_parser_1 = tslib_1.__importDefault(require("content-security-policy-parser"));
7
7
  const crypto_1 = tslib_1.__importDefault(require("crypto"));
8
8
  class InvalidConnectSrc extends Error {
@@ -12,23 +12,23 @@ class InvalidConnectSrc extends Error {
12
12
  }
13
13
  exports.InvalidConnectSrc = InvalidConnectSrc;
14
14
  class CSPProcessingService {
15
- logger;
16
- STYLE_SRC_ALLOWLIST = [`'unsafe-inline'`];
17
- QUOTED_SCRIPT_SRC_ALLOWLIST = ['unsafe-inline', 'unsafe-eval', 'unsafe-hashes'];
18
- UNQUOTED_SCRIPT_SRC_ALLOWLIST = ['blob:'];
19
- SCRIPT_SRC_ALLOWLIST = [...this.QUOTED_SCRIPT_SRC_ALLOWLIST, ...this.UNQUOTED_SCRIPT_SRC_ALLOWLIST];
20
- BASE_64_HASH_PATTERNS = [
21
- /^sha256-[a-zA-Z0-9=+/]{44}$/,
22
- /^sha384-[a-zA-Z0-9=+/]{64}$/,
23
- /^sha512-[a-zA-Z0-9=+/]{88}$/
24
- ];
25
15
  constructor(logger) {
26
16
  this.logger = logger;
17
+ this.STYLE_SRC_ALLOWLIST = [`'unsafe-inline'`];
18
+ this.QUOTED_SCRIPT_SRC_ALLOWLIST = ['unsafe-inline', 'unsafe-eval', 'unsafe-hashes'];
19
+ this.UNQUOTED_SCRIPT_SRC_ALLOWLIST = ['blob:'];
20
+ this.SCRIPT_SRC_ALLOWLIST = [...this.QUOTED_SCRIPT_SRC_ALLOWLIST, ...this.UNQUOTED_SCRIPT_SRC_ALLOWLIST];
21
+ this.BASE_64_HASH_PATTERNS = [
22
+ /^sha256-[a-zA-Z0-9=+/]{44}$/,
23
+ /^sha384-[a-zA-Z0-9=+/]{64}$/,
24
+ /^sha512-[a-zA-Z0-9=+/]{88}$/
25
+ ];
27
26
  }
28
27
  getCspDetails(body, permissions) {
29
- const { scripts, styles } = permissions?.content ?? { scripts: [], styles: [] };
30
- const external = permissions?.external ?? {};
31
- const $ = (0, cheerio_1.load)(body, { xml: { xmlMode: false } });
28
+ var _a, _b;
29
+ const { scripts, styles } = (_a = permissions === null || permissions === void 0 ? void 0 : permissions.content) !== null && _a !== void 0 ? _a : { scripts: [], styles: [] };
30
+ const external = (_b = permissions === null || permissions === void 0 ? void 0 : permissions.external) !== null && _b !== void 0 ? _b : {};
31
+ const $ = (0, slim_1.load)(body, { xml: { xmlMode: false } });
32
32
  const { 'script-src': scriptSrc, 'style-src': styleSrc, ...mappedExternalCsp } = this.mapExternalPermissionsToCsp(external);
33
33
  return {
34
34
  'style-src': [...this.getStyleSrc($, styles), ...styleSrc],
@@ -37,14 +37,15 @@ class CSPProcessingService {
37
37
  };
38
38
  }
39
39
  getInvalidCspPermissions(contentPermissions) {
40
+ var _a, _b;
40
41
  const { styles, scripts } = contentPermissions;
41
- const invalidStyles = styles?.filter((styleSrc) => !this.isValidUserStyleSrc(`'${styleSrc}'`)) ?? [];
42
- const invalidScripts = scripts?.filter((scriptSrc) => !this.isValidUserScriptSrc(scriptSrc)) ?? [];
42
+ const invalidStyles = (_a = styles === null || styles === void 0 ? void 0 : styles.filter((styleSrc) => !this.isValidUserStyleSrc(`'${styleSrc}'`))) !== null && _a !== void 0 ? _a : [];
43
+ const invalidScripts = (_b = scripts === null || scripts === void 0 ? void 0 : scripts.filter((scriptSrc) => !this.isValidUserScriptSrc(scriptSrc))) !== null && _b !== void 0 ? _b : [];
43
44
  return [...invalidStyles, ...invalidScripts];
44
45
  }
45
46
  assertValidFetchClient(fetch) {
46
- if (fetch?.client) {
47
- for (const client of fetch?.client) {
47
+ if (fetch === null || fetch === void 0 ? void 0 : fetch.client) {
48
+ for (const client of fetch === null || fetch === void 0 ? void 0 : fetch.client) {
48
49
  if (typeof client !== 'string') {
49
50
  throw new InvalidConnectSrc();
50
51
  }
@@ -52,42 +53,46 @@ class CSPProcessingService {
52
53
  }
53
54
  }
54
55
  egressesToStringMap(externalPermissions) {
55
- return externalPermissions?.map((egress) => (typeof egress === 'object' ? egress.address : egress));
56
+ return externalPermissions === null || externalPermissions === void 0 ? void 0 : externalPermissions.map((egress) => (typeof egress === 'object' ? egress.address : egress));
56
57
  }
57
58
  mapExternalPermissionsToCsp(externalPermissions) {
59
+ var _a, _b, _c, _d, _e, _f, _g;
58
60
  const { images, media, scripts, fetch, styles, fonts, frames } = externalPermissions;
59
61
  this.assertValidFetchClient(fetch);
60
62
  return {
61
- 'img-src': this.egressesToStringMap(images) ?? [],
62
- 'media-src': this.egressesToStringMap(media) ?? [],
63
- 'script-src': this.egressesToStringMap(scripts) ?? [],
64
- 'style-src': this.egressesToStringMap(styles) ?? [],
65
- 'connect-src': fetch?.client ?? [],
66
- 'font-src': this.egressesToStringMap(fonts) ?? [],
67
- 'frame-src': this.egressesToStringMap(frames) ?? []
63
+ 'img-src': (_a = this.egressesToStringMap(images)) !== null && _a !== void 0 ? _a : [],
64
+ 'media-src': (_b = this.egressesToStringMap(media)) !== null && _b !== void 0 ? _b : [],
65
+ 'script-src': (_c = this.egressesToStringMap(scripts)) !== null && _c !== void 0 ? _c : [],
66
+ 'style-src': (_d = this.egressesToStringMap(styles)) !== null && _d !== void 0 ? _d : [],
67
+ 'connect-src': (_e = fetch === null || fetch === void 0 ? void 0 : fetch.client) !== null && _e !== void 0 ? _e : [],
68
+ 'font-src': (_f = this.egressesToStringMap(fonts)) !== null && _f !== void 0 ? _f : [],
69
+ 'frame-src': (_g = this.egressesToStringMap(frames)) !== null && _g !== void 0 ? _g : []
68
70
  };
69
71
  }
70
72
  getStyleSrc($, userStyleSrc) {
71
- const quotedUserStyleSrc = userStyleSrc?.map((x) => `'${x}'`) ?? [];
72
- const deprecatedUserStyleSrc = this.getDeprecatedUserCsp($)['style-src'] ?? [];
73
+ var _a, _b;
74
+ const quotedUserStyleSrc = (_a = userStyleSrc === null || userStyleSrc === void 0 ? void 0 : userStyleSrc.map((x) => `'${x}'`)) !== null && _a !== void 0 ? _a : [];
75
+ const deprecatedUserStyleSrc = (_b = this.getDeprecatedUserCsp($)['style-src']) !== null && _b !== void 0 ? _b : [];
73
76
  const uniqueStyleSrc = [...new Set([...deprecatedUserStyleSrc, ...quotedUserStyleSrc])];
74
77
  return uniqueStyleSrc.filter((x) => this.isValidUserStyleSrc(x));
75
78
  }
76
79
  getScriptSrc($, userScriptSrc) {
77
- const validUserScriptSrc = userScriptSrc?.filter((x) => this.isValidUserScriptSrc(x)) ?? [];
80
+ var _a;
81
+ const validUserScriptSrc = (_a = userScriptSrc === null || userScriptSrc === void 0 ? void 0 : userScriptSrc.filter((x) => this.isValidUserScriptSrc(x))) !== null && _a !== void 0 ? _a : [];
78
82
  const generatedScriptHashes = validUserScriptSrc.includes('unsafe-inline') ? [] : this.getInlineScriptHashes($);
79
83
  const { scriptSrc, userScriptHashes } = this.extractUniqueHashes(validUserScriptSrc, generatedScriptHashes);
80
84
  return [...scriptSrc, ...generatedScriptHashes, ...userScriptHashes].map((x) => this.formatScriptSrc(x));
81
85
  }
82
86
  extractUniqueHashes(userScriptSrc, existingScriptHashes) {
87
+ var _a;
83
88
  const userScriptHashes = [];
84
- const scriptSrc = userScriptSrc?.filter((scriptSrc) => {
89
+ const scriptSrc = (_a = userScriptSrc === null || userScriptSrc === void 0 ? void 0 : userScriptSrc.filter((scriptSrc) => {
85
90
  const isValidHash = this.isValidHash(scriptSrc);
86
91
  if (isValidHash && !existingScriptHashes.includes(scriptSrc)) {
87
92
  userScriptHashes.push(scriptSrc);
88
93
  }
89
94
  return !isValidHash;
90
- }) ?? [];
95
+ })) !== null && _a !== void 0 ? _a : [];
91
96
  return { scriptSrc, userScriptHashes };
92
97
  }
93
98
  getInlineScriptHashes($) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/csp",
3
- "version": "4.2.0-experimental-959d7b9",
3
+ "version": "4.2.0-experimental-8191ad1",
4
4
  "description": "Contains the CSP configuration for Custom UI resources in Forge",
5
5
  "main": "out/index.js",
6
6
  "author": "Atlassian",