diff --git a/extension/chrome/elements/attachment.ts b/extension/chrome/elements/attachment.ts index 2697e262616..49c94eae54e 100644 --- a/extension/chrome/elements/attachment.ts +++ b/extension/chrome/elements/attachment.ts @@ -195,7 +195,7 @@ export class AttachmentDownloadView extends View { private renderHeader = () => { const span = $(`${this.isEncrypted ? 'ENCRYPTED\n' : 'PLAIN\n'} FILE`); - this.header.empty().append(span); // xss-escaped + this.header.empty().append(span); // xss-direct }; private getFileIconSrc = () => { diff --git a/extension/chrome/elements/compose-modules/compose-quote-module.ts b/extension/chrome/elements/compose-modules/compose-quote-module.ts index 97c5446294e..686650b512c 100644 --- a/extension/chrome/elements/compose-modules/compose-quote-module.ts +++ b/extension/chrome/elements/compose-modules/compose-quote-module.ts @@ -237,11 +237,11 @@ export class ComposeQuoteModule extends ViewModule { const header = `` + `---------- Forwarded message ---------` + - `From: ${from}` + - `Date: ${dateStr}` + - `Subject: ${this.messageToReplyOrForward.headers.subject}` + - `To: ${this.messageToReplyOrForward.headers.to.join(', ')}` + - (this.messageToReplyOrForward.headers.cc?.length ? `Cc: ${this.messageToReplyOrForward.headers.cc?.join(', ')}` : '') + + `From: ${Xss.escape(from || '')}` + + `Date: ${Xss.escape(dateStr)}` + + `Subject: ${Xss.escape(this.messageToReplyOrForward.headers.subject || '')}` + + `To: ${Xss.escape(this.messageToReplyOrForward.headers.to.join(', '))}` + + (this.messageToReplyOrForward.headers.cc?.length ? `Cc: ${Xss.escape(this.messageToReplyOrForward.headers.cc.join(', '))}` : '') + ``; return `${header}${escapedText}`; } diff --git a/extension/chrome/elements/compose-modules/compose-recipients-module.ts b/extension/chrome/elements/compose-modules/compose-recipients-module.ts index ac046ce3f26..472ce153595 100644 --- a/extension/chrome/elements/compose-modules/compose-recipients-module.ts +++ b/extension/chrome/elements/compose-modules/compose-recipients-module.ts @@ -809,7 +809,7 @@ export class ComposeRecipientsModule extends ViewModule { ulHtml += ''; contact.pgpLoading .then(hasPgp => { - Xss.replaceElementDANGEROUSLY($(`[email="${contact.email}"] .loading-icon`)[0], this.getPgpIconHtml(hasPgp)); // xss-escaped + Xss.replaceElementDANGEROUSLY($(`[email="${contact.email}"] .loading-icon`)[0], this.getPgpIconHtml(hasPgp)); // xss-direct }) .catch(() => { this.failedLookupEmails.push(contact.email); diff --git a/extension/chrome/elements/pgp_block_modules/pgp-block-print-module.ts b/extension/chrome/elements/pgp_block_modules/pgp-block-print-module.ts index e79a09b931c..45152923030 100644 --- a/extension/chrome/elements/pgp_block_modules/pgp-block-print-module.ts +++ b/extension/chrome/elements/pgp_block_modules/pgp-block-print-module.ts @@ -95,7 +95,7 @@ export class PgpBlockViewPrintModule { html = policy.createHTML(html); } if (w?.document?.body) { - w.document.body.innerHTML = html; // xss-escaped + w.document.body.innerHTML = html; // xss-reinsert } // Give some time for above dom to load in print dialog // https://stackoverflow.com/questions/31725373/google-chrome-not-showing-image-in-print-preview diff --git a/extension/chrome/settings/inbox/inbox-modules/inbox-menu-module.ts b/extension/chrome/settings/inbox/inbox-modules/inbox-menu-module.ts index 85106abab1b..51450af6016 100644 --- a/extension/chrome/settings/inbox/inbox-modules/inbox-menu-module.ts +++ b/extension/chrome/settings/inbox/inbox-modules/inbox-menu-module.ts @@ -3,7 +3,7 @@ 'use strict'; import { Catch } from '../../../../js/common/platform/catch.js'; -import { Dict } from '../../../../js/common/core/common.js'; +import { checkValidURL, Dict } from '../../../../js/common/core/common.js'; import { GmailRes } from '../../../../js/common/api/email-provider/gmail/gmail-parser.js'; import { Google } from '../../../../js/common/api/email-provider/gmail/google.js'; import { InboxView } from '../inbox.js'; @@ -122,7 +122,7 @@ export class InboxMenuModule extends ViewModule { if (chooseAccountEl) { chooseAccountEl.title = this.view.acctEmail; } - if (this.view.picture) { + if (this.view.picture && checkValidURL(this.view.picture)) { $('img.main-profile-img') .attr('src', this.view.picture) .on( diff --git a/extension/chrome/settings/index.ts b/extension/chrome/settings/index.ts index eb1338a0c6b..692f639e23b 100644 --- a/extension/chrome/settings/index.ts +++ b/extension/chrome/settings/index.ts @@ -5,7 +5,7 @@ import { Bm, BrowserMsg } from '../../js/common/browser/browser-msg.js'; import { Ui } from '../../js/common/browser/ui.js'; import { KeyUtil, KeyInfoWithIdentity } from '../../js/common/core/crypto/key.js'; -import { Str, Url, UrlParams } from '../../js/common/core/common.js'; +import { checkValidURL, Str, Url, UrlParams } from '../../js/common/core/common.js'; import { ApiErr, EnterpriseServerAuthErr } from '../../js/common/api/shared/api-error.js'; import { Assert } from '../../js/common/assert.js'; @@ -300,7 +300,7 @@ View.run( } this.checkGoogleAcct().catch(Catch.reportErr); this.checkFcAcctAndContactPage().catch(Catch.reportErr); - if (storage.picture) { + if (storage.picture && checkValidURL(storage.picture)) { $('img.main-profile-img') .attr('src', storage.picture) .on( diff --git a/extension/js/common/ui/key-import-ui.ts b/extension/js/common/ui/key-import-ui.ts index bd039697aca..cc84ca99c15 100644 --- a/extension/js/common/ui/key-import-ui.ts +++ b/extension/js/common/ui/key-import-ui.ts @@ -89,7 +89,7 @@ export class KeyImportUi { for (const option of ['generate_private_key', 'submit_pubkey']) { const dataTestValue = `input-email-alias-${option}-${e.replace(/[^a-z0-9]+/g, '')}`; $(`.${option}_addresses`).append( - `${Xss.escape(e)}` + `${Xss.escape(e)}` ); // xss-escaped } } diff --git a/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts b/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts index 0244f139943..2fe205d239b 100644 --- a/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts +++ b/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts @@ -55,7 +55,7 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer { } } const pgpBlock = this.generatePgpBlockTemplate(encryptionStatus, verificationStatus, decryptedMsg); - $('body').html(pgpBlock); // xss-sanitized + $('body').html(pgpBlock); // xss-escaped } else { const decryptErr = result as DecryptError; let decryptionErrorMsg = ''; @@ -68,7 +68,7 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer { decryptionErrorMsg = `decrypt error: ${(result as DecryptError).error.message}`; } const pgpBlock = this.generatePgpBlockTemplate(decryptionErrorMsg, 'not signed', this.emailBodyFromThunderbirdMail); - $('body').html(pgpBlock); // xss-sanitized + $('body').html(pgpBlock); // xss-escaped } } else if (this.isCleartextMsg(fullMsg)) { const message = await openpgp.readCleartextMessage({ cleartextMessage: this.emailBodyFromThunderbirdMail }); @@ -82,7 +82,7 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer { verificationStatus = `could not verify signature: ${result.error}`; } const pgpBlock = this.generatePgpBlockTemplate('not encrypted', verificationStatus, signedMessage); - $('body').html(pgpBlock); // xss-sanitized + $('body').html(pgpBlock); // xss-escaped } // todo: detached signed message via https://github.com/FlowCrypt/flowcrypt-browser/issues/5668 } @@ -93,8 +93,8 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer { return ` - ${encryptionStatus} - ${verificationStatus} + ${Xss.escape(encryptionStatus)} + ${Xss.escape(verificationStatus)} ${Xss.escape(messageToRender)}
${Xss.escape(messageToRender)}