Skip to main content

Blind Data Vault — privilege-separated secret vault for AI agents

Project description

BDV (Blind Data Vault)

A privilege-separated, encrypted secret vault that lets AI agents verify, send, and act on sensitive data without ever seeing it.

The daemon runs in a Docker container. The AI agent talks to it via Unix socket or TCP. Even if the agent is fully compromised, it cannot decrypt secrets as the privilege boundary is at the OS/container level.

pip install bdv      # client only
docker compose up -d # full daemon

For the paradigm rationale, see WHITEPAPER.md. For design decisions, see ARCHITECTURE.md.

Quick Start

Docker

docker compose up -d
docker exec bdv bdv list
docker exec bdv bdv write ssn --value "123-45-6789" --type numeric --desc "US SSN"
docker exec bdv bdv check ssn /data/inbox/form.pdf

pip

The client connects to a running BDV daemon. Start the daemon first (via Docker or manual setup), then:

pip install bdv
bdv list
bdv write ssn --value "123-45-6789" --type numeric --desc "US SSN"

TCP

# Daemon: BDV_SERVER_TCP_ENABLED=true BDV_SERVER_TCP_TOKEN=mytoken
bdv --tcp localhost:9652 --token mytoken list

What It Does

The agent sends commands. The daemon handles all crypto, file reading, and pattern matching internally. The agent only receives redacted results.

Command Parameters What the agent gets back
list Secret names + descriptions (never values)
check_document secret name, file path MATCH/NO MATCH with redacted context
send template, subject "Sent. 2 secrets injected." (never the content)
write name, value, type "Encrypted and stored."
delete name "Deleted."
describe name, description "Updated."

Secret Types

Type What it does Examples
numeric Pattern-based sweep with anomaly report SSN, routing numbers, credit cards
exact Case-sensitive exact match Email addresses, API keys
text Case-insensitive with component decomposition Names, addresses

Namespaced Secrets

Store multiple values under a single name using colon syntax:

bdv write email:personal --value "me@gmail.com" --type exact --desc "Personal"
bdv write email:work --value "me@corp.com" --type exact --desc "Corporate"

# Check all values at once
bdv check email /data/inbox/form.pdf
# RESULT: Checked 2 values under 'email'. 1 found, 1 not found.

# Or a specific label
bdv check email:work /data/inbox/form.pdf

# Delete one label or the entire group
bdv delete email:work    # one label
bdv delete email         # all values

Flat secrets (no colon) work exactly as before.

Supported Document Formats

PDF (text + scanned via OCR), images (Tesseract), plain text (txt/md/csv/json/xml).

Python Client

from client import BDVClient

# Unix socket (default: /run/bdv/bdv.sock)
client = BDVClient()

# Or TCP
client = BDVClient(host="localhost", port=9652, token="...")

client.list()
client.write("ssn", "123-45-6789", description="US SSN", secret_type="numeric")
client.check_document("ssn", "/data/inbox/form.pdf")
client.send(template="Your SSN is {{VAULT:ssn}}.", subject="Details")
client.delete("ssn")
client.describe("ssn", "Updated description")

Configuration

Three layers: defaultsYAMLenv vars (env wins).

cp bdv.example.yml bdv.yml  # see all options
Variable Default Description
BDV_CONFIG Path to YAML config file
BDV_SERVER_SOCKET_PATH /run/bdv/bdv.sock Unix socket path
BDV_SERVER_TCP_ENABLED false Enable TCP listener
BDV_SERVER_TCP_HOST 127.0.0.1 TCP listen address
BDV_SERVER_TCP_PORT 9652 TCP port
BDV_SERVER_TCP_TOKEN Required auth token for TCP
BDV_STORAGE_VAULT_DIR /data/secrets Encrypted secret storage
BDV_STORAGE_INBOX_DIR /data/inbox Write-only document inbox
BDV_STORAGE_OUTBOX_DIR /data/outbox Output directory (file channel)
BDV_OUTPUT_TYPE file Output channel: file, smtp, webhook
BDV_PLUGINS_DIR /plugins Directory for plugin .py files
BDV_SOCKET Client-side override for the socket path (alternative to --socket)
BDV_TOKEN Client-side override for the TCP auth token (alternative to --token)

Extensibility

Custom commands

New agent-invocable actions can be added as plugins. Drop a .py file into the plugins directory and mount it as a volume. No fork or rebuild needed.

# docker-compose.yml
volumes:
  - ./plugins:/plugins:ro

Each plugin defines a COMMANDS dict mapping command names to handlers:

# plugins/fill_form.py
from daemon.crypto import decrypt
from daemon.config import BDVConfig
from daemon.channels.base import OutputChannel
from pathlib import Path

