{"record":{"id":"fadd24063c185de0","repo":"glanceapp/glance","slug":"decoding-secret-key-v","errorCode":null,"errorMessage":"decoding secret-key: %v","messagePattern":"decoding secret-key: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/glance/glance.go","lineNumber":64,"sourceCode":"\nfunc newApplication(c *config) (*application, error) {\n\tapp := &application{\n\t\tVersion:    buildVersion,\n\t\tCreatedAt:  time.Now(),\n\t\tConfig:     *c,\n\t\tslugToPage: make(map[string]*page),\n\t\twidgetByID: make(map[uint64]widget),\n\t}\n\tconfig := &app.Config\n\n\t//\n\t// Init auth\n\t//\n\n\tif len(config.Auth.Users) > 0 {\n\t\tsecretBytes, err := base64.StdEncoding.DecodeString(config.Auth.SecretKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decoding secret-key: %v\", err)\n\t\t}\n\n\t\tif len(secretBytes) != AUTH_SECRET_KEY_LENGTH {\n\t\t\treturn nil, fmt.Errorf(\"secret-key must be exactly %d bytes\", AUTH_SECRET_KEY_LENGTH)\n\t\t}\n\n\t\tapp.usernameHashToUsername = make(map[string]string)\n\t\tapp.failedAuthAttempts = make(map[string]*failedAuthAttempt)\n\t\tapp.RequiresAuth = true\n\n\t\tfor username := range config.Auth.Users {\n\t\t\tuser := config.Auth.Users[username]\n\t\t\tusernameHash, err := computeUsernameHash(username, secretBytes)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"computing username hash for user %s: %v\", username, err)\n\t\t\t}\n\t\t\tapp.usernameHashToUsername[string(usernameHash)] = username\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/glance.go#L46-L82","documentation":"Thrown during application startup when auth is configured (users exist) and the `auth.secret-key` value cannot be base64-decoded with standard encoding. The secret key is stored as base64 in the YAML config, so any character outside the standard base64 alphabet or wrong padding makes DecodeString fail.","triggerScenarios":"Setting `secret-key` to a raw 64-byte random string instead of its base64 encoding; hand-editing the key and introducing spaces, url-safe (-/_) characters, or truncating/wrapping the value; using base64url encoding instead of standard base64.","commonSituations":"Generating a key with `openssl rand 64` (raw bytes) instead of `openssl rand -base64 64`; copying a key with a line break from a terminal; secret injected via environment templating that mangles padding ('=' signs stripped).","solutions":["Regenerate the key properly: `openssl rand -base64 64` and paste the single-line result into auth.secret-key","Ensure no whitespace/newlines/url-safe substitutions are present; standard alphabet only (A-Z a-z 0-9 + / =)","If the value comes from a template/env substitution, verify padding characters survive injection"],"exampleFix":"# before\nauth:\n  secret-key: \"hGk9...raw-64-bytes...==(\"  # not valid base64\n# after (generate correctly)\n# openssl rand -base64 64\nauth:\n  secret-key: \"K9dX...single-line-base64...==\"\n","handlingStrategy":"validation","validationCode":"// Validate secret-key before handing config to glance\nimport \"encoding/base64\"\n\nfunc secretKeyValid(s string) error {\n    b, err := base64.StdEncoding.DecodeString(s)\n    if err != nil { return fmt.Errorf(\"secret-key is not standard base64: %w\", err) }\n    if len(b) != 64 { return fmt.Errorf(\"secret-key decodes to %d bytes, want 64\", len(b)) }\n    return nil\n}\n","typeGuard":null,"tryCatchPattern":"Treat as fatal config error; catch at startup, print the regen command (`openssl rand -base64 64`), and exit — never fall back to a default key.","preventionTips":["Always generate with `openssl rand -base64 64`","Store the key in a secret manager and inject verbatim; avoid shell transformations","Add a pre-deploy check that base64-decodes and length-checks the key"],"tags":["auth","config","base64","startup"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}