crowdsecurity/crowdsec · error

while getting owner security info

Error message

while getting owner security info: %w

What it means

CheckPerms queries the plugin file's security descriptor with windows.GetNamedSecurityInfo(SE_FILE_OBJECT, OWNER|DACL), the Win32 GetNamedSecurityInfo API. This error wraps a failure of that call, meaning Windows could not return the object's owner and DACL information — typically an OS error like ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND, or ERROR_INVALID_OWNER.

Solutions

  1. Verify the plugin file still exists at the path and is on an NTFS volume that supports ACLs
  2. Run crowdsec under an account with READ_CONTROL access to the plugin directory, or fix the ACLs on the plugin files
  3. Check antivirus/EDR software isn't blocking security-descriptor queries on the plugin path
  4. Read the wrapped %w Win32 error to distinguish not-found vs access-denied and act accordingly

Example fix

// before
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)
}
// after
if _, err := os.Stat(path); err != nil {
	return fmt.Errorf("plugin vanished before security check: %w", err)
}
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 for %s: %w", path, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if fi, err := os.Stat(path); err != nil {
	return fmt.Errorf("plugin missing: %w", err)
} else if fi.Mode()&os.ModeType != 0 {
	return errors.New("path is not a regular file")
}

Try / catch

err := CheckPerms(pluginPath)
var errno windows.Errno
if err != nil && errors.As(err, &errno) && errno == windows.ERROR_ACCESS_DENIED {
	return fmt.Errorf("grant READ_CONTROL on %s to the crowdsec account", pluginPath)
}

Prevention

When it happens

Trigger: Calling CheckPerms on a path where GetNamedSecurityInfo fails: the file was deleted between the earlier os.Stat and this call; the caller lacks READ_CONTROL on the file; the path is malformed or on a filesystem that doesn't support NT security descriptors (FAT32, some network shares).

Common situations: Plugin directory on a FAT32/exFAT volume or network share without NT ACL support; antivirus or EDR blocking security-descriptor queries; race where the plugin binary is replaced/removed while crowdsec scans; crowdsec run by an account with no read-control access to the plugin file.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at pkg/csplugin/utils_windows.go:84

	adminSid, err := windows.CreateWellKnownSid(windows.WELL_KNOWN_SID_TYPE(windows.WinBuiltinAdministratorsSid))
	if err != nil {
		return fmt.Errorf("while creating built-in Administrators well known sid: %w", err)
	}

	currentUser, err := user.Current()
	if err != nil {
		return fmt.Errorf("while getting current user: %w", err)
	}

	currentUserSid, _, _, err := windows.LookupSID("", currentUser.Username)

	if err != nil {
		return fmt.Errorf("while looking up current user sid: %w", err)
	}

	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 {

View on GitHub (pinned to 909b515798)