You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Java data flow: access paths longer than five contents are silently dropped; the default accessPathLimit is not stated in the data-flow guides #23042
CodeQL CLI 2.27.4 (release binary) on macOS 26.6 (arm64), with the bundled codeql/java-queries 1.12.0 (security-extended), codeql/java-all 9.3.4 and codeql/dataflow 2.1.17.
Taint stored in nested lists is found up to five levels of nesting and lost at six:
publicclassNested {
voidhandle(javax.servlet.http.HttpServletRequestreq) throwsjava.io.IOException {
java.util.Listc0 = newjava.util.ArrayList();
c0.add(req.getParameter("cmd"));
java.util.Listc1 = newjava.util.ArrayList(); c1.add(c0);
// ... c2 to c4 wrap the previous list the same way ...java.util.Listc5 = newjava.util.ArrayList(); c5.add(c4); // six lists, c0 to c5java.util.Listcur = c5;
cur = (java.util.List) cur.get(0); // repeated five times, back down to c0// ...Runtime.getRuntime().exec((String) cur.get(0));
}
}
With five nested lists the command injection is reported. With six it is not.
The same cut-off appears with Maps.
A chain of getters on nested objects is cut off the same way: b.getInner().getInner().getInner().getInner().getVal() is found, and one more getInner() is not. The same fields read directly (b.inner.inner.inner.inner.inner.val) are found at least up to eight levels.
The cut-off is the shared library's default accessPathLimit(), which is 5 (codeql/dataflow/DataFlow.qll, around line 299, in 2.1.17). Java does not override it.
What is missing.
The standard-library reference names accessPathLimit but gives no value.
Neither the "Analyzing data flow in Java" guide nor the query help states that paths beyond five contents are dropped.
Nothing in the results says a path was dropped, so a user sees a false negative with no hint. It is also not obvious that a getter chain counts toward the limit while direct field reads do not.
Suggestion. State the default and its effect in the data-flow documentation, together with how to raise it for a custom configuration
(ConfigSig::accessPathLimit, from #15867). Raising it currently has no effect on 2.27.x, which I reported separately in #23041.
Proposed change. The attached diff adds two things to docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst:
accessPathLimit in the list of optional configuration predicates;
a short "Access path limit" section. It explains access paths, states the default of 5 and that longer flows are dropped without a warning, and shows int accessPathLimit() { result = 8 } in a ConfigSig.
I checked that text with a small taint query. With the default, the five-list program is found and the six-list program is not. With accessPathLimit() = 8 in the configuration, the six-list program should be found, as it is on 2.26.2, but on 2.27.4 it is not (#23041). The text describes the intended behaviour.
Since the limit lives in the shared library, the same section could go into the other languages' guides. I will open a PR with this change and link it here. (codeql-docs-access-path-limit.patch)
Activity
sam-robson commentedon Nov 6, 2026
Thanks for the report @yuan2li .
We'll look into this and get back to you.Edit: A contribution would be most welcome 👍🏻