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:
- Authentication: token validity (token store).
- Identity resolution: token → entity → groups (identity store).
- Policy evaluation: ACL capabilities at the path.
- Login MFA: factors required for login.
- Sentinel (Enterprise): policy programs evaluated against the request.
- Control groups (Enterprise): multi-party authorization.
- Quotas: rate and lease-count limits.
- 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 (undertools/codechecker/).security-scan.yml— HashiCorp security-scanner (gosec, govulncheck, …) configured byscan.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.