crowdsecurity/crowdsec · error

plugin at %s is not owned by SYSTEM, Administrators or by cu

Error message

plugin at %s is not owned by SYSTEM, Administrators or by current user, but by %s

What it means

This is a deliberate security-policy rejection, not a system failure. CheckPerms verifies the plugin binary's owner is SYSTEM, BUILTIN\Administrators, or the user running crowdsec; if a regular/unprivileged account owns the file, any such account could silently replace the binary with malicious code that crowdsec would execute. The error names the offending owner SID.

Source

Thrown at pkg/csplugin/utils_windows.go:98

	}

	sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION)
	if err != nil {
		return fmt.Errorf("while getting owner security info: %w", err)
	}
	if !sd.IsValid() {
		return errors.New("security descriptor is invalid")
	}
	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

View on GitHub (pinned to 909b515798)

Solutions

  1. Take ownership as an administrator: `icacls <plugin> /setowner Administrators` or takeown.exe
  2. Reinstall the plugins using an elevated installer/process so files are owned by Administrators
  3. Move plugins to the standard install directory and set ownership there
  4. Verify with `icacls <plugin>` that the owner is SYSTEM, Administrators, or crowdsec's service account

Example fix

// before
# plugin copied by user 'dev' → owner dev
C:\ProgramData\crowdsec\plugins> icacls notify-email.exe
... Owner: CORP\dev
// after
# run elevated
icacls "C:\ProgramData\crowdsec\plugins\notify-email.exe" /setowner Administrators
Defensive patterns

Strategy: validation

Validate before calling

func pluginOwnerIsTrusted(path string) error {
	sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION)
	if err != nil {
		return err
	}
	owner, _, err := sd.Owner()
	if err != nil {
		return err
	}
	s, err := owner.String()
	if err != nil {
		return err
	}
	switch s {
	case "S-1-5-18", "S-1-5-32-544": // SYSTEM, Administrators
		return nil
	}
	return fmt.Errorf("untrusted owner %s on %s", s, path)
}

Prevention

When it happens

Trigger: Calling CheckPerms (via pluginIsValid, during plugin discovery) on a plugin binary whose NTFS owner is a normal user account — e.g. a plugin installed by hand by a non-admin user, extracted from an archive preserving an odd owner, or copied onto the machine by a non-elevated process.

Common situations: Plugins unzipped by a logged-in user instead of an elevated installer; plugins deployed by CI/CD or scripts running as a service account different from crowdsec's; files restored from backups with rewritten ownership; plugins in a user-profile folder rather than a system plugin directory.

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