From e8ddd67c9eef154bc0108ab0e65f4f34aaa95107 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 0b036e17a303..b431d0b1c6d5 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 c3ecb5d3fe73..6a7fbf8d0285 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -984,6 +984,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 d6ec3dfde96a..fb5b76fa4028 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 5b3a10ef2bbd..77c1723af259 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"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -10,11 +14,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))), + ); } /** @@ -30,6 +45,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 14ebfb4a1753..2bcb250f9519 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -351,7 +351,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 7b356b18fd5e..83a38201f291 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,