{"record":{"id":"5d135273044e26f8","repo":"puppetlabs/puppet","slug":"invalid-field-given-for-user-user-name","errorCode":null,"errorMessage":"Invalid #{field} given for user #{user_name}","messagePattern":"Invalid #(.+?) given for user #(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/provider/user/directoryservice.rb","lineNumber":220,"sourceCode":"    Puppet::Util::Plist.parse_plist(plist_data)\n  end\n\n  # The salted-SHA512 password hash in 10.7 is stored in the 'SALTED-SHA512'\n  # key as binary data. That data is extracted and converted to a hex string.\n  def self.get_salted_sha512(embedded_binary_plist)\n    embedded_binary_plist['SALTED-SHA512'].unpack1(\"H*\")\n  end\n\n  # This method reads the passed embedded_binary_plist hash and returns values\n  # according to which field is passed.  Arguments passed are the hash\n  # containing the value read from the 'ShadowHashData' key in the User's\n  # plist, and the field to be read (one of 'entropy', 'salt', or 'iterations')\n  def self.get_salted_sha512_pbkdf2(field, embedded_binary_plist, user_name = \"\")\n    case field\n    when 'salt', 'entropy'\n      value = embedded_binary_plist['SALTED-SHA512-PBKDF2'][field]\n      if value.nil?\n        raise Puppet::Error, \"Invalid #{field} given for user #{user_name}\"\n      end\n\n      value.unpack1('H*')\n    when 'iterations'\n      Integer(embedded_binary_plist['SALTED-SHA512-PBKDF2'][field])\n    else\n      raise Puppet::Error, \"Puppet has tried to read an incorrect value from the user #{user_name} in the SALTED-SHA512-PBKDF2 hash. Acceptable fields are 'salt', 'entropy', or 'iterations'.\"\n    end\n  end\n\n  # In versions 10.5 and 10.6 of OS X, the password hash is stored in a file\n  # in the /var/db/shadow/hash directory that matches the GUID of the user.\n  def self.get_sha1(guid)\n    password_hash = nil\n    password_hash_file = \"#{password_hash_dir}/#{guid}\"\n    if Puppet::FileSystem.exist?(password_hash_file) and File.file?(password_hash_file)\n      raise Puppet::Error, \"Could not read password hash file at #{password_hash_file}\" unless File.readable?(password_hash_file)\n","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/provider/user/directoryservice.rb#L202-L238","documentation":"Raised by Puppet's macOS DirectoryService user provider when reading a user's ShadowHashData yields a nil 'salt' or 'entropy' value inside the SALTED-SHA512-PBKDF2 dictionary. get_salted_sha512_pbkdf2 expects both binary keys to exist; a missing key means the stored password hash record is malformed or of a different format.","triggerScenarios":"Reading/comparing `password` on a macOS (10.8+) user whose hash was set as a different scheme (e.g., CRAM-MD5, SHA1 legacy, or a partially written PBKDF2 record), or a user record migrated/imported without full PBKDF2 data. Note 'iterations' uses Integer() and fails differently; only salt/entropy raise this.","commonSituations":"Users created by third-party MDM/imaging tools that write only some keys; accounts predating an OS upgrade; hand-edited plists; dscl cache serving stale/partial records.","solutions":["Inspect the record: `dscl -plist . -read /Users/<name> ShadowHashData` and decode the plist to see which keys exist.","Reset the user's password properly (`passwd` or Users & Groups) so macOS writes a complete SALTED-SHA512-PBKDF2 hash.","Then re-run Puppet; the property compare will see a well-formed hash.","If provisioning new users, provide the full 256-char PBKDF2 hash (salt+entropy+iterations) as the provider expects."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# confirm the PBKDF2 keys exist before managing password on the user\nrequire 'shellwords'\nout = `dscl -plist . -read /Users/alice ShadowHashData 2>/dev/null`\n# decode ShadowHashData plist and check ['SALTED-SHA512-PBKDF2']['salt'] and ['entropy'] are present","typeGuard":"def full_pbkdf2_record?(embedded_binary_plist)\n  h = embedded_binary_plist['SALTED-SHA512-PBKDF2']\n  h.is_a?(Hash) && !h['salt'].nil? && !h['entropy'].nil? && !h['iterations'].nil?\nend","tryCatchPattern":"begin\n  provider.password = pbkdf2_hash\nrescue Puppet::Error => e\n  raise unless e.message =~ /Invalid (salt|entropy) given for user/\n  # record is malformed: reset via system tooling, then let Puppet converge next run\n  Puppet::Util::Execution.execute(['passwd', resource[:name]], stdinfile: reset_file)\nend","preventionTips":["Provision macOS users with complete PBKDF2 hashes (salt, entropy, iterations).","Avoid third-party tools that write partial ShadowHashData records.","When inheriting imaged machines, reset passwords once via supported tooling before managing them."],"tags":["macos","user-management","password-hash","dscl","puppet"],"backgroundTag":"malformed-password-hash","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}