Skip to main content

Architecture Overview

This document describes the high-level architecture of secretctl, including component relationships, data flows, and security boundaries.

System Components

┌─────────────────────────────────────────────────────────────────────────────┐
│ secretctl Architecture │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ CLI │ │ Desktop │ │ MCP Server │ User Interfaces │
│ │ (Cobra) │ │ (Wails) │ │ (stdio) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ │ Full Trust │ Full Trust │ Restricted (AI-Safe Access)│
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ Vault Core (pkg/vault) │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Manager │ │ Secrets │ │ Audit │ │ Policy │ │ │
│ │ │ │──│ Store │──│ Log │ │ Engine │ │ │
│ │ │ (lifecycle) │ │ (CRUD) │ │ (HMAC) │ │ (MCP only) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ Crypto Layer (pkg/crypto) │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Argon2id │ │ AES-256 │ │ HMAC-256 │ │ │
│ │ │ (KDF) │ │ (GCM) │ │ (Chain) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ Storage Layer (SQLite) │ │
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
│ │ │ vault.db (0600) │ vault.salt (0600) │ vault.meta (0600) │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Component Responsibilities

ComponentResponsibilityPackage
CLICommand-line interface, user interactioncmd/secretctl
DesktopNative GUI applicationdesktop/
MCP ServerAI agent integration, AI-Safe Access enforcementinternal/mcp
Vault ManagerLifecycle (init, lock, unlock), session managementpkg/vault
Secrets StoreCRUD operations, metadata handlingpkg/vault
Audit LogHMAC-chained event logging, integrity verificationpkg/vault
Policy EngineMCP command allowlist, deny-by-defaultinternal/mcp
Crypto LayerKey derivation, encryption, HMACpkg/crypto
Storage LayerSQLite persistence, file permissionspkg/vault

Data Flow Diagrams

Secret Set Operation

User                    CLI                     Vault                   Crypto
│ │ │ │
│ set KEY (stdin) │ │ │
│─────────────────────▶│ │ │
│ │ Store(key, value) │ │
│ │───────────────────────▶│ │
│ │ │ Encrypt(DEK, value) │
│ │ │──────────────────────▶│
│ │ │ │
│ │ │◀──────────────────────│
│ │ │ ciphertext │
│ │ │ │
│ │ │ INSERT INTO secrets │
│ │ │──────────▶ [SQLite] │
│ │ │ │
│ │ │ Log(SET, key_hash) │
│ │ │──────────▶ [Audit] │
│ │◀───────────────────────│ │
│◀─────────────────────│ success │ │
│ OK │ │ │

MCP secret_run Operation (AI-Safe Access)

AI Agent            MCP Server              Vault              Subprocess
│ │ │ │
│ secret_run │ │ │
│ (keys, cmd) │ │ │
│──────────────────▶│ │ │
│ │ │ │
│ │ ValidatePolicy(cmd)│ │
│ │────────────────────▶│ │
│ │◀────────────────────│ │
│ │ allowed │ │
│ │ │ │
│ │ GetSecrets(keys) │ │
│ │────────────────────▶│ │
│ │◀────────────────────│ │
│ │ values │ │
│ │ │ │
│ │ Exec(cmd, env=secrets) │
│ │─────────────────────────────────────────▶│
│ │ │
│ │◀─────────────────────────────────────────│
│ │ stdout, stderr │
│ │ │ │
│ │ Sanitize(output, secrets) │
│ │ [REDACTED] replacement │
│ │ │ │
│◀──────────────────│ │ │
│ sanitized output │ │ │
│ (NO plaintext) │ │ │

Threat Model

Trust Boundaries

