Skip to main content

SFGE-gap pack

Salesforce's official Apex SAST stack ships as the Code Analyzer Graph Engine ("SFGE"). The engine is solid on the constructs it covers, but the maintainers explicitly document a handful of Apex shapes it cannot reach. Vulkro for Salesforce v0.1.3 ships three new findings that fill those documented gaps, each one cited verbatim against the platform's own docs so the comparison is not omission-based.

What's in the pack

Apex triggers

"Graph Engine doesn't scan Apex triggers." engine-sfge-work-with.html

Vulkro flags .trigger files that read Trigger.new / Trigger.old / Trigger.newMap / Trigger.oldMap and issue DML without a CRUD/FLS marker upstream. The recognised marker vocabulary is the same one the rest of the Apex catalog uses (Schema.sObjectType.X.isUpdateable(), WITH SECURITY_ENFORCED, Security.stripInaccessible, AccessLevel.USER_MODE).

Deep property chains

"Graph Engine supports Apex property chains with a depth of 2 or fewer." engine-sfge-work-with.html

Vulkro flags chains of depth three or more (req.params.lead.email) that flow into a DML or SOQL sink on the same line. The depth-2 limit is the documented boundary; anything past it the platform scanner silently stops following.

Chained method calls

"Graph Engine doesn't currently support this style of chaining." Maintainer jfeingold35, forcedotcom/sfdx-scanner#1619

Vulkro flags chained method calls (Foo.bar().baz()) that feed a DML sink. The shape is common in service-layer code that fluent-builds a DML payload across multiple helpers; the platform scanner cannot follow the chain through the intermediate return values.

Why the framing matters

Per CLAUDE.md rule 14, every comparative claim Vulkro makes is grounded in a primary source. The SFGE-gap pack is built on three direct quotations from Salesforce's own documentation, plus one quotation from a maintainer comment on the official issue tracker. Each finding's confidence_reason field carries the same citation, so when a reviewer asks "why does Vulkro emit this but not Code Analyzer," the answer surfaces in the finding itself.

The same framing applies to the AP-060 dynamic-dispatch finding (see cross-method engine) where the citation is an empirical bench run rather than a doc quote: we shipped the platform scanner against the same fixtures and recorded the output.

Tuning

  • All three findings are Medium by default. Run with VULKRO_SF_SEVERITY_OVERRIDE=AP-056:high,AP-057:high,AP-058:high to lift them to High for a strict CI gate.
  • The trigger finding (AP-056) is the noisiest of the three on a green-field project (every trigger has to do FLS once); the property- chain finding (AP-057) tends to be the most actionable on a mature codebase that uses Wrapper request DTOs.
  • Suppress inline with the standard // vulkro:disable-line AP-056 annotation. The until=2026-12-01 qualifier expires the suppression so the finding re-emerges if the code outlives the documented intent.

Where to go next