crowdsecurity/crowdsec · error

while duplicating token: %w

Error message

while duplicating token: %w

What it means

This error wraps a failure from windows.DuplicateTokenEx, which clones the crowdsec process token into a new primary token that will be assigned to the plugin subprocess. It is thrown when the OS rejects the duplication — usually because the source token lacks the rights needed to duplicate it (TOKEN_DUPLICATE) or the caller lacks SeAssignPrimaryTokenPrivilege context.

Source

Thrown at pkg/csplugin/utils_windows.go:174

}

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()

	err = windows.DuplicateTokenEx(procToken, 0, nil, windows.SecurityImpersonation,
		windows.TokenPrimary, &token)
	if err != nil {
		return nil, fmt.Errorf("while duplicating token: %w", err)
	}

	//Remove all privileges from the token

	err = windows.AdjustTokenPrivileges(token, true, nil, 0, nil, nil)

	if err != nil {
		return nil, fmt.Errorf("while adjusting token privileges: %w", err)
	}

	//Run the plugin as a medium integrity level process
	//For some reasons, low level integrity don't work, the plugin and crowdsec cannot communicate over the TCP socket
	sid, err := windows.CreateWellKnownSid(windows.WELL_KNOWN_SID_TYPE(windows.WinMediumLabelSid))
	if err != nil {
		return nil, err
	}

	tml := &windows.Tokenmandatorylabel{}

View on GitHub (pinned to 909b515798)

Solutions

  1. Ensure crowdsec runs as an account allowed to duplicate its own token (LocalSystem/admin service account).
  2. Check EDR/AV logs for blocked token-duplication calls and whitelist the crowdsec binary.
  3. Verify OpenProcessToken was called with TOKEN_DUPLICATE included in the access mask (it is by default; a modified build may omit it).
  4. Test DuplicateTokenEx in isolation with a small Go probe to capture the exact Win32 error code.
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the source token carries TOKEN_DUPLICATE before duplicating
if err := windows.OpenProcessToken(proc, windows.TOKEN_DUPLICATE|windows.TOKEN_QUERY, &procToken); err != nil {
    return fmt.Errorf("cannot obtain duplicable token: %w", err)
}

Try / catch

cmd, err := broker.CreateCmd(ctx, binaryPath)
if err != nil {
    var errno syscall.Errno
    if errors.As(err, &errno) && errno == windows.ERROR_ACCESS_DENIED {
        log.Error("token duplication denied; check EDR policy and service account privileges")
    }
    return err
}

Prevention

When it happens

Trigger: getProcessAttr, called from PluginBroker.CreateCmd when launching a plugin on Windows, fails at DuplicateTokenEx(procToken, 0, nil, SecurityImpersonation, TokenPrimary, &token) — e.g. the token was opened without TOKEN_DUPLICATE, or the security descriptor prevents duplication.

Common situations: EDR/security software blocking DuplicateTokenEx; running under an account with a restricted token; attempting duplication in an environment (e.g. some service contexts, containers, or jobs) where token duplication is denied.

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