The vault-secrets-webhook reads the vault.security.banzaicloud.io/vault-addr annotation from any ConfigMap or Secret being admitted and uses it as the Vault server address without any validation or allowlist. When a ConfigMap or Secret contains a value prefixed with vault:, the webhook's admission handler synchronously calls the Vault API at the attacker-supplied address from inside the webhook process during the admission review. The webhook additionally grants serviceaccounts/token:create cluster-wide, and the vault-serviceaccount annotation controls which ServiceAccount's JWT is fetched and sent to that address. An attacker who can create ConfigMaps or Secrets in a watched namespace can cause the webhook process to make arbitrary outbound HTTP connections and exfiltrate ServiceAccount JWTs.
parseVaultConfig() at pkg/webhook/config.go:102-107 reads VaultAddrAnnotation unconditionally into vaultConfig.Addr:
if value, ok := annotations[common.VaultAddrAnnotation]; ok {
vaultConfig.Addr = value
}
No URL scheme validation, no hostname allowlist, no RFC-1918 or link-local filter.
MutateConfigMap and MutateSecret at pkg/webhook/configmap.go and pkg/webhook/secret.go call mw.newVaultClient(ctx, vaultConfig) when the object contains at least one vault:... value. Inside newVaultClient, at pkg/webhook/webhook.go:285:
clientConfig.Address = vaultConfig.Addr
vault.NewClientFromConfigWithContext then opens an HTTP connection to the attacker-controlled address from the webhook server process, synchronously during the admission review. This is not deferred to a separate pod.
The vault-skip-verify annotation (pkg/webhook/config.go:197) sets InsecureSkipVerify: true on the TLS config, eliminating the need for a valid certificate on the attacker's server.
When VaultServiceaccountAnnotation is also set, at pkg/webhook/webhook.go:
1.23.1Exploitability
AV:NAC:LPR:LUI:NScope
S:CImpact
C:HI:HA:N9.6/CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:NInput Validation