HashiCorp Vault — Response Wrapping

2 minute read

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