{"record":{"id":"cd44dcda71e053b3","repo":"puppetlabs/puppet","slug":"mac-os-x-pkg-dmgs-must-specify-a-source-string-end","errorCode":null,"errorMessage":"Mac OS X PKG DMGs must specify a source string ending in .dmg or flat .pkg file","messagePattern":"Mac OS X PKG DMGs must specify a source string ending in \\.dmg or flat \\.pkg file","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/provider/package/pkgdmg.rb","lineNumber":80,"sourceCode":"  end\n\n  def self.installpkg(source, name, orig_source)\n    installer \"-pkg\", source, \"-target\", \"/\"\n    # Non-zero exit status will throw an exception.\n    Puppet::FileSystem.open(\"/var/db/.puppet_pkgdmg_installed_#{name}\", nil, \"w:UTF-8\") do |t|\n      t.print \"name: '#{name}'\\n\"\n      t.print \"source: '#{orig_source}'\\n\"\n    end\n  end\n\n  def self.installpkgdmg(source, name)\n    unless Puppet::Util::HttpProxy.no_proxy?(source)\n      http_proxy_host = Puppet::Util::HttpProxy.http_proxy_host\n      http_proxy_port = Puppet::Util::HttpProxy.http_proxy_port\n    end\n\n    unless source =~ /\\.dmg$/i || source =~ /\\.pkg$/i\n      raise Puppet::Error, _(\"Mac OS X PKG DMGs must specify a source string ending in .dmg or flat .pkg file\")\n    end\n\n    require 'open-uri' # Dead code; this is never used. The File.open call 20-ish lines south of here used to be Kernel.open but changed in '09. -NF\n    cached_source = source\n    tmpdir = Dir.mktmpdir\n    ext = /(\\.dmg|\\.pkg)$/i.match(source)[0]\n    begin\n      if %r{\\A[A-Za-z][A-Za-z0-9+\\-.]*://} =~ cached_source\n        cached_source = File.join(tmpdir, \"#{name}#{ext}\")\n        args = [\"-o\", cached_source, \"-C\", \"-\", \"-L\", \"-s\", \"--fail\", \"--url\", source]\n        if http_proxy_host and http_proxy_port\n          args << \"--proxy\" << \"#{http_proxy_host}:#{http_proxy_port}\"\n        elsif http_proxy_host and !http_proxy_port\n          args << \"--proxy\" << http_proxy_host\n        end\n        begin\n          curl(*args)\n          Puppet.debug \"Success: curl transferred [#{name}] (via: curl #{args.join(' ')})\"","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/provider/package/pkgdmg.rb#L62-L98","documentation":"Raised by `installpkgdmg` (lib/puppet/provider/package/pkgdmg.rb:80), Puppet's macOS pkgdmg provider. The `source` attribute must end in `.dmg` or `.pkg` (case-insensitive) because the suffix selects the strategy: mount a disk image with hdiutil, or install a flat package with `installer -pkg`. Any other extension fails fast before anything is downloaded.","triggerScenarios":"`package { 'Firefox': provider => pkgdmg, source => 'https://.../Firefox.tar.bz2' }`, a CDN/redirect URL whose final path lacks the extension, or a URL with a query string after the filename.","commonSituations":"Pointing source at a .zip archive or an .mpkg bundle (not supported - only flat .pkg); vendor download links that redirect to extension-less URLs; typos in the source.","solutions":["Mirror the artifact as a .dmg or a flat .pkg and point `source` at a URL that literally ends with that extension.","Strip query strings/fragments from the URL so the regex sees the extension.","For .zip or .mpkg payloads, repackage them (a flat .pkg inside a dmg) or use a different provider.","Verify case: the check is case-insensitive, so only the extension itself matters."],"exampleFix":"# before\npackage { 'firefox':\n  ensure   => installed,\n  provider => pkgdmg,\n  source   => 'https://download.example.com/firefox-latest.tar.bz2',\n}\n\n# after\npackage { 'firefox':\n  ensure   => installed,\n  provider => pkgdmg,\n  source   => 'https://download.example.com/mirror/Firefox-115.0.dmg',\n}","handlingStrategy":"validation","validationCode":"# Validate the source extension before declaring the resource\nsource='https://mirror.example.com/Firefox-115.0.dmg'\n[[ \"$source\" =~ \\.(dmg|pkg)$ ]] || { echo \"source must end in .dmg or .pkg\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mirror vendor artifacts under URLs whose final path ends in .dmg or .pkg.","Strip query strings/fragments from download URLs.","Repackage .zip/.mpkg payloads as flat .pkg or .dmg before using pkgdmg."],"tags":["macos","pkgdmg","dmg","source","file-extension"],"backgroundTag":"invalid-file-extension","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}