crowdsecurity/crowdsec · error

no DACL found on plugin, meaning fully permissive access on

Error message

no DACL found on plugin, meaning fully permissive access on plugin %s

What it means

This is an explicit security check: if the plugin file has no DACL, Windows grants everyone full access, meaning any local user could modify or replace the plugin binary that crowdsec executes. CheckPerms refuses such a file. Note this can also trigger on filesystems that don't support ACLs at all.

Source

Thrown at pkg/csplugin/utils_windows.go:107

	owner, _, err := sd.Owner()
	if err != nil {
		return fmt.Errorf("while getting owner: %w", err)
	}
	if !owner.IsValid() {
		return errors.New("owner is invalid")
	}

	if !owner.Equals(systemSid) && !owner.Equals(currentUserSid) && !owner.Equals(adminSid) {
		return fmt.Errorf("plugin at %s is not owned by SYSTEM, Administrators or by current user, but by %s", path, owner.String())
	}

	dacl, _, err := sd.DACL()
	if err != nil {
		return fmt.Errorf("while getting DACL: %w", err)
	}

	if dacl == nil {
		return fmt.Errorf("no DACL found on plugin, meaning fully permissive access on plugin %s", path)
	}

	rs := reflect.ValueOf(dacl).Elem()

	/*
			For reference, the structure of the ACL type is:
			type ACL struct {
			aclRevision byte
			sbz1        byte
			aclSize     uint16
			aceCount    uint16
			sbz2        uint16
		}
		As 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.
	*/
	aceCount := rs.Field(3).Uint()

	for i := range aceCount {

View on GitHub (pinned to 909b515798)

Solutions

  1. Move the plugins to an NTFS volume and apply a restrictive ACL: `icacls <plugin> /inheritance:r /grant Administrators:F /grant SYSTEM:F`
  2. Ensure a DACL exists at all — a freshly reset or explicitly granted ACL (`icacls <plugin> /grant ...`) removes the NULL-DACL state
  3. Avoid storing plugins on FAT32/exFAT/network shares; use the default install path on NTFS
  4. Verify with `icacls <plugin>` that explicit ACEs are listed

Example fix

// before
# plugin on FAT32 mount → no DACL
// after
# move to NTFS and grant explicit ACEs (elevated)
move C:\mnt\usb\notify-email.exe C:\ProgramData\crowdsec\plugins\
icacls "C:\ProgramData\crowdsec\plugins\notify-email.exe" /inheritance:r /grant Administrators:F /grant SYSTEM:F /grant "NT AUTHORITY\SYSTEM":RX
Defensive patterns

Strategy: validation

Validate before calling

func hasDACL(path string) (bool, error) {
	sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION)
	if err != nil {
		return false, err
	}
	dacl, _, err := sd.DACL()
	return dacl != nil, err
}

Prevention

When it happens

Trigger: Calling CheckPerms on a plugin whose security descriptor has a NULL DACL — the file has no ACL entries, or the file sits on a filesystem without NT ACL support (FAT32/exFAT, some network shares) so GetNamedSecurityInfo returns no DACL.

Common situations: Plugins copied to/from FAT32 USB media or non-NTFS mounts; files shared over network filesystems without ACL propagation; manually stripped ACLs (`icacls /remove` all entries); container bind-mounts that drop ACL information.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/bb2785e26afe3c39. Report an issue: GitHub.