java-native-access/jna · error · IllegalArgumentException

SACL is invalid

Error message

SACL is invalid

What it means

When setSACL is requested and a SACL is present, Advapi32Util validates it with Advapi32.IsValidAcl; on failure it throws IllegalArgumentException ('SACL is invalid'), preventing a corrupt audit ACL from being written to the object.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java:2901

                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain group");
            if (!Advapi32.INSTANCE.IsValidSid(psidGroup))
                throw new IllegalArgumentException("Group PSID is invalid");
            infoType |= GROUP_SECURITY_INFORMATION;
        }

        if (setDACL) {
            if (dacl == null)
                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain DACL");
            if (!Advapi32.INSTANCE.IsValidAcl(dacl.getPointer()))
                throw new IllegalArgumentException("DACL is invalid");
            infoType |= DACL_SECURITY_INFORMATION;
        }

        if (setSACL) {
            if (sacl == null)
                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain SACL");
            if (!Advapi32.INSTANCE.IsValidAcl(sacl.getPointer()))
                throw new IllegalArgumentException("SACL is invalid");
            infoType |= SACL_SECURITY_INFORMATION;
        }

        /*
         * Control bits SE_DACL_PROTECTED/SE_SACL_PROTECTED indicate the *ACL is protected. The *ACL_SECURITY_INFORMATION flags
         * are meta flags for SetNamedSecurityInfo and are not stored in the SD.  If either *ACLProtectedStatus is set,
         * get the current status from the securityDescriptor and apply as such, otherwise the ACL remains at its default.
        */
        if (setDACLProtectedStatus) {
            if ((securityDescriptor.Control & SE_DACL_PROTECTED) != 0) {
                infoType |= PROTECTED_DACL_SECURITY_INFORMATION;
            }
            else if ((securityDescriptor.Control & SE_DACL_PROTECTED) == 0) {
                infoType |= UNPROTECTED_DACL_SECURITY_INFORMATION;
            }
        }

        if (setSACLProtectedStatus) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Pre-check with Advapi32.INSTANCE.IsValidAcl(sacl.getPointer()) and rebuild if false.
  2. Rebuild the SACL programmatically (ACL/ACE structures via JNA) instead of reusing suspect bytes.
  3. Re-extract the SACL from the source object with SE_SECURITY_NAME privilege held.
  4. Skip the SACL component (setSACL=false) if audit configuration is not essential.

Example fix

// before
Advapi32Util.setSecurityDescriptorComponents(sd, true, true, true, true, false, false);
// after
if (sd.getSystemACL() != null && Advapi32.INSTANCE.IsValidAcl(sd.getSystemACL().getPointer())) {
    Advapi32Util.setSecurityDescriptorComponents(sd, true, true, true, true, false, false);
}
Defensive patterns

Strategy: validation

Validate before calling

ACL sacl = securityDescriptor.getSystemACL();
if (sacl == null || !Advapi32.INSTANCE.IsValidAcl(sacl.getPointer())) {
    throw new IllegalStateException("SACL missing or invalid");
}

Type guard

boolean isValidSACL(SECURITY_DESCRIPTOR_RELATIVE sd) {
    ACL a = sd.getSystemACL();
    return a != null && Advapi32.INSTANCE.IsValidAcl(a.getPointer());
}

Try / catch

try {
    Advapi32Util.setSecurityDescriptorComponents(sd, false, false, false, true, false, false);
} catch (IllegalArgumentException e) {
    log.error("SACL rejected: " + e.getMessage());
}

Prevention

When it happens

Trigger: setSACL=true with a malformed SACL structure: bad header/revision, AclSize inconsistent with the buffer, corrupted SYSTEM_AUDIT ACEs, or a partially parsed ACL from a truncated descriptor.

Common situations: Hand-built audit ACEs with wrong sizes; descriptor buffers edited without adjusting SACL offsets; SACL copied across descriptors of different layouts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/397cd62e8330dc42. Report an issue: GitHub.