{"record":{"id":"893d6c39e7cbf3c2","repo":"Billionmail/BillionMail","slug":"no-default-jwt-secret-found","errorCode":null,"errorMessage":"no default jwt secret found","messagePattern":"no default jwt secret found","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/internal/service/rbac/jwt.go","lineNumber":48,"sourceCode":"\tSecret        string        // Secret key for signing JWT\n\tAccessExpiry  time.Duration // Duration for access token expiry\n\tRefreshExpiry time.Duration // Duration for refresh token expiry\n}\n\n// newJWTService creates a new JWTService instance\nfunc newJWTService() *JWTService {\n\tdefaultJwtSecret := \"\"\n\n\tif dbpass, err := public.DockerEnv(\"DBPASS\"); err == nil {\n\t\tdefaultJwtSecret += dbpass\n\t}\n\n\tif redispass, err := public.DockerEnv(\"REDISPASS\"); err == nil {\n\t\tdefaultJwtSecret += redispass\n\t}\n\n\tif defaultJwtSecret == \"\" {\n\t\tpanic(\"no default jwt secret found\")\n\t}\n\n\treturn &JWTService{\n\t\tSecret:        g.Cfg().MustGet(context.Background(), \"jwt.secret\", defaultJwtSecret).String(),\n\t\tAccessExpiry:  time.Duration(g.Cfg().MustGet(context.Background(), \"jwt.accessExpiry\", 86400).Int()) * time.Second,\n\t\tRefreshExpiry: time.Duration(g.Cfg().MustGet(context.Background(), \"jwt.refreshExpiry\", 86400*7).Int()) * time.Second,\n\t}\n}\n\n// GenerateToken generates a new JWT token\nfunc (s *JWTService) GenerateToken(accountId int64, username string, roles []string) (string, int64, error) {\n\texpiryTime := time.Now().Add(s.AccessExpiry)\n\tclaims := &JWTCustomClaims{\n\t\tAccountId: accountId,\n\t\tUsername:  username,\n\t\tRoles:     roles,\n\t\tRegisteredClaims: jwt.RegisteredClaims{\n\t\t\tExpiresAt: jwt.NewNumericDate(expiryTime),","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/rbac/jwt.go#L30-L66","documentation":"newJWTService builds the JWT signing secret from config, falling back to a default derived from the REDISPASS environment variable. If both the configured secret and the env-derived default are empty, it panics with 'no default jwt secret found' because issuing JWTs with an empty secret would be insecure. This is fail-fast startup behavior.","triggerScenarios":"Starting the app without REDISPASS set in the environment and without jwt.secret in config — typically running the binary outside the Docker Compose environment.","commonSituations":"Local development without the .env file / docker compose env; REDISPASS renamed or removed in a custom deployment; config file missing the jwt.secret key.","solutions":["Set the REDISPASS environment variable (as docker-compose.yml does) before starting the service.","Explicitly configure jwt.secret in the GoFrame config file.","Run the service via docker compose so environment variables are injected.","Check .env is loaded in non-Docker dev environments (source it or use a dotenv loader)."],"exampleFix":"// before\nexport RUN_MODE=dev   # REDISPASS missing\n./billionmail\n// after\nexport REDISPASS=$(grep REDISPASS .env | cut -d= -f2)\n./billionmail","handlingStrategy":"validation","validationCode":"// run before starting the app\nif os.Getenv(\"REDISPASS\") == \"\" {\n    cfgSecret := readConfig(\"jwt.secret\")\n    if cfgSecret == \"\" {\n        log.Fatal(\"REDISPASS or jwt.secret must be set\")\n    }\n}","typeGuard":null,"tryCatchPattern":"func() {\n    defer func() {\n        if r := recover(); r != nil {\n            if strings.Contains(fmt.Sprint(r), \"no default jwt secret found\") {\n                log.Fatal(\"startup misconfiguration: set REDISPASS or jwt.secret\")\n            }\n            panic(r)\n        }\n    }()\n    service.JWT()\n}()","preventionTips":["Always deploy via docker compose (or ensure --env-file .env) so REDISPASS is present.","Set an explicit jwt.secret in config for non-Docker environments.","Add a startup preflight check that fails with a readable message before the panic.","Never commit a default secret; keep .env out of VCS but documented in .env.example."],"tags":["jwt","security","environment","startup"],"backgroundTag":"missing-env-var","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}