{"record":{"id":"429902c926dd1e9c","repo":"semaphoreui/semaphore","slug":"invalid-password-key","errorCode":null,"errorMessage":"invalid password key","messagePattern":"invalid password key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services/server/access_key_serializer_local.go","lineNumber":54,"sourceCode":"\t\t}\n\t\tplaintext = []byte(key.String)\n\tcase db.AccessKeySSH:\n\t\tif key.SshKey.PrivateKey == \"\" {\n\t\t\tif key.SshKey.Login != \"\" || key.SshKey.Passphrase != \"\" {\n\t\t\t\treturn fmt.Errorf(\"invalid ssh key\")\n\t\t\t}\n\t\t\tkey.Secret = nil\n\t\t\treturn nil\n\t\t}\n\n\t\tplaintext, err = json.Marshal(key.SshKey)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tcase db.AccessKeyLoginPassword:\n\t\tif key.LoginPassword.Password == \"\" {\n\t\t\tif key.LoginPassword.Login != \"\" {\n\t\t\t\treturn fmt.Errorf(\"invalid password key\")\n\t\t\t}\n\t\t\tkey.Secret = nil\n\t\t\treturn nil\n\t\t}\n\n\t\tplaintext, err = json.Marshal(key.LoginPassword)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tcase db.AccessKeyNone:\n\t\tkey.Secret = nil\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid access token type\")\n\t}\n\n\tsecret, err := util.Config.EncryptAccessSecret(plaintext)\n\tif err != nil {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/services/server/access_key_serializer_local.go#L36-L72","documentation":"SerializeSecret for a local-stored LoginPassword access key requires a non-empty password: a key with an empty password but a non-empty login is invalid. The serializer refuses to encrypt/store such a hollow key and returns 'invalid password key'.","triggerScenarios":"Calling SerializeSecret (e.g. during RekeyAccessKeys) on an AccessKey of type AccessKeyLoginPassword whose LoginPassword.Password is empty while Login is set.","commonSituations":"API clients submitting login/password keys with the password omitted or blank; credentials rotated to empty by mistake; forms allowing empty password fields.","solutions":["Set LoginPassword.Password to the actual secret before serializing.","If only a login is needed without a password, clear Login as well or switch the key type to AccessKeyNone.","Add client-side validation that password is non-empty when the key type is login_password."],"exampleFix":"// before\nkey.LoginPassword = db.LoginPassword{Login: \"deploy\"}\n// after\nkey.LoginPassword = db.LoginPassword{Login: \"deploy\", Password: \"s3cret\"}","handlingStrategy":"validation","validationCode":"if key.Type == db.AccessKeyLoginPassword && key.LoginPassword.Password == \"\" {\n    // invalid: require password or clear Login / change key type\n}","typeGuard":null,"tryCatchPattern":"if err := svc.SerializeSecret(key); err != nil && err.Error() == \"invalid password key\" { /* prompt for the password and retry */ }","preventionTips":["Make password a required field when key type is login_password in clients.","Validate non-empty credentials before calling the API.","Audit keys with empty passwords after bulk imports."],"tags":["go","validation","secrets","credentials"],"backgroundTag":"empty-required-field","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}