def cmd_fill_form(params, config, channel):
    vault_dir = Path(config.storage.vault_dir)
    key_file = vault_dir / ".vault-key"
    secret = decrypt(params["name"], vault_dir, key_file).strip()
    # ... fill the form, write to outbox ...
    return "Form filled. 3 fields populated. Output written to outbox."

COMMANDS = {"fill_form": cmd_fill_form}

The daemon loads plugins on startup. Built-in commands cannot be overridden.

Custom output channels

New delivery mechanisms for the send command work the same way. Subclass OutputChannel and export a CHANNELS dict:

# plugins/s3_channel.py
from daemon.channels.base import OutputChannel

class S3Channel(OutputChannel):
    def __init__(self, config):
        self.bucket = "my-vault-output"

    def send(self, body, subject, *, original_message_id=""):
        # ... upload to S3 ...
        return f"Uploaded to s3://{self.bucket}/..."

CHANNELS = {"s3": S3Channel}

Then set BDV_OUTPUT_TYPE=s3 to use it. Built-in channels (file, smtp, webhook) cannot be overridden.

Available imports for plugins

Plugins run inside the daemon process, so all daemon.* modules are available. For local development outside the container, pip install bdv[daemon] makes these importable.

Import What it provides
daemon.crypto.decrypt(name, vault_dir, key_file) Decrypt a secret by name
daemon.crypto.encrypt(name, value, vault_dir, key_file) Encrypt and store a secret
daemon.crypto.secret_path(name, vault_dir) Resolve a name to its .age file path
daemon.document.extract_text(file_path) Extract text from PDF, image, or text file
daemon.patterns.derive_patterns(name, secret) Auto-derive regex from a secret value
daemon.patterns.build_context_window(...) Build a redacted context window around a match
daemon.patterns.normalize_secret(secret) Strip delimiters from a secret for comparison
daemon.config.BDVConfig Config dataclass (passed as config param)
daemon.channels.base.OutputChannel Base class for output channels (passed as channel param)

Every handler receives (params: dict, config: BDVConfig, channel: OutputChannel) and returns a str. The return value is sent back to the agent, so it must never contain plaintext secrets.

Security Model

Threat Mitigation
Prompt injection exfiltrates secrets Agent can't decrypt (wrong container/user)
Agent runs cat on vault files Permission denied (OS-level)
Malicious regex (ReDoS) Patterns derived from trusted vault data only
Secrets leak into logs/memory/vector DB Values never enter agent context
Adjacent PII in context windows Aggressive redaction of 3+ digit sequences

See WHITEPAPER.md for the paradigm rationale and FAQ.

Security Disclaimer

BDV protects secrets from the AI agent. It is not a general-purpose secrets management solution.

What it does NOT cover:

  • Physical server security. Anyone with root/physical/disk access to the host can extract the private key. If you run on a VPS, your hosting provider has theoretical disk access.
  • Transport security. The daemon protects secrets from the LLM, not during delivery to the end user. Use TLS, VPN (Tailscale/WireGuard), or PGP encryption for transport.
  • Backup security. If your backup system captures the vault directory in plaintext, the secrets are exposed. Encrypt backups independently.
  • Memory forensics. During active decryption (a few milliseconds per operation), the plaintext exists in the daemon's process memory.

Recommendation: Run BDV on a dedicated machine (not a shared VPS) behind a VPN mesh like Tailscale, with full-disk encryption (LUKS) enabled.

Requirements

Docker (recommended): All dependencies included in the image.

Manual: Python 3.10+, age, pdfplumber, pytesseract + tesseract-ocr, pdf2image + poppler-utils.

Client only: Python 3.10+, click (pip install bdv).

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bdv-0.2.0.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bdv-0.2.0-py3-none-any.whl (29.5 kB view details)

Uploaded Python 3

File details

Details for the file bdv-0.2.0.tar.gz.

File metadata

  • Download URL: bdv-0.2.0.tar.gz
  • Upload date:
  • Size: 34.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bdv-0.2.0.tar.gz
Algorithm Hash digest
SHA256 777e49c5735618aed43a258586b3b110a083091036c8c72e9646bc74d56ea862
MD5 1164ff2c6b1512cd7b9fb1d102885d34
BLAKE2b-256 c804432ea8c070d8a7276206c6bc4041ea9fd27b72dbf01f16e5fad8a0c23dad

See more details on using hashes here.

Provenance

The following attestation bundles were made for bdv-0.2.0.tar.gz:

Publisher: release.yml on calvinsienatra/bdv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bdv-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: bdv-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 29.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bdv-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a4d799d064f4e145159930e73e438818df6abad8c47fde7cce2044a3ae2db68f
MD5 9c3effcce4e488e60528cd067ffcbdae
BLAKE2b-256 f36fe2592eb260e91f377c2fc3af9290bce6d68da0e1e66ca2b13ac40bb391d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bdv-0.2.0-py3-none-any.whl:

Publisher: release.yml on calvinsienatra/bdv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page