pam_usb's pusb_conf_parse() in src/conf.c calls xmlReadFile() to load the configuration file.
Original vulnerability (flags=0): No parser flags were passed to xmlReadFile(), allowing libxml2 to process external entity references without restriction. This permitted both network-URI (http://, ftp://) and local file:// entity loads at XML parse time from the context of the authenticating process (setuid, running as root in sudo/su contexts).
Incomplete/incorrect initial fix (#385): The fix passed XML_PARSE_NONET | XML_PARSE_NOENT to xmlReadFile(). XML_PARSE_NONET correctly blocks network-URI entity fetches. However, XML_PARSE_NOENT — defined by libxml2 as "substitute entities" — enables entity substitution, not prevents it. The flag was added under the mistaken belief that it would cause NONET-blocked references to expand to empty content. In reality it has no bearing on how blocked entities are handled, and actively enables substitution of file:// entities that XML_PARSE_NONET does not block. The accompanying code comment explaining this reasoning was therefore factually incorrect. This was pointed out by Nick Wellnhof (ex-libxml2 maintainer) after the fix was merged.
Correct fix (#442): Pass only XML_PARSE_NONET. Without XML_PARSE_NOENT, entity references are never substituted into the parsed tree — they remain as inert entity-reference nodes that XPath text() queries do not yield. Network entities are blocked by NONET; file:// entities are neutralised by the absence of NOENT. Normal pamusb.conf files (generated by pamusb-conf) never contain entity declarations, so removing the flag has no impact on real-world operation.
Practical exploitability: Injecting an XXE payload requires write access to /etc/pamusb.conf, which is root-owned. An attacker with that access has already achieved full system compromise. The impact is defence-in-depth: pam_usb runs in setuid contexts and must not make unexpected outbound connections or file reads driven by config content.
pam_usb's
pusb_conf_parse()insrc/conf.ccallsxmlReadFile()to load the configuration file.Original vulnerability (flags=0): No parser flags were passed to
xmlReadFile(), allowing libxml2 to process external entity references without restriction. This permitted both network-URI (http://, ftp://) and local file:// entity loads at XML parse time from the context of the authenticating process (setuid, running as root in sudo/su contexts).Incomplete/incorrect initial fix (#385): The fix passed
XML_PARSE_NONET | XML_PARSE_NOENTtoxmlReadFile().XML_PARSE_NONETcorrectly blocks network-URI entity fetches. However,XML_PARSE_NOENT— defined by libxml2 as "substitute entities" — enables entity substitution, not prevents it. The flag was added under the mistaken belief that it would cause NONET-blocked references to expand to empty content. In reality it has no bearing on how blocked entities are handled, and actively enables substitution of file:// entities thatXML_PARSE_NONETdoes not block. The accompanying code comment explaining this reasoning was therefore factually incorrect. This was pointed out by Nick Wellnhof (ex-libxml2 maintainer) after the fix was merged.Correct fix (#442): Pass only
XML_PARSE_NONET. WithoutXML_PARSE_NOENT, entity references are never substituted into the parsed tree — they remain as inert entity-reference nodes that XPathtext()queries do not yield. Network entities are blocked by NONET; file:// entities are neutralised by the absence of NOENT. Normal pamusb.conf files (generated bypamusb-conf) never contain entity declarations, so removing the flag has no impact on real-world operation.Practical exploitability: Injecting an XXE payload requires write access to
/etc/pamusb.conf, which is root-owned. An attacker with that access has already achieved full system compromise. The impact is defence-in-depth: pam_usb runs in setuid contexts and must not make unexpected outbound connections or file reads driven by config content.