HashiCorp Vault — Response Wrapping
Response wrapping provides a secure one-time delivery mechanism for secrets using Vault’s cubbyhole response wrapping tokens.
The Problem
Without wrapping:
Admin reads secret → copies to Slack → developer uses it
⚠️ Secret visible in chat history forever
⚠️ Multiple people can see it
⚠️ No audit trail of who used it
With wrapping:
Admin wraps secret → shares one-time token → developer unwraps
✅ Token is single-use (destroyed after unwrap)
✅ TTL enforced (expires if unused)
✅ Tamper detection (admin can check if unwrapped)
How It Works
1. Admin requests a secret with -wrap-ttl
2. Vault stores the response in a cubbyhole
3. Vault returns a wrapping token (not the secret)
4. Admin shares the wrapping token
5. Recipient unwraps the token → gets the secret
6. Cubbyhole is destroyed (single-use)
Wrap a Secret
# Wrap a KV secret read
vault kv get -wrap-ttl=1h secret/myapp/db
# Returns:
# Key Value
# --- -----
# wrapping_token: hvs.CAES...
# wrapping_accessor: abc123
# wrapping_token_ttl: 1h
# wrapping_token_creation_time: 2024-01-15T10:30:00Z
# wrapping_token_creation_path: secret/data/myapp/db
# Wrap arbitrary data
vault write -wrap-ttl=30m sys/wrapping/wrap data="my-secret-data"
Unwrap
# Unwrap (anyone with the wrapping token can do this)
VAULT_TOKEN=hvs.CAES... vault unwrap
# Returns the original secret
# Or use the API
curl -s --header "X-Vault-Token: hvs.CAES..." \
--request POST \
"$VAULT_ADDR/v1/sys/wrapping/unwrap" | jq
# Second unwrap attempt:
VAULT_TOKEN=hvs.CAES... vault unwrap
# Error: wrapping token is not valid or does not exist
# ✅ Single-use enforced!
Lookup Wrapping Token
Check if a wrapping token has been used (tamper detection):
# Check wrapping token status (without unwrapping)
vault write sys/wrapping/lookup token=hvs.CAES...
# If successful: token is still valid (not yet unwrapped)
# If error: token was already unwrapped or expired
Rewrap
Transfer a wrapped secret to a new wrapping token (without exposing the secret):
vault write -wrap-ttl=1h sys/wrapping/rewrap token=hvs.OLD_TOKEN...
# Returns a new wrapping token, old one is invalidated
Use Cases
Secure Secret Distribution
# DevOps creates a database password and wraps it
vault kv get -wrap-ttl=2h secret/prod/db-master
# Share wrapping token via secure channel
# Developer unwraps when ready
Wrapped AppRole Secret ID
# Wrap the secret_id for secure delivery to a CI/CD pipeline
vault write -wrap-ttl=5m -f auth/approle/role/ci-cd/secret-id
# Share wrapping token as a CI variable
# Pipeline unwraps at runtime
Wrapped Initial Credentials
# New employee onboarding
vault write -wrap-ttl=24h sys/wrapping/wrap \
username=newuser \
temp_password=change-me-immediately
# Email the wrapping token — expires in 24h, single-use
API Examples
# Wrap via API
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
--header "X-Vault-Wrap-TTL: 3600" \
--request GET \
"$VAULT_ADDR/v1/secret/data/myapp/db" | jq '.wrap_info'
# Unwrap via API
curl -s --header "X-Vault-Token: hvs.WRAPPING_TOKEN" \
--request POST \
"$VAULT_ADDR/v1/sys/wrapping/unwrap" | jq
Quick Reference
| Command | Description |
|---|---|
vault kv get -wrap-ttl=1h secret/path |
Wrap a secret read |
vault unwrap |
Unwrap (uses VAULT_TOKEN) |
vault write sys/wrapping/lookup token=TOKEN |
Check token status |
vault write sys/wrapping/rewrap token=TOKEN |
Rewrap to new token |
Next: Identity Engine