{"record":{"id":"620018a736630351","repo":"gastownhall/beads","slug":"identity-generate-proxy-secret-w","errorCode":null,"errorMessage":"identity: generate proxy secret: %w","messagePattern":"identity: generate proxy secret: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/identity/identity.go","lineNumber":45,"sourceCode":"func RootID(rootDir string) (string, error) {\n\tabs, err := filepath.Abs(rootDir)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"identity: absolute root path: %w\", err)\n\t}\n\tresolved, err := filepath.EvalSymlinks(abs)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"identity: resolve root path: %w\", err)\n\t}\n\tsum := sha256.Sum256([]byte(resolved))\n\treturn hex.EncodeToString(sum[:]), nil\n}\n\n// WriteSecret creates and atomically writes a new control-listener secret.\n// Each proxy start intentionally rotates the previous secret.\nfunc WriteSecret(rootDir string) (string, error) {\n\traw := make([]byte, 32)\n\tif _, err := rand.Read(raw); err != nil {\n\t\treturn \"\", fmt.Errorf(\"identity: generate proxy secret: %w\", err)\n\t}\n\tsecret := hex.EncodeToString(raw)\n\tif err := atomicfile.WriteFile(filepath.Join(rootDir, SecretFileName), []byte(secret+\"\\n\"), 0o600); err != nil {\n\t\treturn \"\", fmt.Errorf(\"identity: write proxy secret: %w\", err)\n\t}\n\treturn secret, nil\n}\n\n// ReadSecret reads and validates the control-listener secret.\nfunc ReadSecret(rootDir string) (string, error) {\n\tdata, err := os.ReadFile(filepath.Join(rootDir, SecretFileName)) // #nosec G304 - rootDir is the workspace proxy root, not user input\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"identity: read proxy secret: %w\", err)\n\t}\n\tsecret := strings.TrimSpace(string(data))\n\tif len(secret) != 64 {\n\t\treturn \"\", errors.New(\"identity: invalid proxy secret\")\n\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/identity/identity.go#L27-L63","documentation":"WriteSecret generates 32 random bytes via crypto/rand.Read and encodes them as the control-listener secret. This error wraps a failure of crypto/rand.Read, which on virtually all platforms only fails if the operating system's cryptographic random source is unavailable or broken. The library throws it because it cannot produce a cryptographically secure secret without the OS entropy source.","triggerScenarios":"Calling identity.WriteSecret(rootDir) when crypto/rand.Read fails: on Linux this can happen if getrandom(2) is blocked and /dev/urandom is unavailable; on very early boot before the entropy pool is initialized on old kernels; or in exotic sandboxes/seccomp profiles that block getrandom. It is extremely rare on modern systems.","commonSituations":"Running inside a container or sandbox with a restricted seccomp filter that denies getrandom, extremely stripped-down environments lacking /dev/urandom, or legacy kernels during early boot with insufficient entropy.","solutions":["Inspect the wrapped error via errors.Unwrap to identify the OS-level cause","Fix the environment: ensure /dev/urandom exists and seccomp/sandbox policy permits getrandom(2)","Retry after the system entropy source is available (e.g. after boot completes)","Check container runtime security profiles (Docker seccomp, gVisor) that may block getrandom"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"secret, err := identity.WriteSecret(rootDir)\nif err != nil {\n    // crypto/rand failures are environmental; retry once after a short delay,\n    // then fail loudly with the wrapped cause\n    time.Sleep(100 * time.Millisecond)\n    secret, err = identity.WriteSecret(rootDir)\n    if err != nil {\n        return fmt.Errorf(\"entropy source unavailable: %w\", err)\n    }\n}","preventionTips":["Avoid sandboxes/seccomp profiles that block getrandom(2) or /dev/urandom","Keep kernels reasonably modern (getrandom available since 3.17)","In containers, mount a working /dev/urandom","Treat this error as an environment health signal, not a code bug"],"tags":["go","crypto","entropy","random-generation"],"backgroundTag":"crypto-rand-failure","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}