{"record":{"id":"c14d906398ee3399","repo":"puppetlabs/puppet","slug":"attempt-to-install-file-with-an-invalid-path-into","errorCode":null,"errorMessage":"Attempt to install file with an invalid path into %{path} under %{dir}","messagePattern":"Attempt to install file with an invalid path into %(.+?) under %(.+?)","errorType":"exception","errorClass":"Puppet::ModuleTool::Errors::InvalidPathInPackageError","httpStatus":null,"severity":"error","filePath":"lib/puppet/module_tool/tar/mini.rb","lineNumber":109,"sourceCode":"  # This check was mainly added to ignore 'x' and 'g' flags from the PAX\n  # standard but will also ignore any other non-standard tar flags.\n  # tar format info: https://pic.dhe.ibm.com/infocenter/zos/v1r13/index.jsp?topic=%2Fcom.ibm.zos.r13.bpxa500%2Ftaf.htm\n  # pax format info: https://pic.dhe.ibm.com/infocenter/zos/v1r13/index.jsp?topic=%2Fcom.ibm.zos.r13.bpxa500%2Fpxarchfm.htm\n  def find_valid_files(tarfile)\n    Archive::Tar::Minitar.open(tarfile).collect do |entry|\n      flag = entry.typeflag\n      if flag.nil? || flag =~ /[[:digit:]]/ && (0..7).cover?(flag.to_i)\n        entry.full_name\n      else\n        Puppet.debug \"Invalid tar flag '#{flag}' will not be extracted: #{entry.name}\"\n        next\n      end\n    end\n  end\n\n  def validate_entry(destdir, path)\n    if Pathname.new(path).absolute?\n      raise Puppet::ModuleTool::Errors::InvalidPathInPackageError, :entry_path => path, :directory => destdir\n    end\n\n    path = Pathname.new(File.join(destdir, path)).cleanpath.to_path\n\n    if path !~ /\\A#{Regexp.escape destdir}/\n      raise Puppet::ModuleTool::Errors::InvalidPathInPackageError, :entry_path => path, :directory => destdir\n    end\n  end\nend\n","sourceCodeStart":91,"sourceCodeEnd":119,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module_tool/tar/mini.rb#L91-L119","documentation":"While unpacking a module tarball, the Mini backend validates every entry path before extraction. validate_entry first rejects entries whose path is absolute (Pathname#absolute? — leading '/' or a Windows drive root) with InvalidPathInPackageError, because joining an absolute path with the destination would write outside the module directory. This is a security control against hostile or malformed packages, not a Puppet bug.","triggerScenarios":"'puppet module install' of a tarball containing at least one entry with an absolute name — typically packages created with 'tar czf mod.tar.gz /abs/path/to/files', or malicious archives attempting to overwrite system files.","commonSituations":"Hand-packaged modules built with wrong tar flags from outside the module root; CI pipelines archiving absolute paths; hostile third-party modules; archives converted from Windows zips with drive-letter paths.","solutions":["Rebuild the package with relative paths from inside the module root (cd mymod && tar czf ../author-mymod-1.0.0.tar.gz metadata.json manifests lib), or better, use 'puppet module build'.","Inspect the archive first: tar tzf pkg.tar.gz — any leading '/' or drive letter is a red flag.","If the module came unmodified from a third party, treat it as hostile and report it; do not force extraction.","Keep puppet-agent current so the hardened validators (absolute paths, traversal, symlinks) all run."],"exampleFix":"# before — absolute entry names\n$ tar czf mymod.tar.gz /home/me/src/mymod/metadata.json /home/me/src/mymod/manifests\n\n# after — relative entries from the module root\n$ cd /home/me/src/mymod && tar czf /tmp/author-mymod-1.0.0.tar.gz metadata.json manifests lib","handlingStrategy":"validation","validationCode":"require 'minitar'\nrequire 'pathname'\n# reject packages whose entries are absolute before attempting install\ndef safe_package?(tarball)\n  Minitar::Input.open(File.open(tarball, 'rb')) do |inp|\n    inp.each { |entry| return false if Pathname.new(entry.name).absolute? }\n  end\n  true\nend","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::ModuleTool::Tar.instance.unpack(pkg, target_dir, module_name)\nrescue Puppet::ModuleTool::Errors::InvalidPathInPackageError => e\n  # entry_path/directory in the message identify the offender — quarantine the package\n  quarantine(pkg)\nend","preventionTips":["Build packages only with 'puppet module build'.","Audit third-party tarballs with 'tar tzf' before installing.","Source modules from the public Forge or a reviewed internal mirror.","Treat this error as a security finding; never retry with --force."],"tags":["puppet","ruby","module-tool","tar","security","path-traversal","hardening"],"backgroundTag":"archive-path-traversal","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}