Consul 1.21.5 breaks existing keyvault entries with illegal key name
Overview of the Issue
https://github.com/hashicorp/consul/pull/22682 is a major breaking change but was released in a patch release.
It silently breaks kv operations for existing kv entries with a (now) illegal key name.
This is going to impact anyone who has used uuencode / url encode / percent-encoding to mask the / character in their consul keys as part of their hierarchical organization of their consul kv, which I expect to be many people.
Reproduction Steps
- Have an existing consul cluster with version < 1.21.5 with key names such as (from
consul kv export):
[
{
"key": "foo/bar/baz%2Fqux",
"flags": 0,
"value": "XXXXXXX"
}
]
- Observe that
consul kv get 'foo/bar/baz%2Fqux'works - Upgrade consul to 1.21.5
- Observe that
consul kv get 'foo/bar/baz%2Fqux'no longer works
consul kv export still works, but consul kv import does not.
Consul info for both Client and Server
[root ~] [1] # consul info
agent:
check_monitors = 0
check_ttls = 0
checks = 2
services = 40
build:
prerelease =
revision = 3261d11a
version = 1.21.5
version_metadata =
consul:
acl = disabled
bootstrap = true
known_datacenters = 1
leader = true
leader_addr = 10.37.129.192:8300
server = true
raft:
applied_index = 182221
commit_index = 182221
fsm_pending = 0
last_contact = 0
last_log_index = 182221
last_log_term = 4
last_snapshot_index = 180239
last_snapshot_term = 3
latest_configuration = [{Suffrage:Voter ID:8206222e-a5c1-185e-0e54-a6039138008e Address:10.37.129.192:8300}]
latest_configuration_index = 0
num_peers = 0
protocol_version = 3
protocol_version_max = 3
protocol_version_min = 0
snapshot_version_max = 1
snapshot_version_min = 0
state = Leader
term = 4
runtime:
arch = amd64
cpu_count = 4
goroutines = 352
max_procs = 2
os = linux
version = go1.25.0
serf_lan:
coordinate_resets = 0
encrypted = false
event_queue = 1
event_time = 301
failed = 0
health_score = 0
intent_queue = 1
left = 0
member_time = 6
members = 1
query_queue = 0
query_time = 1
serf_wan:
coordinate_resets = 0
encrypted = false
event_queue = 0
event_time = 1
failed = 0
health_score = 0
intent_queue = 0
left = 0
member_time = 3
members = 1
query_queue = 0
query_time = 1
Operating system and Environment details
Debian
Log Fragments
2025-09-24T02:46:34.700732-04:00 some-server-hostname consul[2573172]: agent.http: Request error: method=GET url="/v1/kv/foo/bar/baz%252Fqux?stale=1" from=127.0.0.1:45122 error="invalid key name, keys should respect the \"^[a-zA-Z0-9,_./\\-?&=]+$\" format"
Hi,
this change breaks existing Terraform states stored in Consul. After upgrading Consul to 1.21.5, terraform init fails with:
# terraform init
Initializing the backend...
Initializing modules...
╷
│ Error: Failed to get existing workspaces: Unexpected response code: 500 (invalid key name, keys should respect the "^[a-zA-Z0-9,_./\\-?&=]+$" format)
│
│
╵
Environment:
terraform --version
Terraform v1.13.3
on darwin_arm64
+ provider registry.terraform.io/hashicorp/vault v5.1.0
+ provider registry.terraform.io/tchupp/env v0.0.2
+ provider registry.terraform.io/terraform-provider-openstack/openstack v3.3.2
Cheers, Marius
It also breaks Vault Consul storage:
/v1/kv/vault/core/plugin-catalog/database/kv/v0.24.0+builtin contains the + symbol, which isn't allowed by the regex.
It looks like this new check can be disabled via disable_http_unprintable_char_filter.
Have you tried setting this to true in your agent config?
Hey folks, sorry to hear that this change broke some integrations. It was a sanitization we've added to prevent potential path traversals in our key names in the kv endpoint following an external security assessment. The disable_http_unprintable_char_filter should indeed disable it and feel free to use it if your key names are well sanitized. We'll adjust the kv regex in the next Consul version to include + , *, ? and %. Please feel free to @ me here if you have another character that causes an issue and isn't capturer in here. Thanks a lot for reporting this, we'll get a fix as soon as possible.
@dduzgun-security Are those extra characters going to be enough to fix the issues with Traefik, which uses a hard-coded key with the ç character in as part of their healthchecks?
Also, it would probably be worth updating the documentation which currently says "Keys, like objects, are not restricted by type and can include any character", as that's no longer correct.
@uduncanu Good catch, I suggested it in the PR: https://github.com/hashicorp/consul/pull/22850
Hi @dduzgun-security,
I want to suggest also the colon ":" character which is used in consul esm!
Consul ESM is writing its key always with the keyname with "${CONSUL_SERVICE_NAME}:${CONSUL_INSTANCE_ID}"!
Not sure if anyone else would like to chime in on the PR improving this KV validation feature
https://github.com/hashicorp/consul/pull/22863
I'm seeing the same issue with Orleans and Consul as membership provider. Keys are of the form orleans/Staging/192.168.147.66:11111@122992601 (note the : and @)
@ahilsend do you have the same behaviour on Consul 1.22?