Conversation
Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
|
QHelp previews: rust/ql/src/queries/security/CWE-611/Xxe.qhelpXML external entity expansionParsing XML input with external entity (XXE) expansion enabled while the input is controlled by a user can lead to a variety of attacks. An attacker who controls the XML input may be able to use an XML external entity declaration to read the contents of arbitrary files from the server's file system, perform server-side request forgery (SSRF), or perform denial-of-service attacks. The Rust RecommendationDo not enable ExampleIn the following example, the program reads an XML document supplied by the user and parses it with external entity expansion enabled: use libxml::bindings::{xmlReadMemory, XML_PARSE_NOENT};
use std::ffi::CString;
fn parse_user_xml(user_input: &str) {
let c_input = CString::new(user_input).unwrap();
// BAD: external entity expansion is enabled via XML_PARSE_NOENT
unsafe {
xmlReadMemory(
c_input.as_ptr(),
c_input.as_bytes().len() as i32,
std::ptr::null(),
std::ptr::null(),
XML_PARSE_NOENT as i32,
);
}
}The following example shows a corrected version that parses with safe options: use libxml::bindings::xmlReadMemory;
use std::ffi::CString;
fn parse_user_xml(user_input: &str) {
let c_input = CString::new(user_input).unwrap();
// GOOD: safe options (0) disable external entity expansion
unsafe {
xmlReadMemory(
c_input.as_ptr(),
c_input.as_bytes().len() as i32,
std::ptr::null(),
std::ptr::null(),
0,
);
}
}References
|
Adds a new
@precision high/@severity errorpath-problem query detecting XML External Entity (XXE) vulnerabilities in Rust code that uses thelibxmlcrate (bindings to C's libxml2). Pure-Rust XML crates are safe by default; onlylibxmlis a realistic target viaXML_PARSE_NOENT(value 2) orXML_PARSE_DTDLOAD(value 4).Query logic
ActiveThreatModelSource(network, env, stdin, etc.)xmlReadFile,xmlReadMemory,xmlReadDoc,xmlReadFd,xmlCtxtReadFile,xmlCtxtReadDoc,xmlCtxtReadFd,xmlCtxtReadMemory,xmlReadIO,xmlCtxtReadIO,xmlParseInNodeContextFiles
rust/ql/lib/codeql/rust/security/XxeExtensions.qll— sources, sinks, barriersrust/ql/src/queries/security/CWE-611/Xxe.ql— main query (CWE-611, CWE-776, CWE-827)rust/ql/src/queries/security/CWE-611/Xxe.qhelp— documentation and examplesrust/ql/test/query-tests/security/CWE-611/— test suite with stub libxml2 functions covering bad/good casesrust/ql/src/change-notes/2026-02-20-xxe.mdNote:
xmlCtxtUseOptionsis intentionally excluded — it configures an existing parser context and has no XML content argument, so treating it as a sink would produce false positives.Original prompt
Create a new query for XXE ("XML eXternal Entities") vulnerabilities in Rust. This will provide coverage for CWE-611 and OWASP A05.
See issue: https://github.com/github/codeql-c-team/issues/2865
Background
XXE vulnerabilities occur when an XML parser is configured to process external entity references while parsing user-controlled XML input. In the Rust ecosystem, most pure-Rust XML crates (quick-xml, xml-rs, roxmltree, etc.) do NOT support external entity expansion and are safe by default. The only realistic target is the
libxmlcrate (Rust bindings to C's libxml2), which can be configured to expand external entities via parsing options likeXML_PARSE_NOENTandXML_PARSE_DTDLOAD.MRVA analysis of the top 1000 projects confirms this is very rare in practice - only one project even defines these constants and doesn't use them. Therefore, keep the implementation minimal and focused on just the
libxmlbindings.Plan (in order)
Step 1: Write test cases FIRST
Create test Rust code in
rust/ql/test/query-tests/security/CWE-611/that exercises thelibxml2bindings:xmlReadFile,xmlReadMemory,xmlReadDoc,xmlCtxtReadFile,xmlCtxtReadDoc,xmlCtxtReadMemory,xmlReadFd,xmlCtxtReadFd,xmlReadIO,xmlCtxtUseOptions) withXML_PARSE_NOENTorXML_PARSE_DTDLOADin the options, where the XML input comes from a remote/taint source. These should produce alerts.0or safe options (no entity expansion enabled) — should NOT produce alerts.Cargo.tomlfor the test project.$ Alert,$ Source=, sink annotations) following the established pattern in other Rust security query tests (seerust/ql/test/query-tests/security/CWE-022/for the pattern).Step 2: Add the XXE Extensions library
Create
rust/ql/lib/codeql/rust/security/XxeExtensions.qllfollowing the established pattern used by other Rust security queries (e.g.,TaintedPathExtensions.qll,CleartextTransmissionExtensions.qll):Source,Sink, andBarrier.Sourceshould default toActiveThreatModelSource(fromcodeql.rust.Concepts).Sinkshould model the XML input argument of libxml2 parsing functions whenXML_PARSE_NOENTorXML_PARSE_DTDLOADappears in the options argument.cpp/ql/src/Security/CWE/CWE-611/Libxml2.qlland Swift model atswift/ql/lib/codeql/swift/frameworks/Xml/Libxml2.qllfor the list of functions and which argument positions hold the XML input vs options. The key functions and their options argument positions are:xmlCtxtUseOptions— options at arg 1xmlReadFile— options at arg 2xmlCtxtReadFile,xmlParseInNodeContext,xmlReadDoc,xmlReadFd— options at arg 3xmlCtxtReadDoc,xmlCtxtReadFd,xmlReadMemory— options at arg 4xmlCtxtReadMemory,xmlReadIO— options at arg 5xmlCtxtReadIO— options at arg 6xmlCtxt*variants).XML_PARSE_NOENT(value 2) orXML_PARSE_DTDLOAD(value 4), which enable external entity processing.Step 3: Write the query
Create
rust/ql/src/queries/security/CWE-611/Xxe.ql:@id rust/xxe@kind path-problem@problem.severity error@security-severity 9.1@precision highsecurity,external/cwe/cwe-611,external/cwe/cwe-776,external/cwe/cwe-827"XML parsing depends on a $@ without guarding against external entity expansion."Step 4: Documentation
rust/ql/src/queries/security/CWE-611/Xxe.qhelpwith a description of XXE, risk explanation, and recommendation.rust/ql/src/queries/security/CWE-611/examples/.rust/ql/src/change-notes/for the new query.Reference implementations to study
ruby/ql/src/queries/security/cwe-611/Xxe.qlandruby/ql/lib/codeql/ruby/frameworks/XmlParsing.qllswift/ql/src/queries/Security/CWE-611/XXE.qlandswift/ql/lib/codeql/swift/security/XXEExtensions.qlland `swift/ql/lib/codeql/swift/frameworks/Xml/Libxml2.qll...This pull request was created from Copilot chat.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.