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
- Pre-check with Advapi32.INSTANCE.IsValidAcl(sacl.getPointer()) and rebuild if false.
- Rebuild the SACL programmatically (ACL/ACE structures via JNA) instead of reusing suspect bytes.
- Re-extract the SACL from the source object with SE_SECURITY_NAME privilege held.
- 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
- Validate SACLs with Advapi32.INSTANCE.IsValidAcl before applying.
- Rebuild audit ACLs programmatically rather than copying raw bytes between descriptors.
- Re-extract SACLs from the source with proper privileges if validation fails.
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
- DACL is invalid
- SECURITY_DESCRIPTOR_RELATIVE does not contain owner
- Owner PSID is invalid
- SECURITY_DESCRIPTOR_RELATIVE does not contain group
- Group PSID is invalid
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/397cd62e8330dc42.
Report an issue: GitHub.