1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 21:50:15 +00:00

WIP: generate SPA checksum to validate web page

This commit is contained in:
Matt Gibson
2025-02-04 12:38:40 -08:00
parent 0b17d9e74d
commit 7a40ca1b26
3 changed files with 62 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
export class ScriptSignature {
constructor(private readonly cryptoFunctionService: CryptoFunctionService) {}
}

View File

@@ -5,6 +5,7 @@ import { firstValueFrom } from "rxjs";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@@ -22,6 +23,7 @@ export class UpdateBadge {
private authService: AuthService;
private badgeSettingsService: BadgeSettingsServiceAbstraction;
private cipherService: CipherService;
private environmentService: EnvironmentService;
private badgeAction: typeof chrome.action | typeof chrome.browserAction;
private sidebarAction: OperaSidebarAction | FirefoxSidebarAction;
private win: Window & typeof globalThis;
@@ -31,6 +33,7 @@ export class UpdateBadge {
this.sidebarAction = BrowserApi.getSidebarAction(self);
this.win = win;
this.environmentService = services.environmentService;
this.badgeSettingsService = services.badgeSettingsService;
this.authService = services.authService;
this.cipherService = services.cipherService;
@@ -38,9 +41,19 @@ export class UpdateBadge {
async run(opts?: { tabId?: number; windowId?: number }): Promise<void> {
const authStatus = await this.authService.getAuthStatus();
const environment = await firstValueFrom(this.environmentService.cloudWebVaultUrl$);
await this.setBadgeBackgroundColor();
const tab = await this.getTab(opts?.tabId, opts?.windowId);
await this.setAuthStatusBadge(authStatus, tab);
if (tab?.url?.startsWith(environment)) {
await this.setValidWebVaultBadge(authStatus, tab);
return;
}
}
async setAuthStatusBadge(authStatus: AuthenticationStatus, tab: chrome.tabs.Tab) {
switch (authStatus) {
case AuthenticationStatus.LoggedOut: {
await this.setLoggedOut();
@@ -51,13 +64,21 @@ export class UpdateBadge {
break;
}
case AuthenticationStatus.Unlocked: {
const tab = await this.getTab(opts?.tabId, opts?.windowId);
await this.setUnlocked({ tab, windowId: tab?.windowId });
break;
}
}
}
async setValidWebVaultBadge(authStatus: AuthenticationStatus, tab: chrome.tabs.Tab) {
if (authStatus === AuthenticationStatus.Unlocked) {
await this.setUnlocked({ tab, windowId: tab?.windowId });
} else {
await this.setBadgeIcon("_gray", tab.windowId);
await this.clearBadgeText();
}
}
async setLoggedOut(): Promise<void> {
await this.setBadgeIcon("_gray");
await this.clearBadgeText();

View File

@@ -0,0 +1,35 @@
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
// Path to the built index.html file. The expectation is that this file contains <script> tags to generate checksums for.
const indexFile = process.argv.slice(2);
const indexFileDir = path.dirname(indexFile[0]);
// Read the index.html file.
const index = fs.readFileSync(indexFile[0], "utf8");
// Extract all the script tags.
// captures the src tag in the `src` group and any inline script in the `inline` group.
const scripts = index.matchAll(
/<script[^>]*?(?:src=(["\'])(?<src>(?:[\s\S](?!\1|>))*[\s\S]?)\1)?>(?<inline>[\s\S]*?)<\/script>/gm,
);
const checksums = {
inline: [],
};
for (const match of scripts) {
const src = match.groups.src;
const inline = match.groups.inline;
if (src) {
const file = src;
const fileContent = fs.readFileSync(path.join(indexFileDir, file), "utf8");
checksums[file] = crypto.createHash("sha256").update(fileContent).digest("hex");
}
if (inline) {
checksums.inline.push(crypto.createHash("sha256").update(inline).digest("hex"));
}
}
console.log(JSON.stringify(checksums, null, 2));