{"record":{"id":"7bdeb1860dc0a568","repo":"JuliusBrussee/caveman","slug":"native-session-key-create-w","errorCode":null,"errorMessage":"native session key create: %w","messagePattern":"native session key create: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/marker.go","lineNumber":54,"sourceCode":"\tfile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)\n\tif err == nil {\n\t\tif _, writeErr := file.Write(key); writeErr != nil {\n\t\t\t_ = file.Close()\n\t\t\t_ = os.Remove(path)\n\t\t\treturn nil, fmt.Errorf(\"native session key write: %w\", writeErr)\n\t\t}\n\t\tif syncErr := file.Sync(); syncErr != nil {\n\t\t\t_ = file.Close()\n\t\t\t_ = os.Remove(path)\n\t\t\treturn nil, fmt.Errorf(\"native session key sync: %w\", syncErr)\n\t\t}\n\t\tif closeErr := file.Close(); closeErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"native session key close: %w\", closeErr)\n\t\t}\n\t\treturn key, nil\n\t}\n\tif !errors.Is(err, os.ErrExist) {\n\t\treturn nil, fmt.Errorf(\"native session key create: %w\", err)\n\t}\n\tkey, err = os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key read: %w\", err)\n\t}\n\tif len(key) != sessionKeyBytes {\n\t\treturn nil, fmt.Errorf(\"native session key length = %d, want %d\", len(key), sessionKeyBytes)\n\t}\n\tif err := os.Chmod(path, 0o600); err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key chmod: %w\", err)\n\t}\n\treturn key, nil\n}\n\n// SessionMarker builds model-temporary correlation context. Local proxy removes\n// valid markers byte-surgically before provider inspection or forwarding.\nfunc SessionMarker(key []byte, sessionID string) (string, error) {\n\tif len(key) != sessionKeyBytes || sessionID == \"\" || len(sessionID) > 256 {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/proxy/internal/nativeruntime/marker.go#L36-L72","documentation":"os.OpenFile(path, O_WRONLY|O_CREATE|O_EXCL, 0600) failed with an error other than os.ErrExist — the EEXIST first-startup race is handled separately just below, so this error means a genuinely unexpected create failure: EACCES or EROFS on the runtime dir, ENOSPC, or ENAMETOOLONG. It fires right after successful MkdirAll+Chmod, so permissions usually changed underneath (MAC policy denial, concurrent chmod, immutable attribute).","triggerScenarios":"SELinux or AppArmor denying file creation inside the runtime dir; a concurrent process tightening permissions between the chmod and the open; chattr +i on the directory; a read-only remount occurring mid-startup.","commonSituations":"Hardened RHEL/Ubuntu hosts with strict MAC policy; security agents racing process startups; containers where the directory came from a lower, read-only layer.","solutions":["Check MAC denials: ausearch -m avc -ts recent or the AppArmor log for the runtime path","lsattr -d <home>/runtime — if immutable, clear with chattr -i","Verify dir state: ls -ld <home>/runtime (want 0700 and your uid)","Re-run after fixing; the O_EXCL create is atomic and safe to retry"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"dir := filepath.Join(home, \"runtime\")\nif info, err := os.Stat(dir); err == nil {\n\tif !info.IsDir() {\n\t\treturn fmt.Errorf(\"%s exists and is not a directory — remove it\", dir)\n\t}\n\tif st, ok := info.Sys().(*syscall.Stat_t); ok && int(st.Uid) != os.Getuid() {\n\t\treturn fmt.Errorf(\"%s owned by uid %d — run: sudo chown -R %d:%d %s\", dir, st.Uid, os.Getuid(), os.Getgid(), dir)\n\t}\n} else if !errors.Is(err, fs.ErrNotExist) {\n\treturn fmt.Errorf(\"cannot inspect %s: %w\", dir, err)\n}\n// only now call nativeruntime.LoadOrCreateSessionKey(home)","typeGuard":"func isPermissionErr(err error) bool {\n\treturn errors.Is(err, fs.ErrPermission)\n}","tryCatchPattern":"key, err := nativeruntime.LoadOrCreateSessionKey(home)\nif err != nil {\n\tif errors.Is(err, fs.ErrPermission) {\n\t\t// dir perms changed under startup or MAC policy denies creation:\n\t\t// check ausearch -m avc / AppArmor logs, then lsattr -d <home>/runtime\n\t\tlog.Print(\"create denied — inspect ownership, immutability, and MAC denials\")\n\t}\n\treturn err\n}","preventionTips":["Audit SELinux/AppArmor policies before deploying to hardened hosts — creation denials land here","Watch for concurrent processes tightening permissions on the runtime dir during startup","Clear immutable attributes (chattr -i) on the caveman home before starting","Pre-check directory ownership and type immediately before first key creation"],"tags":["go","filesystem","permissions","selinux"],"backgroundTag":"file-create-permission-denied","analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}