{"record":{"id":"eeef53faab0eb50e","repo":"JuliusBrussee/caveman","slug":"password-must-be-at-most-d-bytes","errorCode":null,"errorMessage":"password must be at most %d bytes","messagePattern":"password must be at most (.+?) bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"shared/platform/security/keys.go","lineNumber":25,"sourceCode":"\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/crypto/argon2\"\n)\n\nconst (\n\tMinPasswordBytes = 12\n\tMaxPasswordBytes = 1024\n)\n\nfunc ValidatePassword(password string) error {\n\tif len(password) < MinPasswordBytes {\n\t\treturn fmt.Errorf(\"password must be at least %d bytes\", MinPasswordBytes)\n\t}\n\tif len(password) > MaxPasswordBytes {\n\t\treturn fmt.Errorf(\"password must be at most %d bytes\", MaxPasswordBytes)\n\t}\n\treturn nil\n}\n\nfunc GenerateProjectKey() (string, string, error) {\n\traw := make([]byte, 32)\n\tif _, err := rand.Read(raw); err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tsecret := base64.RawURLEncoding.EncodeToString(raw)\n\tfull := \"cave_live_\" + secret[:12] + \"_\" + secret[12:]\n\treturn full, secret[:12], nil\n}\n\nfunc HashProjectKey(pepper, full string) string {\n\tmac := hmac.New(sha256.New, []byte(pepper))\n\tmac.Write([]byte(full))\n\treturn hex.EncodeToString(mac.Sum(nil))","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/shared/platform/security/keys.go#L7-L43","documentation":"security.ValidatePassword rejects inputs longer than MaxPasswordBytes = 1024 bytes. The cap exists to prevent resource-exhaustion via argon2 on huge inputs and to bound request handling; it is a length check only, not a complexity check.","triggerScenarios":"Calling security.ValidatePassword with a string over 1024 bytes, e.g. a pasted passphrase manager blob, a keyboard mash, or a client that accidentally sends the whole form as the password field.","commonSituations":"Bug where the wrong form field or file content is passed as the password; automated fuzzers; clients concatenating tokens onto the password.","solutions":["Cap password input length client-side (e.g. maxlength) and server-side before calling ValidatePassword.","Fix the caller that passes the wrong field/blob into the password parameter.","If legitimate use requires more, revisit the API — passwords should never approach 1 KiB; prefer a key file for that."],"exampleFix":"// before\nerr := security.ValidatePassword(request.Body) // body can be MBs\n\n// after\nif len(request.Body) > security.MaxPasswordBytes {\n    return fmt.Errorf(\"input too large\")\n}\nerr := security.ValidatePassword(string(request.Body))","handlingStrategy":"validation","validationCode":"if len(password) > security.MaxPasswordBytes {\n    return fmt.Errorf(\"password too long (max %d bytes)\", security.MaxPasswordBytes)\n}","typeGuard":"func withinMaxPasswordBytes(pw string) bool { return len(pw) <= security.MaxPasswordBytes }","tryCatchPattern":"if err := security.ValidatePassword(pw); err != nil {\n    // treat as client error; check which bound tripped via message\n}","preventionTips":["Cap password inputs at the form/API layer (maxlength or request validation).","A password near 1 KiB almost always means the wrong field is being passed — assert field names in tests."],"tags":["validation","password","security","go"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}