{"record":{"id":"c88a39daa0630d10","repo":"puppetlabs/puppet","slug":"invalid-key-c88a39","errorCode":null,"errorMessage":"invalid key","messagePattern":"invalid key","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/msgpack.rb","lineNumber":52,"sourceCode":"  rescue => detail\n    unless detail.is_a? Errno::ENOENT\n      raise Puppet::Error, _(\"Could not destroy %{name} %{request}: %{detail}\") % { name: name, request: request.key, detail: detail }, detail.backtrace\n    end\n\n    1 # emulate success...\n  end\n\n  def search(request)\n    Dir.glob(path(request.key)).collect do |file|\n      load_msgpack_from_file(file, request.key)\n    end\n  end\n\n  # Return the path to a given node's file.\n  def path(name, ext = '.msgpack')\n    if name =~ Puppet::Indirector::BadNameRegexp then\n      Puppet.crit(_(\"directory traversal detected in %{indirection}: %{name}\") % { indirection: self.class, name: name.inspect })\n      raise ArgumentError, _(\"invalid key\")\n    end\n\n    base = Puppet.run_mode.server? ? Puppet[:server_datadir] : Puppet[:client_datadir]\n    File.join(base, self.class.indirection_name.to_s, name.to_s + ext)\n  end\n\n  private\n\n  def load_msgpack_from_file(file, key)\n    msgpack = nil\n\n    begin\n      msgpack = Puppet::FileSystem.read(file, :encoding => 'utf-8')\n    rescue Errno::ENOENT\n      return nil\n    rescue => detail\n      # TRANSLATORS \"MessagePack\" is a program name and should not be translated\n      raise Puppet::Error, _(\"Could not read MessagePack data for %{indirection} %{key}: %{detail}\") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/msgpack.rb#L34-L70","documentation":"Before touching disk, the MessagePack terminus validates the key against Puppet::Indirector::BadNameRegexp, which matches a leading '..', any '/' or '\\\\', a NUL byte, or a leading Windows drive-letter prefix. 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'.","triggerScenarios":"Calling find/save/destroy on a msgpack-backed indirection with a key containing a slash, a leading '..', an absolute path, a NUL byte, or a 'C:'-style Windows drive prefix.","commonSituations":"Certnames or identifiers containing separators fed straight from user input; code reusing file paths as keys; cross-platform names accidentally carrying a drive-letter prefix.","solutions":["Sanitize the key before the call: replace path separators, NULs, and leading '..' sequences.","Encode special identifiers (URL-encode or digest) rather than passing them raw.","Validate names at your API boundary and reject bad ones early.","Change the naming scheme if provisioning produces keys with separators."],"exampleFix":"# before\nindirection.destroy('web/server01')\n# crit: directory traversal detected ... ArgumentError: invalid key\n\n# after\nsafe_key = 'web/server01'.tr('/', '_')\nindirection.destroy(safe_key)","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'unsafe key ' + key.inspect if key.to_s.match?(Puppet::Indirector::BadNameRegexp)\nsafe_key = key.tr('/', '_')","typeGuard":"def safe_indirector_key?(name)\n  name.is_a?(String) && !name.match?(Puppet::Indirector::BadNameRegexp)\nend","tryCatchPattern":null,"preventionTips":["Never accept raw user input as an indirector key.","Validate identifiers for separators, NULs, and drive prefixes at the boundary.","Alert on the crit log 'directory traversal detected' - it indicates hostile or broken input."],"tags":["puppet","msgpack","path-traversal","input-sanitization","security"],"backgroundTag":"path-traversal-blocked","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}