puppetlabs/puppet · error · Puppet::Util::Windows::Error

Failed to adjust process privileges

Error message

Failed to adjust process privileges

What it means

Raised when AdjustTokenPrivileges returns FALSE while with_privilege tries to enable SE_BACKUP_NAME or SE_RESTORE_NAME in the process token. The function only returns FALSE for hard failures (invalid handle, invalid LUID); note the classic trap that it can also 'succeed' while not assigning the privilege, which this check does not catch. It fires whenever Puppet needs backup/restore privileges to read or write security descriptors.

Source

Thrown at lib/puppet/util/windows/security.rb:572

    Puppet::Util::Windows::Process.with_process_token(TOKEN_ADJUST_PRIVILEGES) do |token|
      Puppet::Util::Windows::Process.lookup_privilege_value(privilege) do |luid|
        FFI::MemoryPointer.new(Puppet::Util::Windows::Process::LUID_AND_ATTRIBUTES.size) do |luid_and_attributes_ptr|
          # allocate unmanaged memory for structs that we clean up afterwards
          luid_and_attributes = Puppet::Util::Windows::Process::LUID_AND_ATTRIBUTES.new(luid_and_attributes_ptr)
          luid_and_attributes[:Luid] = luid
          luid_and_attributes[:Attributes] = enable ? SE_PRIVILEGE_ENABLED : 0

          FFI::MemoryPointer.new(Puppet::Util::Windows::Process::TOKEN_PRIVILEGES.size) do |token_privileges_ptr|
            token_privileges = Puppet::Util::Windows::Process::TOKEN_PRIVILEGES.new(token_privileges_ptr)
            token_privileges[:PrivilegeCount] = 1
            token_privileges[:Privileges][0] = luid_and_attributes

            # size is correct given we only have 1 LUID, otherwise would be:
            # [:PrivilegeCount].size + [:PrivilegeCount] * LUID_AND_ATTRIBUTES.size
            if AdjustTokenPrivileges(token, FFI::WIN32_FALSE,
                                     token_privileges, token_privileges.size,
                                     FFI::MemoryPointer::NULL, FFI::MemoryPointer::NULL) == FFI::WIN32_FALSE
              raise Puppet::Util::Windows::Error, _("Failed to adjust process privileges")
            end
          end
        end
      end
    end

    # token / luid structs freed by this point, so return true as nothing raised
    true
  end

  def get_security_descriptor(path)
    sd = nil

    with_privilege(SE_BACKUP_NAME) do
      open_file(path, READ_CONTROL) do |handle|
        FFI::MemoryPointer.new(:pointer, 1) do |owner_sid_ptr_ptr|
          FFI::MemoryPointer.new(:pointer, 1) do |group_sid_ptr_ptr|
            FFI::MemoryPointer.new(:pointer, 1) do |dacl_ptr_ptr|

View on GitHub (pinned to e227c27540)

Solutions

  1. Run the process elevated as local Administrator (whoami /priv should list SeBackupPrivilege and SeRestorePrivilege)
  2. If a service account is used, grant it the 'Back up files and directories' and 'Restore files and directories' user rights via Local Security Policy
  3. Check e.code on the error for the concrete Win32 reason
  4. Verify privileges at startup with whoami /priv before attempting ACL work
Defensive patterns

Strategy: try-catch

Try / catch

begin
  Puppet::Util::Windows::Security.set_security_descriptor(path, sd)
rescue Puppet::Util::Windows::Error => e
  if e.message.include?('Failed to adjust process privileges')
    raise Puppet::Error, 'ACL write needs an elevated token with SeBackupPrivilege/SeRestorePrivilege'
  end
  raise
end

Prevention

When it happens

Trigger: Any set_security_descriptor / get_security_descriptor path that calls with_privilege, when OpenProcessToken or LookupPrivilegeValue produced an unusable handle/LUID, or the FFI call itself fails. Most often seen when the process token simply does not possess SeBackupPrivilege/SeRestorePrivilege in a degraded token.

Common situations: Running Puppet or custom Ruby code from a non-elevated shell on UAC systems (filtered token lacks the privileges); running as a service account without the required user rights; scripts that drop privileges before managing ACLs.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/b17c0dc507de829e. Report an issue: GitHub.