puppetlabs/puppet · error · ArgumentError
invalid key
Error message
invalid key
What it means
Before touching disk, the JSON terminus validates the key against Puppet::Indirector::BadNameRegexp, which matches a leading '..', any '/' or '\\', a NUL byte, or a leading Windows drive-letter prefix like 'C:'. A match means the key could escape the indirection's data directory (directory traversal), so Puppet logs crit 'directory traversal detected in <class>: <name>' and raises ArgumentError 'invalid key'.
Source
Thrown at lib/puppet/indirector/json.rb:44
rescue => detail
unless detail.is_a? Errno::ENOENT
raise Puppet::Error, _("Could not destroy %{json} %{request}: %{detail}") % { json: name, request: request.key, detail: detail }, detail.backtrace
end
1 # emulate success...
end
def search(request)
Dir.glob(path(request.key)).collect do |file|
load_json_from_file(file, request.key)
end
end
# Return the path to a given node's file.
def path(name, ext = '.json')
if name =~ Puppet::Indirector::BadNameRegexp then
Puppet.crit(_("directory traversal detected in %{json}: %{name}") % { json: self.class, name: name.inspect })
raise ArgumentError, _("invalid key")
end
base = data_dir
File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
end
private
def data_dir
Puppet.run_mode.server? ? Puppet[:server_datadir] : Puppet[:client_datadir]
end
def load_json_from_file(file, key)
json = nil
begin
json = Puppet::FileSystem.read(file, :encoding => Encoding::BINARY)
rescue Errno::ENOENTView on GitHub (pinned to e227c27540)
Solutions
- Sanitize the key before the call: strip or replace path separators, NULs, and leading '..' sequences.
- Encode identifiers that legitimately contain special characters (URL-encode or digest them) instead of passing them raw.
- Reject malformed names at your API boundary with a clear error rather than letting the crit log be the first signal.
- If slashes come from provisioning (certname strategy), change the naming scheme instead of working around the guard.
Example fix
# before
Puppet::Node.indirection.destroy('web/server01')
# crit: directory traversal detected ... ArgumentError: invalid key
# after
safe_key = 'web/server01'.tr('/', '_') # => 'web_server01'
Puppet::Node.indirection.destroy(safe_key) Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'unsafe key ' + key.inspect if key.to_s.match?(Puppet::Indirector::BadNameRegexp)
# normalize instead of passing raw separators
safe_key = key.tr('/', '_') Type guard
def safe_indirector_key?(name) name.is_a?(String) && !name.match?(Puppet::Indirector::BadNameRegexp) end
Prevention
- Never accept raw user input as an indirector key.
- Standardize certnames without slashes or drive-letter prefixes.
- Treat the crit log 'directory traversal detected' as a security signal and alert on it.
When it happens
Trigger: Calling find/save/destroy on a json-backed indirection with a key containing a slash (certname 'web/server01'), a leading '..', an absolute path, a NUL byte, or a 'C:'-style prefix - for example passing a file path or URI where a bare key is expected.
Common situations: Node/certname schemes that include slashes; callers feeding unvalidated upstream identifiers into the indirector; code migrating from file APIs and reusing paths as keys.
Related errors
- invalid key
- invalid key
- Attempt to install file with an invalid path into %{path} un
- Could not destroy %{json} %{request}: %{detail}
- Could not read JSON data for %{name} %{key}: %{detail}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/7d54d7ab15a1ad9c.
Report an issue: GitHub.