1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-22629] Forbid importing popup outside (#15168)

Adds an eslint rule forbidding non popup scripts from importing popups. Also added a webpack plugin that throws if it detects @angular inside background output.
This commit is contained in:
Oscar Hinton
2025-06-13 15:54:49 +02:00
committed by GitHub
parent 40cbac350a
commit 70ad4d048b
32 changed files with 126 additions and 11 deletions

View File

@@ -9,7 +9,7 @@ import {
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { BrowserRouterService } from "../../platform/popup/services/browser-router.service";
import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service";
/**
* This guard verifies the user's authentication status.

View File

@@ -22,7 +22,11 @@ import { DuoLaunchAction } from "@bitwarden/auth/angular";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { BrowserApi } from "../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
AuthPopoutType,
closeSsoAuthResultPopout,

View File

@@ -6,7 +6,11 @@ import {
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { BrowserApi } from "../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
AuthPopoutType,
closeSsoAuthResultPopout,

View File

@@ -5,6 +5,8 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openTwoFactorAuthDuoPopout } from "../../auth/popup/utils/auth-popout-window";
import { ZonedMessageListenerService } from "../../platform/browser/zoned-message-listener.service";

View File

@@ -17,7 +17,11 @@ jest.mock("../../platform/popup/browser-popup-utils", () => ({
inPopup: jest.fn(),
}));
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openTwoFactorAuthEmailPopout } from "../../auth/popup/utils/auth-popout-window";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
import { ExtensionTwoFactorAuthEmailComponentService } from "./extension-two-factor-auth-email-component.service";

View File

@@ -6,7 +6,11 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { DialogService } from "@bitwarden/components";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openTwoFactorAuthEmailPopout } from "../../auth/popup/utils/auth-popout-window";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
// TODO: popup state persistence should eventually remove the need for this service

View File

@@ -44,8 +44,12 @@ import { TaskService } from "@bitwarden/common/vault/tasks";
import { SecurityTaskType } from "@bitwarden/common/vault/tasks/enums";
import { SecurityTask } from "@bitwarden/common/vault/tasks/models/security-task";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openUnlockPopout } from "../../auth/popup/utils/auth-popout-window";
import { BrowserApi } from "../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
openAddEditVaultItemPopout,
openViewVaultItemPopout,

View File

@@ -49,8 +49,12 @@ import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view"
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openUnlockPopout } from "../../auth/popup/utils/auth-popout-window";
import { BrowserApi } from "../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
openAddEditVaultItemPopout,
openViewVaultItemPopout,

View File

@@ -30,8 +30,12 @@ import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openUnlockPopout } from "../../auth/popup/utils/auth-popout-window";
import { BrowserApi } from "../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
openAddEditVaultItemPopout,
openVaultItemPasswordRepromptPopout,

View File

@@ -28,6 +28,8 @@ import {
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { BrowserApi } from "../../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { closeFido2Popout, openFido2Popout } from "../../../vault/popup/utils/vault-popout-window";
const BrowserFido2MessageName = "BrowserFido2UserInterfaceServiceMessage";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { Injectable } from "@angular/core";
import { BehaviorSubject, Observable } from "rxjs";

View File

@@ -49,6 +49,8 @@ import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view"
import { BrowserApi } from "../../platform/browser/browser-api";
import { ScriptInjectorService } from "../../platform/services/abstractions/script-injector.service";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openVaultItemPasswordRepromptPopout } from "../../vault/popup/utils/vault-popout-window";
import { AutofillMessageCommand, AutofillMessageSender } from "../enums/autofill-message.enums";
import { AutofillPort } from "../enums/autofill-port.enum";

View File

@@ -6,6 +6,8 @@ import { ExtensionCommand, ExtensionCommandType } from "@bitwarden/common/autofi
import { VaultTimeoutService } from "@bitwarden/common/key-management/vault-timeout";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { openUnlockPopout } from "../auth/popup/utils/auth-popout-window";
import { LockedVaultPendingNotificationsData } from "../autofill/background/abstractions/notification.background";
import { BrowserApi } from "../platform/browser/browser-api";

View File

@@ -20,6 +20,8 @@ import { CipherType } from "@bitwarden/common/vault/enums";
import { VaultMessages } from "@bitwarden/common/vault/enums/vault-messages.enum";
import { BiometricsCommands } from "@bitwarden/key-management";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import {
closeUnlockPopout,
openSsoAuthResultPopout,

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { firstValueFrom, of } from "rxjs";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { Injectable } from "@angular/core";
import { map, Observable, of, switchMap } from "rxjs";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { Injectable } from "@angular/core";
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { Component } from "@angular/core";
import { RemovePasswordComponent as BaseRemovePasswordComponent } from "@bitwarden/key-management-ui";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { firstValueFrom, of } from "rxjs";
@@ -18,7 +20,11 @@ import {
import { UnlockOptions } from "@bitwarden/key-management-ui";
import { BrowserApi } from "../../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service";
import { ExtensionLockComponentService } from "./extension-lock-component.service";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { inject } from "@angular/core";
import { combineLatest, defer, firstValueFrom, map, Observable } from "rxjs";
@@ -15,7 +17,11 @@ import { LockComponentService, UnlockOptions } from "@bitwarden/key-management-u
import { BiometricErrors, BiometricErrorTypes } from "../../../models/biometricErrors";
import { BrowserApi } from "../../../platform/browser/browser-api";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service";
export class ExtensionLockComponentService implements LockComponentService {

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { NgZone } from "@angular/core";
import { MonoTypeOperatorFunction, Observable } from "rxjs";

View File

@@ -1,3 +1,5 @@
// FIXME (PM-22628): angular imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { Injectable, NgZone } from "@angular/core";
import { Observable } from "rxjs";

View File

@@ -43,12 +43,12 @@ import {
} from "@bitwarden/auth/angular";
import { LockComponent } from "@bitwarden/key-management-ui";
import { fido2AuthGuard } from "../auth/guards/fido2-auth.guard";
import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component";
import {
ExtensionAnonLayoutWrapperComponent,
ExtensionAnonLayoutWrapperData,
} from "../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper.component";
import { fido2AuthGuard } from "../auth/popup/guards/fido2-auth.guard";
import { SetPasswordComponent } from "../auth/popup/set-password.component";
import { AccountSecurityComponent } from "../auth/popup/settings/account-security.component";
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
@@ -70,9 +70,6 @@ import { AboutPageV2Component } from "../tools/popup/settings/about-page/about-p
import { ExportBrowserV2Component } from "../tools/popup/settings/export/export-browser-v2.component";
import { ImportBrowserV2Component } from "../tools/popup/settings/import/import-browser-v2.component";
import { SettingsV2Component } from "../tools/popup/settings/settings-v2.component";
import { canAccessAtRiskPasswords } from "../vault/guards/at-risk-passwords.guard";
import { clearVaultStateGuard } from "../vault/guards/clear-vault-state.guard";
import { IntroCarouselGuard } from "../vault/guards/intro-carousel.guard";
import { AtRiskPasswordsComponent } from "../vault/popup/components/at-risk-passwords/at-risk-passwords.component";
import { AddEditV2Component } from "../vault/popup/components/vault-v2/add-edit/add-edit-v2.component";
import { AssignCollections } from "../vault/popup/components/vault-v2/assign-collections/assign-collections.component";
@@ -81,6 +78,9 @@ import { IntroCarouselComponent } from "../vault/popup/components/vault-v2/intro
import { PasswordHistoryV2Component } from "../vault/popup/components/vault-v2/vault-password-history-v2/vault-password-history-v2.component";
import { VaultV2Component } from "../vault/popup/components/vault-v2/vault-v2.component";
import { ViewV2Component } from "../vault/popup/components/vault-v2/view-v2/view-v2.component";
import { canAccessAtRiskPasswords } from "../vault/popup/guards/at-risk-passwords.guard";
import { clearVaultStateGuard } from "../vault/popup/guards/clear-vault-state.guard";
import { IntroCarouselGuard } from "../vault/popup/guards/intro-carousel.guard";
import { AppearanceV2Component } from "../vault/popup/settings/appearance-v2.component";
import { DownloadBitwardenComponent } from "../vault/popup/settings/download-bitwarden.component";
import { FoldersV2Component } from "../vault/popup/settings/folders-v2.component";

View File

@@ -1,9 +1,9 @@
import { inject } from "@angular/core";
import { CanDeactivateFn } from "@angular/router";
import { VaultV2Component } from "../popup/components/vault-v2/vault-v2.component";
import { VaultPopupItemsService } from "../popup/services/vault-popup-items.service";
import { VaultPopupListFiltersService } from "../popup/services/vault-popup-list-filters.service";
import { VaultV2Component } from "../components/vault-v2/vault-v2.component";
import { VaultPopupItemsService } from "../services/vault-popup-items.service";
import { VaultPopupListFiltersService } from "../services/vault-popup-list-filters.service";
/**
* Guard to clear the vault state (search and filter) when navigating away from the vault view.

View File

@@ -5,7 +5,7 @@ import { of } from "rxjs";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { IntroCarouselService } from "../popup/services/intro-carousel.service";
import { IntroCarouselService } from "../services/intro-carousel.service";
import { IntroCarouselGuard } from "./intro-carousel.guard";

View File

@@ -5,7 +5,7 @@ import { firstValueFrom } from "rxjs";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { IntroCarouselService } from "../popup/services/intro-carousel.service";
import { IntroCarouselService } from "../services/intro-carousel.service";
export const IntroCarouselGuard = async () => {
const router = inject(Router);

View File

@@ -8,6 +8,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { DialogService } from "@bitwarden/components";
import { PasswordRepromptService } from "@bitwarden/vault";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { SetPinComponent } from "./../../auth/popup/components/set-pin.component";
import { Fido2UserVerificationService } from "./fido2-user-verification.service";

View File

@@ -8,6 +8,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { DialogService } from "@bitwarden/components";
import { PasswordRepromptService } from "@bitwarden/vault";
// FIXME (PM-22628): Popup imports are forbidden in background
// eslint-disable-next-line no-restricted-imports
import { SetPinComponent } from "../../auth/popup/components/set-pin.component";
export class Fido2UserVerificationService {

View File

@@ -8,6 +8,7 @@ const TerserPlugin = require("terser-webpack-plugin");
const { TsconfigPathsPlugin } = require("tsconfig-paths-webpack-plugin");
const configurator = require("./config/config");
const manifest = require("./webpack/manifest");
const AngularCheckPlugin = require("./webpack/angular-check");
if (process.env.NODE_ENV == null) {
process.env.NODE_ENV = "development";
@@ -404,7 +405,7 @@ if (manifestVersion == 2) {
cache: true,
},
dependencies: ["main"],
plugins: [...requiredPlugins],
plugins: [...requiredPlugins /*new AngularCheckPlugin()*/], // TODO (PM-22630): Re-enable this plugin when angular is removed from the background script.
};
// Safari's desktop build process requires a background.html and vendor.js file to exist

