From 9a50c1b531c57165f97c32f087b3c3eb96fdffc4 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Fri, 1 Nov 2024 15:28:35 -0400 Subject: [PATCH] use disabled URIs service state as a preemptive conditon to injecting content scripts --- .../services/autofill.service.spec.ts | 6 ++++- .../browser/src/background/main.background.ts | 1 + .../browser-script-injector.service.spec.ts | 8 ++++++- .../browser-script-injector.service.ts | 24 +++++++++++++++++++ .../src/popup/services/services.module.ts | 2 +- .../fileless-importer.background.spec.ts | 8 ++++++- 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/apps/browser/src/autofill/services/autofill.service.spec.ts b/apps/browser/src/autofill/services/autofill.service.spec.ts index 91f926440a0..d3b9dfdec4d 100644 --- a/apps/browser/src/autofill/services/autofill.service.spec.ts +++ b/apps/browser/src/autofill/services/autofill.service.spec.ts @@ -98,7 +98,11 @@ describe("AutofillService", () => { let messageListener: MockProxy; beforeEach(() => { - scriptInjectorService = new BrowserScriptInjectorService(platformUtilsService, logService); + scriptInjectorService = new BrowserScriptInjectorService( + domainSettingsService, + platformUtilsService, + logService, + ); inlineMenuVisibilityMock$ = new BehaviorSubject(AutofillOverlayVisibility.OnFieldFocus); showInlineMenuCardsMock$ = new BehaviorSubject(false); showInlineMenuIdentitiesMock$ = new BehaviorSubject(false); diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 555e3a13fa0..618512cc51c 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -957,6 +957,7 @@ export default class MainBackground { this.totpService = new TotpService(this.cryptoFunctionService, this.logService); this.scriptInjectorService = new BrowserScriptInjectorService( + this.domainSettingsService, this.platformUtilsService, this.logService, ); diff --git a/apps/browser/src/platform/services/browser-script-injector.service.spec.ts b/apps/browser/src/platform/services/browser-script-injector.service.spec.ts index d6ec3dfde96..fb5b76fa402 100644 --- a/apps/browser/src/platform/services/browser-script-injector.service.spec.ts +++ b/apps/browser/src/platform/services/browser-script-injector.service.spec.ts @@ -1,5 +1,6 @@ import { mock } from "jest-mock-extended"; +import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -25,11 +26,16 @@ describe("ScriptInjectorService", () => { let scriptInjectorService: BrowserScriptInjectorService; jest.spyOn(BrowserApi, "executeScriptInTab").mockImplementation(); jest.spyOn(BrowserApi, "isManifestVersion"); + const domainSettingsService = mock(); const platformUtilsService = mock(); const logService = mock(); beforeEach(() => { - scriptInjectorService = new BrowserScriptInjectorService(platformUtilsService, logService); + scriptInjectorService = new BrowserScriptInjectorService( + domainSettingsService, + platformUtilsService, + logService, + ); }); describe("inject", () => { diff --git a/apps/browser/src/platform/services/browser-script-injector.service.ts b/apps/browser/src/platform/services/browser-script-injector.service.ts index 2a6b7397a6c..c326ec78b21 100644 --- a/apps/browser/src/platform/services/browser-script-injector.service.ts +++ b/apps/browser/src/platform/services/browser-script-injector.service.ts @@ -1,3 +1,7 @@ +import { Subject, takeUntil } from "rxjs"; + +import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; +import { NeverDomains } from "@bitwarden/common/models/domain/domain-service"; // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -12,11 +16,22 @@ import { } from "./abstractions/script-injector.service"; export class BrowserScriptInjectorService extends ScriptInjectorService { + disabledDomains: Set = null; + + private destroy$ = new Subject(); + constructor( + private readonly domainSettingsService: DomainSettingsService, private readonly platformUtilsService: PlatformUtilsService, private readonly logService: LogService, ) { super(); + + this.domainSettingsService.disabledInteractionsUris$ + .pipe(takeUntil(this.destroy$)) + .subscribe( + (neverDomains: NeverDomains) => (this.disabledDomains = new Set(Object.keys(neverDomains))), + ); } /** @@ -32,6 +47,15 @@ export class BrowserScriptInjectorService extends ScriptInjectorService { throw new Error("No file specified for script injection"); } + // Check if the tab URI is on the disabled URIs list + const tab = await BrowserApi.getTab(tabId); + const tabURL = tab.url ? new URL(tab.url) : null; + const injectionAllowedInTab = !(tabURL && this.disabledDomains?.has(tabURL.hostname)); + + if (!injectionAllowedInTab) { + throw new Error("This URI of this tab is on the disabled domains list."); + } + const injectionDetails = this.buildInjectionDetails(injectDetails, file); if (BrowserApi.isManifestVersion(3)) { diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 5b27833636f..a854a14b100 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -365,7 +365,7 @@ const safeProviders: SafeProvider[] = [ safeProvider({ provide: ScriptInjectorService, useClass: BrowserScriptInjectorService, - deps: [PlatformUtilsService, LogService], + deps: [DomainSettingsService, PlatformUtilsService, LogService], }), safeProvider({ provide: VaultTimeoutService, diff --git a/apps/browser/src/tools/background/fileless-importer.background.spec.ts b/apps/browser/src/tools/background/fileless-importer.background.spec.ts index 7b356b18fd5..83a38201f29 100644 --- a/apps/browser/src/tools/background/fileless-importer.background.spec.ts +++ b/apps/browser/src/tools/background/fileless-importer.background.spec.ts @@ -4,6 +4,7 @@ import { firstValueFrom } from "rxjs"; import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthService } from "@bitwarden/common/auth/services/auth.service"; +import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -35,6 +36,7 @@ jest.mock("rxjs", () => { describe("FilelessImporterBackground ", () => { let filelessImporterBackground: FilelessImporterBackground; const configService = mock(); + const domainSettingsService = mock(); const authService = mock(); const policyService = mock(); const notificationBackground = mock(); @@ -45,7 +47,11 @@ describe("FilelessImporterBackground ", () => { let scriptInjectorService: BrowserScriptInjectorService; beforeEach(() => { - scriptInjectorService = new BrowserScriptInjectorService(platformUtilsService, logService); + scriptInjectorService = new BrowserScriptInjectorService( + domainSettingsService, + platformUtilsService, + logService, + ); filelessImporterBackground = new FilelessImporterBackground( configService, authService,