{"record":{"id":"1b0cf3aa1d8fefb1","repo":"cloudflare/cloudflared","slug":"get-token-file-dacl-w","errorCode":null,"errorMessage":"get token file DACL: %w","messagePattern":"get token file DACL: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/windows_service.go","lineNumber":185,"sourceCode":"\t\treturn fmt.Errorf(\"create token file: %w\", err)\n\t}\n\n\tif err := windows.CloseHandle(f); err != nil {\n\t\treturn fmt.Errorf(\"close token file: %w\", err)\n\t}\n\n\t// As with os.CreateFile / os.OpenFile on Unix, if the file already exists\n\t// windows.CreateFile will not update the permission information, so we do\n\t// that explicitly after creating the file.\n\n\towner, _, err := sd.Owner()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get token file owner: %w\", err)\n\t}\n\n\tdacl, _, err := sd.DACL()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get token file DACL: %w\", err)\n\t}\n\n\t// Bitmask indicating which security info we want to set on the file:\n\t//\n\t// OWNER_SECURITY_INFORMATION\n\t//\t-> Set file owner\n\t// DACL_SECURITY_INFORMATION\n\t// \t-> Set ACEs\n\t// PROTECTED_DACL_SECURITY_INFORMATION\n\t//  -> Update DACL to be \"protected' such that it cannot inherit entries from its parent\n\tconst securityInfo = windows.OWNER_SECURITY_INFORMATION |\n\t\twindows.DACL_SECURITY_INFORMATION |\n\t\twindows.PROTECTED_DACL_SECURITY_INFORMATION\n\n\tif err := windows.SetNamedSecurityInfo(\n\t\tpath,\n\t\twindows.SE_FILE_OBJECT,\n\t\tsecurityInfo,","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/windows_service.go#L167-L203","documentation":"createTokenFile retrieves the discretionary ACL (DACL) from the parsed security descriptor via sd.DACL() so it can be applied to the token file with SetSecurityInformation. If the SECURITY_DESCRIPTOR has no DACL or the Win32 query fails, cloudflared wraps the error with this message. The DACL is what restricts the token file to Administrators and SYSTEM.","triggerScenarios":"sd.DACL() returns an error for the descriptor built from the SDDL string — the descriptor lacks a 'D:' (DACL) section or its ACEs are invalid.","commonSituations":"A customized sdString that dropped or mangled the 'D:P(...)' portion; tampered/patched cloudflared builds; failure to allocate the ACL during the Win32 call under heavy memory pressure.","solutions":["Ensure the SDDL string keeps its 'D:P(A;;FA;;;BA)(A;;FA;;;SY)' DACL section intact","Validate custom SDDL with PowerShell ConvertFrom-SddlString before embedding","Rebuild/install from an official cloudflared release","Retry after freeing memory if the failure was transient (rare allocation failure)"],"exampleFix":"// before\nconst sdString = \"O:BA\" // DACL section dropped\n// after\nconst sdString = \"O:BAD:P(A;;FA;;;BA)(A;;FA;;;SY)\" // D:P supplies a protected DACL","handlingStrategy":"try-catch","validationCode":"# Ensure the SDDL keeps its DACL section\n$sddl = 'O:BAD:P(A;;FA;;;BA)(A;;FA;;;SY)'\nif (-Not ($sddl -match '^O:[^D]*D:')) { Write-Error 'SDDL missing DACL'; exit 1 }\nConvertFrom-SddlString $sddl | Out-Null","typeGuard":null,"tryCatchPattern":"if err := installWindowsService(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"get token file DACL\") {\n\t\tlog.Error().Msg(\"security descriptor lost its DACL; reinstall an official build\")\n\t}\n\treturn err\n}","preventionTips":["Keep the 'D:P(...)' DACL section intact in the SDDL string","Validate custom SDDL with ConvertFrom-SddlString","Install official builds; retry if the failure was a transient allocation error"],"tags":["windows","sddl","dacl"],"backgroundTag":"security-descriptor-query-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}