Skip to content

[Feature Request] Graph Engine: taint-tracking sinks for SSRF (HttpRequest.setEndpoint), resource injection, and dynamic type reflection #2078

Description

@temadu

Product Area

An Engine

Your Need or Problem

We run Code Analyzer across customer Apex to report security defects, and we have four
CodeScan-equivalent conditions that we cannot express in any bundled engine, all for the same
underlying reason: they are taint-tracking questions, not syntactic ones.

Condition Why a syntactic rule cannot decide it
Server-Side Request Forgery The defect is user-controlled input reaching a callout endpoint across method boundaries. HttpRequest.setEndpoint(...) is trivially greppable; whether its argument is attacker-controlled is not.
Resource injection Same shape — untrusted input reaching a resource identifier.
Dynamic type reflection from untrusted input Type.forName(...) is lexically visible, but flagging every dynamic instantiation fires on the standard factory pattern, which is idiomatic and correct.
Reliance on the spoofable Referer header Reading the header is visible; the defect is using it for a security or logic decision. Reading it to log is not a defect, and the two are indistinguishable without dataflow to a branch condition.

In each case the naive lexical rule is not merely imprecise, it is actively harmful — it would
tell customers that correct, conventional Apex is a vulnerability. We are not willing to ship that,
so today we report nothing for these four conditions.

We checked the alternatives before filing. None of these rule names exists in any bundled engine
(ServerSideRequestForgery, ResourceInjection, HotspotTypeReflection, AvoidHttpReferer), and
they are not expressible as PMD custom XPath rules, because XPath over the Apex AST cannot follow a
value across a method boundary.

Your Desired Solution

Graph Engine already does the hard part. ApexFlsViolationRule performs path-based dataflow
analysis over the Apex call graph — it tracks a value to a sink and reasons about whether it is
guarded. What is missing is not a dataflow engine; it is a taint source/sink vocabulary layered
on the one that already exists
.

Concretely, in rough priority order:

  1. An SSRF rule with a taint sink on HttpRequest.setEndpoint(String), with the standard
    request-derived taint sources (ApexPages.currentPage().getParameters().get(...),
    RestRequest params/body/headers, @AuraEnabled and @InvocableMethod parameters, Visualforce
    controller getters/setters). This single rule is the bulk of the value for us.
  2. A resource-injection rule reusing the same source set against resource-identifier sinks.
  3. A dynamic-reflection rule with Type.forName(...) as the sink, which is only reportable
    with taint information — without it, the factory-pattern false positives make it unusable.

The most broadly useful version of this would be a configurable sink list — letting users
declare additional taint sinks (and trust boundaries/sanitizers) in the Code Analyzer config file,
the way engines.pmd.custom_rulesets already lets us supply custom PMD rules. That would let the
community add sinks without an engine release for each one, and would cover conditions you have not
thought of. If a configurable sink list is too large a change, the three named rules above would
still close most of this gap for us.

Alternatives Considered

  • PMD custom rulesets (engines.pmd.custom_rulesets) — confirmed present and working, and it
    is the right home for most of our other gaps. It cannot do these four: XPath over the AST has no
    interprocedural view.
  • Lexical/regex rules — rejected. For Type.forName this fires on the standard factory
    pattern; for Referer it fires on legitimate logging. Both would report correct code as a
    defect.
  • A read-only inventory variant ("here is every dynamic instantiation, you decide") — rejected
    as a security finding, since a finding that is true of nearly every codebase is not actionable.

Additional Context (Screenshots, Files, etc)

On the Referer item specifically, we want to be straight with you about our own evidence: across
the Apex corpus we currently scan, the string referer occurs zero times. So we can show you
the reasoning for why it needs dataflow, but we cannot show you a real-world hit, and we would
rank it well below the SSRF sink. We are including it only because it is the same engine capability
and we would rather file one accurate request than four overlapping ones.

The first three we do consider real and recurring.

Workaround

None that we are willing to ship. We currently report nothing for all four conditions rather than
emit findings we know would be wrong. Our internal catalog records them as blocked on this upstream
capability, which is why we are asking rather than building.

Urgency

Moderate

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions