{"record":{"id":"36a26fd3f6704265","repo":"vercel/turborepo","slug":"owner-only-security-descriptor-did-not-contain-a-d","errorCode":null,"errorMessage":"owner-only security descriptor did not contain a DACL","messagePattern":"owner-only security descriptor did not contain a DACL","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/turborepo-daemon/src/endpoint.rs","lineNumber":287,"sourceCode":"        }\n        let descriptor = LocalAllocGuard(descriptor as HLOCAL);\n\n        let mut dacl_present = 0;\n        let mut dacl_defaulted = 0;\n        let mut dacl: *mut ACL = ptr::null_mut();\n        if unsafe {\n            GetSecurityDescriptorDacl(\n                descriptor.0 as PSECURITY_DESCRIPTOR,\n                &mut dacl_present,\n                &mut dacl,\n                &mut dacl_defaulted,\n            )\n        } == 0\n        {\n            return Err(std::io::Error::last_os_error());\n        }\n        if dacl_present == 0 || dacl.is_null() {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidData,\n                \"owner-only security descriptor did not contain a DACL\",\n            ));\n        }\n\n        let path = wide_null(path.as_std_path().as_os_str());\n        let result = unsafe {\n            SetNamedSecurityInfoW(\n                path.as_ptr(),\n                SE_FILE_OBJECT,\n                DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,\n                ptr::null_mut(),\n                ptr::null_mut(),\n                dacl,\n                ptr::null_mut(),\n            )\n        };\n        if result == ERROR_SUCCESS {","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/crates/turborepo-daemon/src/endpoint.rs#L269-L305","documentation":"set_owner_only_dacl in endpoint.rs builds an owner-only DACL, applies it with SetNamedSecurityInfoW (DACL + PROTECTED_DACL), then reads the descriptor back with GetSecurityDescriptorDacl; this InvalidData error fires when the descriptor comes back with no DACL at all (dacl_present == 0 or null pointer). The ACL write did not stick, so the daemon aborts rather than run with unknown permissions.","triggerScenarios":"Daemon startup hardening on a volume/path that silently drops or ignores DACL protection — e.g. temp redirected to a FAT-formatted or network drive, or the descriptor being rewritten concurrently.","commonSituations":"TMP/TEMP overridden to a non-NTFS location (FAT USB stick, some SMB shares) Object IDs / quota states on the volume that reject PROTECTED_DACL writes","solutions":["Point TEMP/TMP and any daemon path override at a local NTFS volume and restart the daemon","Delete the daemon directory so it is recreated with fresh security descriptors","If it persists on NTFS, report with the volume type and the path involved"],"exampleFix":"# cmd: move temp to a local NTFS drive\nsetx TEMP C:\\Users\\you\\AppData\\Local\\Temp\nsetx TMP C:\\Users\\you\\AppData\\Local\\Temp","handlingStrategy":"try-catch","validationCode":"// ensure temp/daemon paths live on NTFS before daemon start\nfs::metadata(&tmp)?.filesystem_type_is_ntfs() // pseudo; check via GetVolumeInformationW","typeGuard":null,"tryCatchPattern":"match secure_daemon_dir(path) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains(\"DACL\") => {\n        // move to a local NTFS path, then retry daemon start\n    }\n    other => other?,\n}","preventionTips":["Do not point TEMP/TMP or daemon paths at FAT/network volumes","Delete and recreate the daemon dir after volume-type changes"],"tags":["daemon","windows","security","acl","dacl"],"backgroundTag":"acl-security-descriptor-invalid","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}