fix: Automatically convert MV3 content_security_policy to MV2 (#1168)
Co-authored-by: windmillcode0 <michaelodumosu57@gmail.com> Co-authored-by: windmillcode0 <shieldmousetower734@gmail.com>
This commit is contained in:
@@ -1581,6 +1581,41 @@ describe('Manifest Utils', () => {
|
||||
permissions: ['tabs', 'scripting'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert MV3 CSP object to MV2 CSP string with localhost for MV2', async () => {
|
||||
const entrypoints: Entrypoint[] = [];
|
||||
const buildOutput = fakeBuildOutput();
|
||||
const inputCsp =
|
||||
"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';";
|
||||
const expectedCsp =
|
||||
"script-src 'self' 'wasm-unsafe-eval' http://localhost:3000; object-src 'self';";
|
||||
|
||||
// Setup WXT for Firefox and serve command
|
||||
setFakeWxt({
|
||||
config: {
|
||||
browser: 'firefox',
|
||||
command: 'serve',
|
||||
manifestVersion: 2,
|
||||
manifest: {
|
||||
content_security_policy: {
|
||||
extension_pages: inputCsp,
|
||||
},
|
||||
},
|
||||
},
|
||||
server: fakeWxtDevServer({
|
||||
port: 3000,
|
||||
hostname: 'localhost',
|
||||
origin: 'http://localhost:3000',
|
||||
}),
|
||||
});
|
||||
|
||||
const { manifest: actual } = await generateManifest(
|
||||
entrypoints,
|
||||
buildOutput,
|
||||
);
|
||||
|
||||
expect(actual.content_security_policy).toEqual(expectedCsp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -117,11 +117,12 @@ export async function generateManifest(
|
||||
if (wxt.config.manifestVersion === 2) {
|
||||
convertWebAccessibleResourcesToMv2(manifest);
|
||||
convertActionToMv2(manifest);
|
||||
convertCspToMv2(manifest);
|
||||
moveHostPermissionsToPermissions(manifest);
|
||||
}
|
||||
|
||||
if (wxt.config.manifestVersion === 3) {
|
||||
validateMv3WebAccessbileResources(manifest);
|
||||
validateMv3WebAccessibleResources(manifest);
|
||||
}
|
||||
|
||||
stripKeys(manifest);
|
||||
@@ -143,7 +144,7 @@ export async function generateManifest(
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes suffixes from the version, like X.Y.Z-alpha1 (which brosers don't allow), so it's a
|
||||
* Removes suffixes from the version, like X.Y.Z-alpha1 (which browsers don't allow), so it's a
|
||||
* simple version number, like X or X.Y or X.Y.Z, which browsers allow.
|
||||
*/
|
||||
function simplifyVersion(versionName: string): string {
|
||||
@@ -467,34 +468,28 @@ function addDevModeCsp(manifest: Manifest.WebExtensionManifest): void {
|
||||
}
|
||||
|
||||
const extensionPagesCsp = new ContentSecurityPolicy(
|
||||
manifest.manifest_version === 3
|
||||
? // @ts-expect-error: extension_pages is not typed
|
||||
(manifest.content_security_policy?.extension_pages ??
|
||||
"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';") // default extension_pages CSP for MV3
|
||||
: (manifest.content_security_policy ??
|
||||
"script-src 'self'; object-src 'self';"), // default CSP for MV2
|
||||
// @ts-expect-error: extension_pages exists, we convert MV2 CSPs to this earlier in the process
|
||||
manifest.content_security_policy?.extension_pages ??
|
||||
(manifest.manifest_version === 3
|
||||
? DEFAULT_MV3_EXTENSION_PAGES_CSP
|
||||
: DEFAULT_MV2_CSP),
|
||||
);
|
||||
const sandboxCsp = new ContentSecurityPolicy(
|
||||
// @ts-expect-error: sandbox is not typed
|
||||
manifest.content_security_policy?.sandbox ??
|
||||
"sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';", // default sandbox CSP for MV3
|
||||
manifest.content_security_policy?.sandbox ?? DEFAULT_MV3_SANDBOX_CSP,
|
||||
);
|
||||
|
||||
if (wxt.server) {
|
||||
if (wxt.config.command === 'serve') {
|
||||
extensionPagesCsp.add('script-src', allowedCsp);
|
||||
sandboxCsp.add('script-src', allowedCsp);
|
||||
}
|
||||
|
||||
if (manifest.manifest_version === 3) {
|
||||
manifest.content_security_policy ??= {};
|
||||
// @ts-expect-error: extension_pages is not typed
|
||||
manifest.content_security_policy.extension_pages =
|
||||
extensionPagesCsp.toString();
|
||||
// @ts-expect-error: sandbox is not typed
|
||||
manifest.content_security_policy.sandbox = sandboxCsp.toString();
|
||||
} else {
|
||||
manifest.content_security_policy = extensionPagesCsp.toString();
|
||||
}
|
||||
manifest.content_security_policy ??= {};
|
||||
// @ts-expect-error: extension_pages is not typed
|
||||
manifest.content_security_policy.extension_pages =
|
||||
extensionPagesCsp.toString();
|
||||
// @ts-expect-error: sandbox is not typed
|
||||
manifest.content_security_policy.sandbox = sandboxCsp.toString();
|
||||
}
|
||||
|
||||
function addDevModePermissions(manifest: Manifest.WebExtensionManifest) {
|
||||
@@ -613,7 +608,7 @@ export function stripPathFromMatchPattern(pattern: string) {
|
||||
/**
|
||||
* Converts all MV3 web accessible resources to their MV2 forms. MV3 web accessible resources are
|
||||
* generated in this file, and may be defined by the user in their manifest. In both cases, when
|
||||
* targetting MV2, automatically convert their definitions down to the basic MV2 array.
|
||||
* targeting MV2, automatically convert their definitions down to the basic MV2 array.
|
||||
*/
|
||||
export function convertWebAccessibleResourcesToMv2(
|
||||
manifest: Manifest.WebExtensionManifest,
|
||||
@@ -652,10 +647,21 @@ function convertActionToMv2(manifest: Manifest.WebExtensionManifest): void {
|
||||
manifest.browser_action = manifest.action;
|
||||
}
|
||||
|
||||
function convertCspToMv2(manifest: Manifest.WebExtensionManifest): void {
|
||||
if (
|
||||
typeof manifest.content_security_policy === 'string' ||
|
||||
manifest.content_security_policy?.extension_pages == null
|
||||
)
|
||||
return;
|
||||
|
||||
manifest.content_security_policy =
|
||||
manifest.content_security_policy.extension_pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure all resources are in MV3 format. If not, add a wanring
|
||||
*/
|
||||
export function validateMv3WebAccessbileResources(
|
||||
export function validateMv3WebAccessibleResources(
|
||||
manifest: Manifest.WebExtensionManifest,
|
||||
): void {
|
||||
if (manifest.web_accessible_resources == null) return;
|
||||
@@ -718,3 +724,9 @@ const mv3OnlyKeys = [
|
||||
'side_panel',
|
||||
];
|
||||
const firefoxMv3OnlyKeys = ['host_permissions'];
|
||||
|
||||
const DEFAULT_MV3_EXTENSION_PAGES_CSP =
|
||||
"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';";
|
||||
const DEFAULT_MV3_SANDBOX_CSP =
|
||||
"sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';";
|
||||
const DEFAULT_MV2_CSP = "script-src 'self'; object-src 'self';";
|
||||
|
||||
Generated
+4
@@ -3041,10 +3041,12 @@ packages:
|
||||
|
||||
glob@6.0.4:
|
||||
resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
glob@8.1.0:
|
||||
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
|
||||
engines: {node: '>=12'}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
global-dirs@3.0.1:
|
||||
resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
|
||||
@@ -3174,6 +3176,7 @@ packages:
|
||||
|
||||
inflight@1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
@@ -4283,6 +4286,7 @@ packages:
|
||||
|
||||
rimraf@2.4.5:
|
||||
resolution: {integrity: sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==}
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
|
||||
rollup-plugin-dts@6.1.1:
|
||||
|
||||
Reference in New Issue
Block a user