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) => {