{"record":{"id":"d63f9f4127a5fb66","repo":"projectdiscovery/katana","slug":"could-not-change-ownership-of-chrome-data-director","errorCode":null,"errorMessage":"could not change ownership of chrome data directory","messagePattern":"could not change ownership of chrome data directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/engine/headless/browser/browser.go","lineNumber":401,"sourceCode":"\t\t\tvar err error\n\t\t\ttempDir, err = os.MkdirTemp(l.opts.ChromeUser.HomeDir, \"chrome-data-*\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"could not create temporary chrome data directory\")\n\t\t\t}\n\n\t\t\tuid, err := strconv.Atoi(l.opts.ChromeUser.Uid)\n\t\t\tif err != nil {\n\t\t\t\t_ = os.RemoveAll(tempDir)\n\t\t\t\treturn nil, errors.Wrap(err, \"invalid user ID\")\n\t\t\t}\n\t\t\tgid, err := strconv.Atoi(l.opts.ChromeUser.Gid)\n\t\t\tif err != nil {\n\t\t\t\t_ = os.RemoveAll(tempDir)\n\t\t\t\treturn nil, errors.Wrap(err, \"invalid group ID\")\n\t\t\t}\n\t\t\tif err := os.Chown(tempDir, uid, gid); err != nil {\n\t\t\t\t_ = os.RemoveAll(tempDir)\n\t\t\t\treturn nil, errors.Wrap(err, \"could not change ownership of chrome data directory\")\n\t\t\t}\n\t\t\tshouldCleanupTempDir = true\n\t\t} else {\n\t\t\tvar err error\n\t\t\ttempDir, err = os.MkdirTemp(\"\", \"katana-chrome-data-*\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"could not create temporary chrome data directory\")\n\t\t\t}\n\t\t\tshouldCleanupTempDir = true\n\t\t}\n\t}\n\n\tbrowser, err := l.launchBrowserWithDataDir(tempDir)\n\tif err != nil {\n\t\tif shouldCleanupTempDir {\n\t\t\t_ = os.RemoveAll(tempDir)\n\t\t}\n\t\treturn nil, err","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/engine/headless/browser/browser.go#L383-L419","documentation":"Thrown when os.Chown(tempDir, uid, gid) fails after the temp chrome data directory was created for ChromeUser. Katana removes the directory and aborts because Chrome would otherwise run with the wrong profile ownership. Typical causes are the process lacking CAP_CHOWN/root privileges or a nonexistent uid/gid pair.","triggerScenarios":"ChromeUser set with a uid/gid the current process may not chown to: not running as root and target uid != current uid, target uid/gid does not exist, or an immutable/read-only filesystem.","commonSituations":"Docker/Kubernetes containers without root or CAP_CHOWN while using a dedicated chrome user; user-namespace remapping making the uid invalid; running katana as a non-root user for a different chrome user.","solutions":["Run the process as root or with CAP_CHOWN when ChromeUser ownership change is required (Docker --user root or securityContext capabilities).","Prefer running the process itself as the chrome user so no chown to a foreign uid is needed.","Verify the uid/gid exist: getent passwd <uid>; getent group <gid>.","Ensure the filesystem backing the temp dir supports chown and the parent directory is writable.","If a dedicated user is unnecessary, set ChromeUser=nil to skip the chown path entirely."],"exampleFix":"// before\n# k8s pod running as 1000, ChromeUser uid 998 -> chown denied\n// after\nsecurityContext:\n  runAsUser: 998\n  runAsGroup: 998","handlingStrategy":"validation","validationCode":"u := opts.ChromeUser\nuid, _ := strconv.Atoi(u.Uid)\nif os.Geteuid() != 0 && os.Geteuid() != uid {\n    return fmt.Errorf(\"cannot chown to %s:%s: run as root or as uid %d\", u.Uid, u.Gid, uid)\n}","typeGuard":"func canChownTo(uid int) bool {\n    return os.Geteuid() == 0 || os.Geteuid() == uid\n}","tryCatchPattern":"page, err := l.createBrowserPageFunc(...)\nif err != nil && strings.Contains(err.Error(), \"change ownership of chrome data directory\") {\n    l.opts.ChromeUser = nil // retry without ownership change\n    page, err = l.createBrowserPageFunc(...)\n}","preventionTips":["Grant CAP_CHOWN or run as root only if chown is genuinely required.","Prefer running the process itself as the chrome user instead of chowning afterwards.","Verify target uid/gid exist with getent before launch.","Remember container user-namespace remapping shifts uid validity."],"tags":["permissions","filesystem","chrome","containers"],"backgroundTag":"chown-permission-denied","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}