TazPod Vault Security

TazPod’s real security boundary is the vault lifecycle, not the Docker container by itself. The container is only the shell. The vault determines when sensitive material exists and where.

Canonical Paths

From internal/vault/vault.go:

  • VaultDir = /workspace/.tazpod/vault
  • VaultFile = /workspace/.tazpod/vault/vault.tar.aes
  • MountPath = /home/tazpod/secrets
  • AwsLocalHome = /home/tazpod/.aws
  • AwsVaultDir = /home/tazpod/secrets/.aws
  • PassCache = /home/tazpod/secrets/.vault_pass

These are the real operational paths. If another document says otherwise, it is stale.

Encryption Model

The cryptographic engine is implemented in internal/crypto/crypto.go.

Verified properties:

  • algorithm: AES-256-GCM
  • salt size: 32 bytes
  • nonce size: 12 bytes
  • key derivation: PBKDF2 with SHA-256
  • iterations: 100000
  • output format: [salt][nonce][ciphertext]

vault.tar.aes is therefore not a loopback disk image or a LUKS volume. It is a tar.gz byte stream encrypted at the application layer.

Unlock Flow

vault.Unlock() does the following:

  1. if /home/tazpod/secrets is already mounted, it reuses cached passphrase and reruns identity setup
  2. otherwise it mounts a 64 MB tmpfs
  3. if vault.tar.aes exists, it reads and decrypts it
  4. the decrypted tar.gz is extracted into the RAM mount
  5. the passphrase is cached into .vault_pass inside the RAM mount
  6. SetupIdentity() ensures persistent agent config directories exist under /workspace/.tazpod/
  7. setupBindAuth() bind-mounts .aws from the RAM mount into the standard home path

The practical implication is simple: secrets are only available after explicit unlock, and they only exist in RAM while unlocked.

Lock Flow

vault.Lock():

  1. unmounts /home/tazpod/.aws
  2. unmounts /home/tazpod/secrets

Because the secret mount is tmpfs, unmounting it is the real destruction boundary for runtime secrets.

AWS Enclave Bridge

The AWS bridge is explicit and minimal:

  • source: /home/tazpod/secrets/.aws
  • target: /home/tazpod/.aws
  • method: mount --bind

This allows standard tooling (aws, SDKs, S3 helpers) to work without knowing anything about TazPod internals while keeping credentials inside the RAM enclave.

Identity Side Effects

SetupIdentity() creates these directories under /workspace/.tazpod/:

  • .pi
  • .omp
  • .gemini
  • .claude
  • .aws
  • .opencode

This matters because not all operator state is secret state. TazPod separates encrypted vault material from persistent tool state that must survive container recreation.

See Also