crowdsecurity/crowdsec · error

only SYSTEM, Administrators or the user currently running cr

Error message

only SYSTEM, Administrators or the user currently running crowdsec can have more than read/execute on plugin %s

What it means

This is the final policy enforcement in CheckPerms: for every allow-ACE whose SID is not SYSTEM, BUILTIN\Administrators, or the crowdsec process user, the code masks the AccessMask with the inverse of FILE_GENERIC_READ|FILE_GENERIC_EXECUTE; any extra bits (e.g. write/delete) mean that account could modify the plugin binary, so CheckPerms rejects it. It exists because a world-writable plugin could be swapped for malicious code executed by crowdsec.

Source

Thrown at pkg/csplugin/utils_windows.go:151

		if ace.AceType == ACCESS_DENIED_ACE_TYPE {
			continue
		}
		aceSid := (*windows.SID)(unsafe.Pointer(&ace.SidStart))

		if aceSid.Equals(systemSid) || aceSid.Equals(adminSid) {
			log.Debugf("Not checking permission for well-known SID %s", aceSid.String())
			continue
		}

		if aceSid.Equals(currentUserSid) {
			log.Debugf("Not checking permission for current user %s", currentUser.Username)
			continue
		}

		log.Debugf("Checking permission for SID %s", aceSid.String())
		denyMask := ^(windows.FILE_GENERIC_READ | windows.FILE_GENERIC_EXECUTE)
		if ace.AccessMask&uint32(denyMask) != 0 {
			return fmt.Errorf("only SYSTEM, Administrators or the user currently running crowdsec can have more than read/execute on plugin %s", path)
		}
	}

	return nil
}

func getProcessAttr() (*windows.SysProcAttr, error) {
	var procToken, token windows.Token

	proc := windows.CurrentProcess()
	defer windows.CloseHandle(proc)

	err := windows.OpenProcessToken(proc, windows.TOKEN_DUPLICATE|windows.TOKEN_ADJUST_DEFAULT|
		windows.TOKEN_QUERY|windows.TOKEN_ASSIGN_PRIMARY|windows.TOKEN_ADJUST_GROUPS|windows.TOKEN_ADJUST_PRIVILEGES, &procToken)
	if err != nil {
		return nil, fmt.Errorf("while opening process token: %w", err)
	}
	defer procToken.Close()

View on GitHub (pinned to 909b515798)

Solutions

  1. Restrict the plugin's ACL so non-privileged accounts get only read/execute: `icacls <plugin> /inheritance:r /grant Administrators:F /grant SYSTEM:F /grant Users:RX`
  2. Fix the parent directory's inherited permissions so plugins don't inherit broad write ACEs
  3. Move the plugins out of any world-writable directory into the standard install path
  4. Audit with `icacls <plugin>` and remove ACEs granting Users/Everyone Modify or Full Control

Example fix

// before
# Everyone has Modify on the plugin → rejected
icacls notify-email.exe
Everyone:(M)
// after
# elevated shell
icacls notify-email.exe /inheritance:r /grant Administrators:F /grant SYSTEM:F /grant Users:RX
Defensive patterns

Strategy: validation

Validate before calling

func pluginACLEntriesAreReadExecute(path string, trusted map[string]bool) error {
	sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION)
	if err != nil {
		return err
	}
	dacl, _, err := sd.DACL()
	if err != nil || dacl == nil {
		return errors.New("DACL missing")
	}
	// entries granting non-trusted SIDs more than RX will be rejected by CheckPerms
	return nil
}

Prevention

When it happens

Trigger: Calling CheckPerms on a plugin whose DACL grants a non-whitelisted account more than read/execute — e.g. ACEs granting Users or Everyone Modify/Full Control, or inherited broad-write ACEs on the plugin directory.

Common situations: Plugin directory shared with group write access for convenience; inherited permissions from a loosely-secured parent folder; plugins deployed by a tool that grants 'Users: Modify'; files in a temp/downloads folder with permissive default ACLs.

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/fe97dabe2016ffcd. Report an issue: GitHub.