Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@forge/csp

Package Overview
Dependencies
Maintainers
0
Versions
170
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@forge/csp - npm Package Compare versions

Comparing version 3.2.1-experimental-a59129c to 3.2.1-experimental-a92f9f3

115

out/csp/csp-injection-service.js

@@ -27,59 +27,2 @@ "use strict";

class CSPInjectionService {
constructor() {
this.getInjectableCSP = ({ existingCSPDetails, microsEnv, tunnelCSPReporterUri, hostname, isFedRAMP }) => {
const reportUri = tunnelCSPReporterUri || this.getCSPReportUri(microsEnv);
const defaultSrc = `'self'`;
const frameAncestors = ["'self'", ...this.getFrameAncestors(microsEnv, hostname)].join(' ');
const frameSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FRAME_SRC, existingCSPDetails)].join(' ');
const fontSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FONT_SRC, existingCSPDetails)].join(' ');
const imgSrc = [
"'self'",
'data:',
'blob:',
hostname,
gravatarUrl,
...atlassianImageHosts[microsEnv],
...this.getExistingCSPDetails(types_1.ExternalCspType.IMG_SRC, existingCSPDetails)
]
.filter((a) => a)
.join(' ');
const mediaSrc = [
"'self'",
'data:',
'blob:',
...this.getExistingCSPDetails(types_1.ExternalCspType.MEDIA_SRC, existingCSPDetails)
].join(' ');
const connectSrc = [
"'self'",
...this.getConnectSrc(microsEnv, !!tunnelCSPReporterUri),
...this.getExistingCSPDetails(types_1.ExternalCspType.CONNECT_SRC, existingCSPDetails)
].join(' ');
const scriptSrc = [
"'self'",
this.getForgeGlobalCSP(microsEnv, isFedRAMP),
...this.getExistingCSPDetails(types_1.ExternalCspType.SCRIPT_SRC, existingCSPDetails)
].join(' ');
const styleSrc = [
"'self'",
this.getForgeGlobalCSP(microsEnv, isFedRAMP),
...this.getExistingCSPDetails(types_1.ExternalCspType.STYLE_SRC, existingCSPDetails)
].join(' ');
const navigateTo = ["'self'"];
return [
`default-src ${defaultSrc}`,
`frame-ancestors ${frameAncestors}`,
`frame-src ${frameSrc}`,
`font-src ${fontSrc}`,
`img-src ${imgSrc}`,
`media-src ${mediaSrc}`,
`connect-src ${connectSrc}`,
`script-src ${scriptSrc}`,
`navigate-to ${navigateTo}`,
`style-src ${styleSrc}`,
`form-action 'self'`,
`sandbox allow-downloads allow-forms allow-modals allow-pointer-lock allow-same-origin allow-scripts`,
`report-uri ${reportUri}`
];
};
}
getCSPReportUri(microsEnv) {

@@ -96,4 +39,3 @@ if (microsEnv === 'dev' || microsEnv === 'stg')

getExistingCSPDetails(cspType, cspDetails) {
var _a;
return (_a = cspDetails[cspType]) !== null && _a !== void 0 ? _a : [];
return cspDetails[cspType] ?? [];
}

@@ -135,3 +77,58 @@ getConnectSrc(microsEnv, isTunnelling) {

}
getInjectableCSP = ({ existingCSPDetails, microsEnv, tunnelCSPReporterUri, hostname, isFedRAMP }) => {
const reportUri = tunnelCSPReporterUri || this.getCSPReportUri(microsEnv);
const defaultSrc = `'self'`;
const frameAncestors = ["'self'", ...this.getFrameAncestors(microsEnv, hostname)].join(' ');
const frameSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FRAME_SRC, existingCSPDetails)].join(' ');
const fontSrc = ["'self'", ...this.getExistingCSPDetails(types_1.ExternalCspType.FONT_SRC, existingCSPDetails)].join(' ');
const imgSrc = [
"'self'",
'data:',
'blob:',
hostname,
gravatarUrl,
...atlassianImageHosts[microsEnv],
...this.getExistingCSPDetails(types_1.ExternalCspType.IMG_SRC, existingCSPDetails)
]
.filter((a) => a)
.join(' ');
const mediaSrc = [
"'self'",
'data:',
'blob:',
...this.getExistingCSPDetails(types_1.ExternalCspType.MEDIA_SRC, existingCSPDetails)
].join(' ');
const connectSrc = [
"'self'",
...this.getConnectSrc(microsEnv, !!tunnelCSPReporterUri),
...this.getExistingCSPDetails(types_1.ExternalCspType.CONNECT_SRC, existingCSPDetails)
].join(' ');
const scriptSrc = [
"'self'",
this.getForgeGlobalCSP(microsEnv, isFedRAMP),
...this.getExistingCSPDetails(types_1.ExternalCspType.SCRIPT_SRC, existingCSPDetails)
].join(' ');
const styleSrc = [
"'self'",
this.getForgeGlobalCSP(microsEnv, isFedRAMP),
...this.getExistingCSPDetails(types_1.ExternalCspType.STYLE_SRC, existingCSPDetails)
].join(' ');
const navigateTo = ["'self'"];
return [
`default-src ${defaultSrc}`,
`frame-ancestors ${frameAncestors}`,
`frame-src ${frameSrc}`,
`font-src ${fontSrc}`,
`img-src ${imgSrc}`,
`media-src ${mediaSrc}`,
`connect-src ${connectSrc}`,
`script-src ${scriptSrc}`,
`navigate-to ${navigateTo}`,
`style-src ${styleSrc}`,
`form-action 'self'`,
`sandbox allow-downloads allow-forms allow-modals allow-pointer-lock allow-same-origin allow-scripts`,
`report-uri ${reportUri}`
];
};
}
exports.CSPInjectionService = CSPInjectionService;

