Skip to content

Java data flow: access paths longer than five contents are silently dropped; the default accessPathLimit is not stated in the data-flow guides #23042

Open

Description

@yuan2li

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:

public class Nested {
    void handle(javax.servlet.http.HttpServletRequest req) throws java.io.IOException {
        java.util.List c0 = new java.util.ArrayList();
        c0.add(req.getParameter("cmd"));
        java.util.List c1 = new java.util.ArrayList(); c1.add(c0);
        // ... c2 to c4 wrap the previous list the same way ...
        java.util.List c5 = new java.util.ArrayList(); c5.add(c4);   // six lists, c0 to c5
        java.util.List cur = 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

  1. sam-robson commented on Nov 6, 2026

    @sam-robson
    Contributor

    Thanks for the report @yuan2li . We'll look into this and get back to you.

    Edit: A contribution would be most welcome 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions