{"record":{"id":"ccf7660566c5fafd","repo":"puppetlabs/puppet","slug":"passwords-cannot-include-ccf766","errorCode":null,"errorMessage":"Passwords cannot include ':'","messagePattern":"Passwords cannot include ':'","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/user.rb","lineNumber":277,"sourceCode":"            events:\n            - !ruby/object:Puppet::Transaction::Event\n              audited: false\n              property: password\n              previous_value: \"[redacted]\"\n              desired_value: \"[redacted]\"\n              historical_value:\n              message: changed [redacted] to [redacted]\n              name: :password_changed\n              status: success\n              time: 2017-05-17 16:06:02.934398293 -07:00\n              redacted: true\n              corrective_change: false\n            corrective_change: false\n        ```\n        }\n\n      validate do |value|\n        raise ArgumentError, _(\"Passwords cannot include ':'\") if value.is_a?(String) and value.include?(\":\")\n      end\n\n      sensitive true\n    end\n\n    newproperty(:password_min_age, :required_features => :manages_password_age) do\n      desc \"The minimum number of days a password must be used before it may be changed.\"\n\n      munge do |value|\n        case value\n        when String\n          Integer(value)\n        else\n          value\n        end\n      end\n\n      validate do |value|","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/user.rb#L259-L295","documentation":"The user type's `password` property takes a shadow-format password hash. /etc/shadow entries are colon-separated fields, so a value containing ':' would corrupt the stored entry; the validate (lib/puppet/type/user.rb:277) therefore raises ArgumentError for any String containing ':'. The property is sensitive and normally reports as [redacted].","triggerScenarios":"`user { 'bob': password => 'bob:$6$salt$hash' }` (whole shadow line pasted instead of just the hash field); generated secrets formatted as 'salt:hash'; stray trailing colon.","commonSituations":"Copy-pasting full lines from /etc/shadow or usermgmt exports; password-generator functions that emit 'salt:hash' pairs; YAML values carrying extra structure.","solutions":["Pass only the hash field itself (e.g. '$6$salt$hash...')","Split salt/hash pairs in your generation pipeline before assigning","Strip colons from the value in wrapper code and fail if any remain"],"exampleFix":"# before (whole shadow line pasted)\nuser { 'bob':\n  ensure   => present,\n  password => 'bob:$6$saltsalt$hashhashhash',\n}\n\n# after (hash field only)\nuser { 'bob':\n  ensure   => present,\n  password => '$6$saltsalt$hashhashhash',\n}","handlingStrategy":"validation","validationCode":"if $password != undef and $password =~ /:/ {\n  fail('user password must be the bare hash; it cannot contain \":\"')\n}","typeGuard":"def valid_user_password?(pw)\n  pw.is_a?(String) && !pw.include?(':')\nend","tryCatchPattern":"begin\n  Puppet::Type.type(:user).new(name: 'bob', password: 'bob:$6$s$hash')\nrescue ArgumentError => e\n  raise unless e.message.include?(\"Passwords cannot include ':'\")\n  # keep only the hash field and rebuild\nend","preventionTips":["Never paste whole /etc/shadow lines; extract the second field","Generate hashes with puppet's puppet application of openssl passwd -6 or pwgen pipelines that avoid ':'","Keep password lookups Sensitive-typed to avoid logging"],"tags":["puppet","user","password","shadow","validation"],"backgroundTag":"invalid-password-characters","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}