Skip to main content

vulkro scan --include-eslint

PRO-T-W-2: ESLint wrapper for Salesforce LWC and Aura. This page covers the --include-eslint flag on vulkro scan, the bundled ruleset, the binary discovery rules, and how the wrapper's findings show up in Vulkro output.

What it does

When you pass --include-eslint, Vulkro:

  1. Runs the native scan (Apex, Visualforce, Flow, metadata, LWC, Aura, plus every cross-language rule that applies to your project).
  2. Shells out to a host-installed ESLint with a curated security-only config, scanning force-app/main/default/lwc/ and force-app/main/default/aura/.
  3. Parses ESLint's JSON output, maps each message into Vulkro's SecurityFinding shape, and merges the result into the same findings list.
  4. Returns the merged set to every downstream sink: the CLI table, the JSON / SARIF / NDJSON / JUnit / CSV formatters, the AppExchange readiness report, --fail-on, --gate, the .vulkro-baseline.json diff, and so on.

The wrapper makes Vulkro a drop-in replacement for the sfdx-scanner step that runs ESLint over LWC and Aura.

Quick start

# One-time install of ESLint and the Salesforce plugins
npm install -g eslint @salesforce/eslint-plugin-lwc @salesforce/eslint-plugin-aura

# Pass --include-eslint to opt in
vulkro scan ./my-managed-package --include-eslint

If eslint is not on $PATH but npx is, Vulkro falls back to npx eslint automatically. To pin a specific binary, set the env var:

VULKRO_ESLINT_BIN=/opt/sfdx/node_modules/.bin/eslint vulkro scan . --include-eslint

Curated ruleset

The wrapper does not load whatever ESLint config the project happens to ship; it bundles a security-only config and passes it via --config <path> --no-eslintrc. The bundled rules are:

RuleSourceSeverityWhat it catches
no-evalCoreerrorDirect eval(expr) calls.
no-implied-evalCoreerrorsetTimeout(string, ms), setInterval(string, ms), and friends.
no-new-funcCoreerrornew Function('arg', body) indirect eval.
no-script-urlCoreerrorjavascript: URLs in href / src / location.href.
no-octal-escapeCoreerrorOctal escapes deprecated in ES5 strict mode.
no-prototype-builtinsCoreerrorobj.hasOwnProperty(...) (prototype-pollution shape).
@salesforce/lwc/no-deprecated-api-usagePluginerrorDeprecated Salesforce API surfaces.
@salesforce/lwc/no-document-queryPluginerrordocument.querySelector instead of this.template.querySelector (shadow-root leak / XSS surface).
@salesforce/lwc/no-async-operationPluginwarnFree-floating setTimeout / setInterval outside the LWC lifecycle.
@salesforce/lwc/valid-apiPluginerror@api-decorated properties that bypass input validation.
@salesforce/aura/no-bound-actionPluginerrorAura Action.setCallback(this, ...) with bound function references (callback confusion).

Formatting and style rules (semi, indent, quotes, etc) are deliberately excluded per Vulkro's "security findings only" manifesto.

Finding shape

Every wrapped ESLint message becomes a SecurityFinding with:

  • id rendered into the message as ESLINT-LWC-<rule> or ESLINT-AURA-<rule> based on the file path.
  • severity: ESLint error -> Vulkro High, ESLint warn -> Vulkro Medium.
  • owasp_category chosen from the rule name:
    • /eval|new-func|script-url/ -> SoftwareIntegrityFailures
    • /query|api|bound-action/ -> UnsafeConsumptionOfAPIs
    • everything else -> SecurityMisconfiguration
  • confidence: Medium. ESLint's AST patterns do not have Vulkro's cross-file taint confirmation, so the wrapper does not claim High.
  • remediation: hand-written per-rule advice that names the LWC / Aura idiom you should switch to.

Example mapped JSON finding (truncated for the doc):

{
"id": "uuid-omitted",
"owasp_category": "SoftwareIntegrityFailures",
"severity": "High",
"file": "force-app/main/default/lwc/redirector/redirector.js",
"line": 5,
"message": "ESLINT-LWC-no-script-url: Script URL is a form of eval (5:14 to 5:41)",
"remediation": "Replace `javascript:` URLs with a proper event handler or `lightning-navigation` call. ...",
"confidence": "medium",
"confidence_reason": "wrapped ESLint rule `no-script-url` (pattern match, no Vulkro dataflow confirmation)"
}

Binary discovery

Order, first hit wins:

  1. VULKRO_ESLINT_BIN env var, treated as the absolute path to the binary.
  2. eslint on $PATH.
  3. npx eslint on $PATH.

If none resolve, the scan exits with code 2 and a message naming the install command. Example error:

✗ --include-eslint: ESLint is not installed and Node.js / npx is not
on $PATH. Install Node.js + ESLint: `npm install -g eslint
@salesforce/eslint-plugin-lwc @salesforce/eslint-plugin-aura`, or set
`VULKRO_ESLINT_BIN=/path/to/eslint`.

Exit codes

The wrapper inherits the standard vulkro scan contract:

CodeMeaning
0No findings (including no wrapper findings).
1Findings reported by either Vulkro or the wrapper.
2Operational error: ESLint missing, malformed JSON output, ESLint configuration failure (exit code 2 from ESLint itself).

AppExchange Security Review

Every wrapper finding routes to the Lightning Component Security row in vulkro sf-appexchange-report regardless of which concrete ESLint rule fired, because all wrapped rules target a component-layer concern (XSS surface, code injection inside a controller, deprecated component API, input-validation gap on an @api property).

Comparison with sfdx-scanner

Capabilitysfdx-scannerVulkro
ESLint over LWC + Auravia --engine eslint-lwc--include-eslint
Curated security-only configno (loads project .eslintrc)yes (bundled, ships with Vulkro)
Output formattext / JSON / JUnit / SARIFtable / JSON / SARIF / NDJSON / JUnit / CSV / gh-pr / CycloneDX / SPDX / PDF / RoPA
Native scanner integrationseparate runmerged into the same findings list
Offline operationrequires sf CLI plus Nodewrapper requires ESLint; the rest of Vulkro is fully offline