diff --git a/extension/chrome/elements/pgp_pubkey.ts b/extension/chrome/elements/pgp_pubkey.ts
index c8ac696180d..7081e0c4356 100644
--- a/extension/chrome/elements/pgp_pubkey.ts
+++ b/extension/chrome/elements/pgp_pubkey.ts
@@ -190,7 +190,7 @@ View.run(
private showKeyNotUsableError = async () => {
$('.error_container').removeClass('hidden');
- $('.error_introduce_label').html(`This OpenPGP key is not usable.
(${await this.getErrorText()})`); // xss-escaped
+ $('.error_introduce_label').html(`This OpenPGP key is not usable.
(${Xss.escape(await this.getErrorText())})`); // xss-escaped
$('.hide_if_error').hide();
$('.fingerprints, .add_contact, #manual_import_warning').remove();
const email = this.firstParsedPublicKey ? KeyUtil.getPrimaryEmail(this.firstParsedPublicKey) : undefined;
diff --git a/extension/chrome/settings/modules/contacts.ts b/extension/chrome/settings/modules/contacts.ts
index 8912a086d96..432f3ccf993 100644
--- a/extension/chrome/settings/modules/contacts.ts
+++ b/extension/chrome/settings/modules/contacts.ts
@@ -175,13 +175,16 @@ View.run(
}
const key = await KeyUtil.parse(armoredPubkey);
$('.hide_when_rendering_subpage').css('display', 'none');
- Xss.sanitizeRender('h1', `${this.backBtn}${this.space}${email} `);
+ Xss.sanitizeRender('h1', `${this.backBtn}${this.space}${Xss.escape(email)} `); // xss-escaped
$('#view_contact .key_dump').text(armoredPubkey);
$('#view_contact #container-pubkey-details').text(
[
`Type: ${key.family}`,
`Fingerprint: ${Str.spaced(key.id || 'none')}`,
- `Users: ${key.users?.map(u => u.email).filter(Boolean).join(', ')}`,
+ `Users: ${key.users
+ ?.map(u => u.email)
+ .filter(Boolean)
+ .join(', ')}`,
`Created on: ${key.created ? new Date(key.created) : ''}`,
`Expiration: ${key.expiration ? new Date(key.expiration) : 'Does not expire'}`,
`Last signature: ${key.lastModified ? new Date(key.lastModified) : ''}`,
diff --git a/extension/js/common/ui/passphrase-ui.ts b/extension/js/common/ui/passphrase-ui.ts
index 32f15e6149e..e1630e8cc10 100644
--- a/extension/js/common/ui/passphrase-ui.ts
+++ b/extension/js/common/ui/passphrase-ui.ts
@@ -90,8 +90,8 @@ export const isCreatePrivateFormInputCorrect = async (section: string, clientCon
Please write down your passphrase and store it in safe place or even two.
It is needed in order to access your FlowCrypt account.
-
${notePp}
- `;
+ ${Xss.escape(notePp)}
+ `; // xss-escaped
return await Ui.modal.confirmWithCheckbox('Yes, I wrote it down', paperPassPhraseStickyNote);
}
return true;
diff --git a/extension/manifest.json b/extension/manifest.json
index c4bcbbf63ef..df68a026b53 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -92,6 +92,6 @@
],
"minimum_chrome_version": "96",
"content_security_policy": {
- "extension_pages": "script-src 'self'; frame-ancestors 'self' https://mail.google.com; img-src 'self' data: blob: https:; frame-src 'self' blob:; worker-src 'self'; form-action 'none'; media-src 'none'; font-src 'none'; manifest-src 'none'; object-src 'none'; base-uri 'self';"
+ "extension_pages": "script-src 'self'; default-src 'self'; frame-ancestors 'self' https://mail.google.com; img-src 'self' https://* data: blob:; frame-src 'self' blob:; worker-src 'self'; form-action 'none'; media-src 'none'; font-src 'none'; manifest-src 'none'; object-src 'none'; base-uri 'self'; connect-src 'self' https://flowcrypt.com https://*.flowcrypt.com https://flowcrypt.s3.amazonaws.com https://www.google.com https://gmail.googleapis.com;"
}
}
diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts
index 97054225ffa..5d539128b09 100644
--- a/tooling/build-types-and-manifests.ts
+++ b/tooling/build-types-and-manifests.ts
@@ -173,9 +173,23 @@ const makeMockBuild = (sourceBuildType: string) => {
edit(`${buildDir(mockBuildType)}/js/common/core/const.js`, editor);
edit(`${buildDir(mockBuildType)}/js/common/platform/catch.js`, editor);
edit(`${buildDir(mockBuildType)}/js/content_scripts/webmail_bundle.js`, editor);
- edit(`${buildDir(mockBuildType)}/manifest.json`, code =>
- code.replace(/https:\/\/mail\.google\.com/g, mockGmailPage).replace(/https:\/\/\*\.google.com\/\*/, 'https://google.localhost/*')
- );
+ edit(`${buildDir(mockBuildType)}/manifest.json`, code => {
+ let updatedCode = code.replace(/https:\/\/mail\.google\.com/g, mockGmailPage).replace(/https:\/\/\*\.google.com\/\*/, 'https://google.localhost/*');
+ const manifest = JSON.parse(updatedCode) as chrome.runtime.ManifestV3;
+ if (manifest.content_security_policy?.extension_pages) {
+ const csp = manifest.content_security_policy.extension_pages;
+ if (csp) {
+ let updatedCsp = csp.replace(
+ /connect-src[^;]*/,
+ "connect-src 'self' https://localhost:* https://flowcrypt.com https://fes.flowcrypt.test https://fes.standardsubdomainfes.localhost:* https://fes.key-manager-server-offline.flowcrypt.test https://google.com https://www.google.com https://*.flowcrypt.com https://flowcrypt.s3.amazonaws.com https://*.localhost:* https://google.localhost:* https://gmail.localhost:*;"
+ );
+ updatedCsp += "; style-src 'self' 'unsafe-inline'";
+ manifest.content_security_policy.extension_pages = updatedCsp;
+ }
+ updatedCode = JSON.stringify(manifest, undefined, 2);
+ }
+ return updatedCode;
+ });
};
const makeLocalFesBuild = (sourceBuildType: string) => {