21
apps/browser/webpack/angular-check.js vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* Webpack plugin that errors if it detects angular imports.
*/
class AngularCheckPlugin {
apply(compiler) {
compiler.hooks.assetEmitted.tap("AngularCheckPlugin", (file, info) => {
// Ensure we only check outputted JavaScript files
if (!file.endsWith(".js")) {
return;
}
if (info.content.includes("@angular")) {
throw new Error(
`Angular detected in ${file}. Please ensure angular is not imported to non popup scripts.`,
);
}
});
}
}
module.exports = AngularCheckPlugin;

View File

@@ -279,6 +279,31 @@ export default tseslint.config(
]),
},
},
// Browser background and content scripts are not allowed to import from the popup directory
{
files: ["apps/browser/src/**/*.ts"],
rules: {
"no-restricted-imports": buildNoRestrictedImports([
"@angular",
"bitwarden_license/**",
"@bitwarden/bit-common/*",
"@bitwarden/bit-web/*",
"**/popup/*",
]),
},
},
// This removes the previous rule forbidding imports from the popup directory
{
files: ["apps/browser/src/**/popup/**/*.ts"],
rules: {
"no-restricted-imports": buildNoRestrictedImports([
"bitwarden_license/**",
"@bitwarden/bit-common/*",
"@bitwarden/bit-web/*",
]),
},
},
{
files: ["libs/nx-plugin/**/*.ts", "libs/nx-plugin/**/*.js"],
rules: {