mirror of
https://github.com/bitwarden/browser
synced 2026-01-30 00:03:30 +00:00
[PM-29271] Add referrer checking for vault messages (#18346)
* update message from vault handling to check against accounts or message sender * update valid vault referrer logic to check all configured environments
This commit is contained in:
@@ -291,15 +291,21 @@ export default class RuntimeBackground {
|
||||
}
|
||||
break;
|
||||
case "openPopup":
|
||||
await this.openPopup();
|
||||
await this.executeMessageActionOrOpenPopup(msg, this.openPopup.bind(this));
|
||||
break;
|
||||
case VaultMessages.OpenAtRiskPasswords: {
|
||||
await this.main.openAtRisksPasswordsPage();
|
||||
await this.executeMessageActionOrOpenPopup(
|
||||
msg,
|
||||
this.main.openAtRisksPasswordsPage.bind(this),
|
||||
);
|
||||
this.announcePopupOpen();
|
||||
break;
|
||||
}
|
||||
case VaultMessages.OpenBrowserExtensionToUrl: {
|
||||
await this.main.openTheExtensionToPage(msg.url);
|
||||
await this.executeMessageActionOrOpenPopup(
|
||||
msg,
|
||||
this.main.openTheExtensionToPage.bind(this, msg.url),
|
||||
);
|
||||
this.announcePopupOpen();
|
||||
break;
|
||||
}
|
||||
@@ -374,40 +380,55 @@ export default class RuntimeBackground {
|
||||
* @param message
|
||||
* @returns true if message fails validation
|
||||
*/
|
||||
private async shouldRejectManyOriginMessage(message: {
|
||||
webExtSender: chrome.runtime.MessageSender;
|
||||
}): Promise<boolean> {
|
||||
private async executeMessageActionOrOpenPopup(
|
||||
message: {
|
||||
webExtSender: chrome.runtime.MessageSender;
|
||||
},
|
||||
messageAction: () => Promise<void>,
|
||||
): Promise<boolean> {
|
||||
const hasAccounts = await firstValueFrom(
|
||||
this.accountService.accounts$.pipe(map((a) => Object.keys(a).length > 0)),
|
||||
);
|
||||
|
||||
// When there are no accounts associated with the extension, only allow opening the popup
|
||||
if (!hasAccounts) {
|
||||
await this.openPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
const isValidVaultReferrer = await this.isValidVaultReferrer(
|
||||
Utils.getHostname(message?.webExtSender?.origin),
|
||||
);
|
||||
|
||||
if (isValidVaultReferrer) {
|
||||
return false;
|
||||
// When the referrer is not a known vault and the message is external, reject the message
|
||||
if (!isValidVaultReferrer && isExternalMessage(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return isExternalMessage(message);
|
||||
await messageAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a message's referrer matches the configured web vault hostname.
|
||||
* Validates that a referrer hostname matches any of the available regions' and current environment web vault URLs.
|
||||
*
|
||||
* @param referrer - hostname from message source
|
||||
* @returns true if referrer matches web vault
|
||||
* @param referrer - hostname from message source (should not include protocol or path)
|
||||
* @returns true if referrer matches any known vault hostname, false otherwise
|
||||
*/
|
||||
private async isValidVaultReferrer(referrer: string | null | undefined): Promise<boolean> {
|
||||
if (!referrer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const env = await firstValueFrom(this.environmentService.environment$);
|
||||
const vaultUrl = env.getWebVaultUrl();
|
||||
const vaultHostname = Utils.getHostname(vaultUrl);
|
||||
const environment = await firstValueFrom(this.environmentService.environment$);
|
||||
|
||||
if (!vaultHostname) {
|
||||
return false;
|
||||
}
|
||||
const regions = this.environmentService.availableRegions();
|
||||
const regionVaultUrls = regions.map((r) => r.urls.webVault ?? r.urls.base);
|
||||
const environmentWebVaultUrl = environment.getWebVaultUrl();
|
||||
const messageIsFromKnownVault = [...regionVaultUrls, environmentWebVaultUrl].some(
|
||||
(webVaultUrl) => Utils.getHostname(webVaultUrl) === referrer,
|
||||
);
|
||||
|
||||
return vaultHostname === referrer;
|
||||
return messageIsFromKnownVault;
|
||||
}
|
||||
|
||||
private async autofillPage(tabToAutoFill: chrome.tabs.Tab) {
|
||||
|
||||
Reference in New Issue
Block a user