Open-Source Wikis

/

Vault

/

Security

hashicorp/vault

Security

Vault's whole job is to be a security-critical service, so this page is necessarily short on novel content. The threat model is well-documented upstream at https://developer.hashicorp.com/vault/docs/internals/security. This page focuses on the contributor-relevant points: where the trust boundaries are, where the cryptography lives, and what the codebase's hardening posture looks like.

Reporting a vulnerability

If you believe you have found a security issue in Vault, please responsibly disclose by contacting us at security@hashicorp.com.

That line is at the top of README.md and CONTRIBUTING.md for a reason. Do not file a public issue for a security bug.

Trust boundaries

graph LR
    subgraph "Untrusted"
        Client[API client]
    end
    subgraph "Vault process"
        TLS[TLS listener]
        H[http/handler.go]
        Core[Core]
        Backends[Auth methods + secret engines]
        Plugins[(External plugin processes<br/>each its own boundary)]
    end
    subgraph "Trusted (operator)"
        Cfg[Config file]
        SealHardware[Local KMS / HSM]
    end
    subgraph "External"
        KMS[Cloud KMS]
        DBs[Backed services<br/>databases, AWS, ...]
    end
    Client -->|TLS + token| TLS --> H --> Core
    Core --> Backends
    Backends --> Plugins
    Backends -->|dynamic creds| DBs
    Core -->|wrap keyring| KMS
    Cfg --> Core
    SealHardware -. seal options .-> Core
  • The HTTP boundary is the only network-untrusted entry point Vault exposes.
  • Plugin processes are less trusted than Core. They can't read storage outside their own view.
  • External KMS / database services are downstream — Vault talks out to them with credentials it manages.

Cryptographic primitives

Primitive Where Used for
AES-256-GCM vault/barrier_aes_gcm.go The encryption barrier between Core and storage. Every byte at rest is wrapped here.
Shamir secret sharing shamir/shamir.go Splitting the master key into N shares with a threshold.
HMAC-SHA-256 audit/hashstructure.go, helper/salt/ Pseudonymizing audit fields and per-mount salts.
Per-key wrappers sdk/helper/keysutil/ Transit's symmetric and asymmetric key flavors.
Cloud KMS / HSM wrappers github.com/hashicorp/go-kms-wrapping/v2 Auto-unseal.
TLS 1.2 / 1.3 internalshared/listenerutil/ Listener termination, configurable cipher suites.
Random crypto/rand everywhere Salt, key, ID generation.

Anything that handles secret material defers to the upstream crypto packages; we don't roll our own primitives.

Secrets in memory

Master key shares are erased from memory after combination. The keyring is held while unsealed but never written to logs. helper/mlock/ calls mlock on Linux to prevent paging the keyring to swap.

Authorization layers

Every request goes through:

  1. Authentication: token validity (token store).
  2. Identity resolution: token → entity → groups (identity store).
  3. Policy evaluation: ACL capabilities at the path.
  4. Login MFA: factors required for login.
  5. Sentinel (Enterprise): policy programs evaluated against the request.
  6. Control groups (Enterprise): multi-party authorization.
  7. Quotas: rate and lease-count limits.
  8. Audit pre-call: log the intent.

Skipping any step is a security regression. The order is enforced in vault/request_handling.go.

Audit guarantees

If at least one audit device is configured and any of them fails, Vault refuses the request. This is intentional: a missed audit log is treated as a security incident.

Plugin sandbox

External plugins are subprocesses with their own filesystem and network access. The runtime catalog (vault/plugincatalog/plugin_runtime_catalog.go) lets operators run them in containers with dropped privileges. Plugins talk to Vault only through the gRPC logical.Backend protocol — they cannot inject paths or bypass the router.

Hardening switches

Switch Effect
disable_mlock=false (default true on Linux) Lock memory to prevent paging.
disable_clustering=true Disable HA listeners. Useful for single-node test deployments.
disable_indexing=true Skip the index header used for read-after-write.
enable_response_header_hostname / enable_response_header_raft_node_id Add diagnostic headers to responses; off by default.
disable_printable_check, disable_sealwrap Diagnostic toggles; rarely used.
enable_debug_endpoints Expose pprof. Off by default.

Static analysis

Workflows under .github/workflows/ run several scanners on every PR:

  • code-checker.yml — internal lint plugin (under tools/codechecker/).
  • security-scan.yml — HashiCorp security-scanner (gosec, govulncheck, …) configured by scan.hcl.
  • mend-pr-scan.yml — Mend (license + vulnerability).

Past advisories

A running list of disclosed advisories is at https://discuss.hashicorp.com/c/security and reflected in CHANGELOG*.md files under release-note:security entries. When auditing a release, grep the relevant CHANGELOG for security to find historical fixes.

What's intentionally not in OSS

  • Sentinel policy engine (Enterprise): full programmable policy.
  • Control groups (Enterprise): multi-party authorization.
  • PKCS#11 seal type (Enterprise): HSM-backed auto-unseal.
  • Multi-namespace nesting (Enterprise): full nested namespace tree.
  • Performance / DR replication (Enterprise).

The OSS tree carries the seams (_ce.go / _oss.go stubs) so Enterprise can drop in real implementations. Removing those seams breaks the Enterprise build.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – Vault wiki | Factory