{"record":{"id":"dd49780b87ac2af5","repo":"crowdsecurity/crowdsec","slug":"while-getting-ace-w","errorCode":null,"errorMessage":"while getting ACE: %w","messagePattern":"while getting ACE: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csplugin/utils_windows.go","lineNumber":129,"sourceCode":"\n\t/*\n\t\t\tFor reference, the structure of the ACL type is:\n\t\t\ttype ACL struct {\n\t\t\taclRevision byte\n\t\t\tsbz1        byte\n\t\t\taclSize     uint16\n\t\t\taceCount    uint16\n\t\t\tsbz2        uint16\n\t\t}\n\t\tAs the field are not exported, we have to use reflection to access them, this should not be an issue as the structure won't (probably) change any time soon.\n\t*/\n\taceCount := rs.Field(3).Uint()\n\n\tfor i := range aceCount {\n\t\tace := &AccessAllowedAce{}\n\t\tret, _, _ := procGetAce.Call(uintptr(unsafe.Pointer(dacl)), uintptr(i), uintptr(unsafe.Pointer(&ace)))\n\t\tif ret == 0 {\n\t\t\treturn fmt.Errorf(\"while getting ACE: %w\", windows.GetLastError())\n\t\t}\n\t\tlog.Debugf(\"ACE %d: %+v\\n\", i, ace)\n\n\t\tif ace.AceType == ACCESS_DENIED_ACE_TYPE {\n\t\t\tcontinue\n\t\t}\n\t\taceSid := (*windows.SID)(unsafe.Pointer(&ace.SidStart))\n\n\t\tif aceSid.Equals(systemSid) || aceSid.Equals(adminSid) {\n\t\t\tlog.Debugf(\"Not checking permission for well-known SID %s\", aceSid.String())\n\t\t\tcontinue\n\t\t}\n\n\t\tif aceSid.Equals(currentUserSid) {\n\t\t\tlog.Debugf(\"Not checking permission for current user %s\", currentUser.Username)\n\t\t\tcontinue\n\t\t}\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csplugin/utils_windows.go#L111-L147","documentation":"CheckPerms walks the plugin's ACL entries by calling the Win32 GetAce API via advapi32.dll (procGetAce.Call). If GetAce returns 0 (failure), this error wraps windows.GetLastError(), meaning the i-th ACE could not be retrieved from the DACL. Causes include an index beyond aceCount, a corrupt ACL, or reflection-derived aceCount mismatching the real ACL state (e.g. the ACL changed concurrently).","triggerScenarios":"Calling CheckPerms when procGetAce.Call fails for some index i: ACL was modified between reading aceCount and enumerating; ACL revision/size fields inconsistent with actual memory; malformed ACL on the file.","commonSituations":"Antivirus/EDR or group policy rewriting plugin-directory ACLs while crowdsec is enumerating them; corrupted ACLs from backup/restore tools; races when multiple processes adjust ACLs simultaneously.","solutions":["Re-run crowdsec once ACL churn settles — a transient race often resolves on retry","Reset and re-apply a stable ACL: `icacls <plugin> /reset` then `icacls <plugin> /grant ...`","Exclude the crowdsec plugin directory from antivirus ACL-rewriting policies","Read the wrapped GetLastError() code to confirm the specific Win32 failure"],"exampleFix":"// before\nret, _, _ := procGetAce.Call(uintptr(unsafe.Pointer(dacl)), uintptr(i), uintptr(unsafe.Pointer(&ace)))\nif ret == 0 {\n\treturn fmt.Errorf(\"while getting ACE: %w\", windows.GetLastError())\n}\n// after\nret, _, _ := procGetAce.Call(uintptr(unsafe.Pointer(dacl)), uintptr(i), uintptr(unsafe.Pointer(&ace)))\nif ret == 0 {\n\treturn fmt.Errorf(\"while getting ACE %d of %d for %s: %w\", i, aceCount, path, windows.GetLastError())\n}","handlingStrategy":"retry","validationCode":"// ensure ACL size fields are consistent before enumeration\nsd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION)\nif err != nil || !sd.IsValid() {\n\treturn errors.New(\"DACL not reliably readable\")\n}","typeGuard":null,"tryCatchPattern":"var lastErr error\nfor attempt := 0; attempt < 3; attempt++ {\n\terr := CheckPerms(pluginPath)\n\tif err == nil {\n\t\tbreak\n\t}\n\tif strings.Contains(err.Error(), \"while getting ACE\") {\n\t\tlastErr = err\n\t\ttime.Sleep(500 * time.Millisecond) // ACL may be mid-modification\n\t\tcontinue\n\t}\n\treturn err\n}\nreturn lastErr","preventionTips":["Don't modify plugin-directory ACLs while crowdsec is running","Exclude the plugin directory from ACL-rewriting security software","Apply ACL changes in a single atomic operation (one icacls command)"],"tags":["windows","acl","win32","security"],"backgroundTag":"index-out-of-bounds","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}