┌─────────────────────────────────────────────────────────────────────────────┐
│ Trust Boundary 1 │
│ (User's Local Environment) │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ TRUSTED ACTORS TRUSTED OPERATIONS │ │
│ │ ────────────── ────────────────── │ │
│ │ • Human user (CLI) • Read plaintext secrets │ │
│ │ • Human user (Desktop) • Write/modify secrets │ │
│ │ • Delete secrets │ │
│ │ • Export vault │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ AI-Safe Access Boundary │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ RESTRICTED ACTORS RESTRICTED OPERATIONS │ │
│ │ ───────────────── ───────────────────── │ │
│ │ • AI agents (MCP) • List key names (no values) │ │
│ │ • Automated tools • Check existence │ │
│ │ • Get masked values │ │
│ │ • Run commands (allowlisted) │ │
│ │ │ │
│ │ DENIED OPERATIONS │ │
│ │ ───────────────── │ │
│ │ ✗ Read plaintext secrets │ │
│ │ ✗ Write/modify secrets │ │
│ │ ✗ Delete secrets │ │
│ │ ✗ Export vault │ │
│ │ ✗ Run blocked commands (env, printenv, etc.) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Threat Categories and Mitigations

CategoryThreatMitigationImplementation
T1: Secret ExposureAI extracts plaintextNo secret_get toolinternal/mcp
T2: Output LeakageCommand output contains secretsOutput sanitizationpkg/vault/sanitizer.go
T3: Prompt InjectionMalicious prompt requests dataTool-level restrictionsMCP tool definitions
T4: Command InjectionInjected shell commandsCommand allowlistmcp-policy.yaml
T5: Env Dumpenv/printenv reveals secretsBlocked commands listinternal/mcp/policy.go
T6: Brute ForceMaster password guessingArgon2id (memory-hard)pkg/crypto
T7: Data at RestDisk access to vaultAES-256-GCM encryptionpkg/crypto
T8: Log TamperingAudit log modificationHMAC chain integritypkg/vault/audit.go
T9: File PermissionUnauthorized file access0600/0700 permissionspkg/vault

STRIDE Analysis

Threat TypeApplicableMitigation
SpoofingNoLocal-only, no network auth
TamperingYesHMAC chain audit logs, encrypted storage
RepudiationYesAudit logging with timestamps
Information DisclosureYesAI-Safe Access, output sanitization
Denial of ServiceLimitedTimeout on commands (300s)
Elevation of PrivilegeYesTrust boundary enforcement

Key Hierarchy

┌─────────────────────────────────────────────────────────────────────────────┐
│ Key Hierarchy │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ User Input: Master Password │
│ │ │
│ │ + Salt (128-bit, random) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Argon2id │ │
│ │ ───────── │ │
│ │ Memory: 64 MiB │ │
│ │ Time: 3 iterations │ │
│ │ Threads: 4 │ │
│ │ Output: 256 bits │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Master Key (256-bit) ──────── NEVER STORED ──────── │
│ │ │
│ │ HKDF-SHA256 ("dek-v1") │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ DEK (Data Encryption Key) - 256-bit │ │
│ │ ───────────────────────────────────── │ │
│ │ • Stored encrypted in vault.db │ │
│ │ • Allows password rotation without re-encrypting all secrets │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ AES-256-GCM │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Encrypted Secrets │ │
│ │ ───────────────── │ │
│ │ • Each secret encrypted with unique nonce │ │
│ │ • Stored as: nonce (12B) || ciphertext || auth_tag (16B) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Audit Log Key (256-bit) │
│ ──────────────────────── │
│ • Derived from Master Key via HKDF-SHA256 ("audit-log-v1") │
│ • Used for HMAC chain computation │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Database Schema

-- Secrets table
CREATE TABLE secrets (
id TEXT PRIMARY KEY,
key TEXT UNIQUE NOT NULL,
encrypted_value BLOB NOT NULL,
notes TEXT,
url TEXT,
tags TEXT, -- JSON array
expires_at DATETIME,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);

-- Audit log table
CREATE TABLE audit_log (
id TEXT PRIMARY KEY,
action TEXT NOT NULL, -- get, set, delete, list, run
key_hash TEXT, -- SHA-256 of key (not plaintext)
source TEXT NOT NULL, -- cli, mcp, ui
success BOOLEAN NOT NULL,
error_msg TEXT,
timestamp DATETIME NOT NULL,
prev_hash TEXT, -- HMAC chain
hash TEXT NOT NULL -- HMAC of this record
);

-- Metadata table
CREATE TABLE metadata (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);

File Structure

~/.secretctl/
├── vault.db # SQLite database (encrypted values)
│ # Permission: 0600

├── vault.salt # Argon2id salt (128 bits)
│ # Permission: 0600

├── vault.meta # Vault metadata (JSON)
│ # Permission: 0600
│ # Contains: version, created_at

└── mcp-policy.yaml # MCP command policy (optional)
# Permission: 0600
# Validated: No symlinks allowed

Security Boundaries Summary

InterfaceTrust LevelCan Read PlaintextCan ModifyCan Delete
CLIFullYesYesYes
DesktopFullYesYesYes
MCPRestrictedNoNoNo

Next Steps