@@ -15,32 +15,35 @@ "use strict";

class CSPProcessingService {
logger;
STYLE_SRC_ALLOWLIST = [`'unsafe-inline'`];
QUOTED_SCRIPT_SRC_ALLOWLIST = ['unsafe-inline', 'unsafe-eval', 'unsafe-hashes'];
UNQUOTED_SCRIPT_SRC_ALLOWLIST = ['blob:'];
SCRIPT_SRC_ALLOWLIST = [...this.QUOTED_SCRIPT_SRC_ALLOWLIST, ...this.UNQUOTED_SCRIPT_SRC_ALLOWLIST];
BASE_64_HASH_PATTERNS = [
/^sha256-[a-zA-Z0-9=+/]{44}$/,
/^sha384-[a-zA-Z0-9=+/]{64}$/,
/^sha512-[a-zA-Z0-9=+/]{88}$/
];
constructor(logger) {
this.logger = logger;
this.STYLE_SRC_ALLOWLIST = [`'unsafe-inline'`];
this.QUOTED_SCRIPT_SRC_ALLOWLIST = ['unsafe-inline', 'unsafe-eval', 'unsafe-hashes'];
this.UNQUOTED_SCRIPT_SRC_ALLOWLIST = ['blob:'];
this.SCRIPT_SRC_ALLOWLIST = [...this.QUOTED_SCRIPT_SRC_ALLOWLIST, ...this.UNQUOTED_SCRIPT_SRC_ALLOWLIST];
this.BASE_64_HASH_PATTERNS = [
/^sha256-[a-zA-Z0-9=+/]{44}$/,
/^sha384-[a-zA-Z0-9=+/]{64}$/,
/^sha512-[a-zA-Z0-9=+/]{88}$/
];
}
getCspDetails(body, permissions) {
var _a, _b;
const { scripts, styles } = (_a = permissions === null || permissions === void 0 ? void 0 : permissions.content) !== null && _a !== void 0 ? _a : { scripts: [], styles: [] };
const external = (_b = permissions === null || permissions === void 0 ? void 0 : permissions.external) !== null && _b !== void 0 ? _b : {};
const { scripts, styles } = permissions?.content ?? { scripts: [], styles: [] };
const external = permissions?.external ?? {};
const $ = cheerio_1.default.load(body);
const _c = this.mapExternalPermissionsToCsp(external), { 'script-src': scriptSrc, 'style-src': styleSrc } = _c, mappedExternalCsp = tslib_1.__rest(_c, ['script-src', 'style-src']);
return Object.assign({ 'style-src': [...this.getStyleSrc($, styles), ...styleSrc], 'script-src': [...this.getScriptSrc($, scripts), ...scriptSrc] }, mappedExternalCsp);
const { 'script-src': scriptSrc, 'style-src': styleSrc, ...mappedExternalCsp } = this.mapExternalPermissionsToCsp(external);
return {
'style-src': [...this.getStyleSrc($, styles), ...styleSrc],
'script-src': [...this.getScriptSrc($, scripts), ...scriptSrc],
...mappedExternalCsp
};
}
getInvalidCspPermissions(contentPermissions) {
var _a, _b;
const { styles, scripts } = contentPermissions;
const invalidStyles = (_a = styles === null || styles === void 0 ? void 0 : styles.filter((styleSrc) => !this.isValidUserStyleSrc(`'${styleSrc}'`))) !== null && _a !== void 0 ? _a : [];
const invalidScripts = (_b = scripts === null || scripts === void 0 ? void 0 : scripts.filter((scriptSrc) => !this.isValidUserScriptSrc(scriptSrc))) !== null && _b !== void 0 ? _b : [];
const invalidStyles = styles?.filter((styleSrc) => !this.isValidUserStyleSrc(`'${styleSrc}'`)) ?? [];
const invalidScripts = scripts?.filter((scriptSrc) => !this.isValidUserScriptSrc(scriptSrc)) ?? [];
return [...invalidStyles, ...invalidScripts];
}
assertValidFetchClient(fetch) {
if (fetch === null || fetch === void 0 ? void 0 : fetch.client) {
for (const client of fetch === null || fetch === void 0 ? void 0 : fetch.client) {
if (fetch?.client) {
for (const client of fetch?.client) {
if (typeof client !== 'string') {

@@ -53,19 +56,17 @@ throw new InvalidConnectSrc();

mapExternalPermissionsToCsp(externalPermissions) {
var _a;
const { images, media, scripts, fetch, styles, fonts, frames } = externalPermissions;
this.assertValidFetchClient(fetch);
return {
'img-src': images !== null && images !== void 0 ? images : [],
'media-src': media !== null && media !== void 0 ? media : [],
'script-src': scripts !== null && scripts !== void 0 ? scripts : [],
'style-src': styles !== null && styles !== void 0 ? styles : [],
'connect-src': (_a = fetch === null || fetch === void 0 ? void 0 : fetch.client) !== null && _a !== void 0 ? _a : [],
'font-src': fonts !== null && fonts !== void 0 ? fonts : [],
'frame-src': frames !== null && frames !== void 0 ? frames : []
'img-src': images ?? [],
'media-src': media ?? [],
'script-src': scripts ?? [],
'style-src': styles ?? [],
'connect-src': fetch?.client ?? [],
'font-src': fonts ?? [],
'frame-src': frames ?? []
};
}
getStyleSrc($, userStyleSrc) {
var _a, _b;
const quotedUserStyleSrc = (_a = userStyleSrc === null || userStyleSrc === void 0 ? void 0 : userStyleSrc.map((x) => `'${x}'`)) !== null && _a !== void 0 ? _a : [];
const deprecatedUserStyleSrc = (_b = this.getDeprecatedUserCsp($)['style-src']) !== null && _b !== void 0 ? _b : [];
const quotedUserStyleSrc = userStyleSrc?.map((x) => `'${x}'`) ?? [];
const deprecatedUserStyleSrc = this.getDeprecatedUserCsp($)['style-src'] ?? [];
const uniqueStyleSrc = [...new Set([...deprecatedUserStyleSrc, ...quotedUserStyleSrc])];

@@ -75,4 +76,3 @@ return uniqueStyleSrc.filter((x) => this.isValidUserStyleSrc(x));

getScriptSrc($, userScriptSrc) {
var _a;
const validUserScriptSrc = (_a = userScriptSrc === null || userScriptSrc === void 0 ? void 0 : userScriptSrc.filter((x) => this.isValidUserScriptSrc(x))) !== null && _a !== void 0 ? _a : [];
const validUserScriptSrc = userScriptSrc?.filter((x) => this.isValidUserScriptSrc(x)) ?? [];
const generatedScriptHashes = validUserScriptSrc.includes('unsafe-inline') ? [] : this.getInlineScriptHashes($);

@@ -83,5 +83,4 @@ const { scriptSrc, userScriptHashes } = this.extractUniqueHashes(validUserScriptSrc, generatedScriptHashes);

extractUniqueHashes(userScriptSrc, existingScriptHashes) {
var _a;
const userScriptHashes = [];
const scriptSrc = (_a = userScriptSrc === null || userScriptSrc === void 0 ? void 0 : userScriptSrc.filter((scriptSrc) => {
const scriptSrc = userScriptSrc?.filter((scriptSrc) => {
const isValidHash = this.isValidHash(scriptSrc);

@@ -92,3 +91,3 @@ if (isValidHash && !existingScriptHashes.includes(scriptSrc)) {

return !isValidHash;
})) !== null && _a !== void 0 ? _a : [];
}) ?? [];
return { scriptSrc, userScriptHashes };

@@ -95,0 +94,0 @@ }

{
"name": "@forge/csp",
"version": "3.2.1-experimental-a59129c",
"version": "3.2.1-experimental-a92f9f3",
"description": "Contains the CSP configuration for Custom UI resources in Forge",

@@ -14,4 +14,4 @@ "main": "out/index.js",

"devDependencies": {
"@forge/cli-shared": "4.2.0-next.1-experimental-a59129c",
"@forge/manifest": "7.2.2-next.0-experimental-a59129c",
"@forge/cli-shared": "5.0.2-next.0-experimental-a92f9f3",
"@forge/manifest": "7.4.1-next.0-experimental-a92f9f3",
"@types/jest": "^29.5.12",

@@ -18,0 +18,0 @@ "@types/node": "14.18.63"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc