AppExchange Security Review readiness report
Salesforce ISVs shipping managed packages through AppExchange must pass a Security Review run by Salesforce's Product Security team, structured around a published checklist. The biggest cause of rejection is CRUD/FLS gaps. The rest (SOQL injection, secrets in source, Visualforce XSS, over-privileged profiles, broad OAuth scopes, cleartext named credentials) is predictable and statically detectable.
vulkro-sf appexchange-report is the offline pre-submission self check. Point
it at a Salesforce DX or legacy MDAPI project. It groups Vulkro's Salesforce
findings by the published checklist sections and renders one self-contained
HTML report, rated PASS / FAIL / NOT EVALUATED per section. The header pins the
checklist version date, so the report is reproducible: run it today or a year
from now and it looks the same, even if the published checklist changes.
Quickstart
vulkro-sf appexchange-report . # render to stdout
vulkro-sf appexchange-report . -o appexchange.html # write to file
Open the resulting HTML in any browser. Use File - Save as PDF for the PDF deliverable to attach to your submission package.
The default path is the current directory. It should contain
sfdx-project.json (SFDX) or package.xml (legacy MDAPI).
Exit codes
0- every covered checklist section passed (zero findings on every section, and at least one section had detector coverage).1- at least one section is FAIL (or the install is on the Free tier).2- argument error or internal failure (missing path, parse error, IO error, internal crash).
Wire into CI as a pre-submission gate:
vulkro-sf appexchange-report ./my-app -o report.html || exit $?
Report layout
- Header: project name, scan timestamp, pinned checklist version string, source URL for the canonical published checklist, and a verdict pill (READY when every section is PASS, GAPS FOUND otherwise).
- Coverage note: a callout reminding the reader that the report is a readiness indicator, not a guarantee, and listing the review categories Vulkro does not cover (penetration test results, org-shape configuration, authentication flows that need a live org to verify, the non-static parts of secure development lifecycle documentation).
- Summary strip: pass / fail / not-evaluated counts, total mapped findings, and the count of other Vulkro findings the scan produced that did not map to a checklist section (so nothing the scanner emitted is silently dropped from the report).
- One row per checklist section: each row carries
- the section title and a one-line description,
- the list of Vulkro rule IDs that cover the section,
- a PASS / FAIL / NOT EVALUATED status pill, and
- a per-finding table (file, line, severity, rule, message) when the section is FAIL.
Checklist sections
The report tracks 10 sections, drawn from the public AppExchange Security Review categorisation as of 2026-Q2:
| Section | Vulkro rule coverage |
|---|---|
| Code Quality and Best Practices | apex_soql_injection, apex_unsafe_deserialize, apex_open_redirect, sf_visualforce (dynamic iframe URL) |
| Object and Field Permissions (CRUD / FLS) | apex_crud_fls, apex_crud_fls (per-method gap), apex_idor, apex_mass_assignment, sf_flow (system-mode DML), sf_visualforce (controller exposes request param) |
| Sensitive Data Storage and Logging | apex_secrets, apex_hardcoded_ids, apex_callout_creds, sf_lwc (real-provider API key), sf_lwc (credential-shaped identifier), sf_lwc (credential in browser storage), sf_metadata (named-credential anonymous principal carrying a secret), sf_metadata (connected-app consumerSecret in metadata), sf_metadata (connected-app consumerKey in metadata) |
| Cryptography | apex_weak_crypto |
| Sharing and Visibility (with / without sharing) | apex_runas_misuse, apex_without_sharing, sf_flow (SystemMode context) |
| Lightning Component Security (LWC + Aura) | sf_lwc (XSS surface), sf_lwc (dangerous JS primitive), plus the credential-shape rules above |
| Visualforce Security | sf_visualforce (escape=false), sf_visualforce (script merge), sf_visualforce (dynamic script load), sf_visualforce (dynamic iframe URL), sf_visualforce (controller exposes request param) |
| Profiles, Permission Sets, Named Credentials, Connected Apps | sf_metadata (over-privileged profile/permset), sf_metadata (named-credential password), sf_metadata (named-credential cleartext), sf_metadata (named-credential merge fields in body), sf_metadata (named-credential anonymous principal carrying a secret), sf_metadata (connected-app Full OAuth scope), sf_metadata (connected-app callbackUrl cleartext), sf_metadata (connected-app consumerSecret in metadata), sf_metadata (connected-app consumerKey in metadata) |
| External Integrations and Callouts | apex_callout_creds, sf_metadata (named-credential password), sf_metadata (named-credential cleartext), sf_metadata (named-credential merge fields in body), sf_metadata (connected-app callbackUrl cleartext) |
| Flow Security | sf_flow (hardcoded ID), sf_flow (system-mode DML), sf_flow (SystemMode context) |
The checklist label in the report always matches the public Partner Community section name verbatim. When Salesforce updates the checklist categorisation, the pinned version string in the header changes and a new mapping is published.
Sample output
<header class="cover">
<div class="cover-l">
<div class="brand">vulkro - Salesforce</div>
<h1>AppExchange Security Review readiness</h1>
<div class="dim">Project: <strong>my-managed-package</strong></div>
<div class="dim small">Scanned: 2026-05-25T14:33:10Z</div>
<div class="dim small">Checklist pin: AppExchange Security Review checklist mapping v0.1.0 (based on public sections as of 2026-Q2)</div>
</div>
<div class="cover-r">
<div class="verdict crit">GAPS FOUND</div>
</div>
</header>
Caveats
- This report is a static-analysis readiness indicator, not a guarantee of acceptance. Salesforce's Product Security team makes the final review determination.
- Sections marked NOT EVALUATED still require manual review.
- The mapping table is pinned to a specific checklist version, printed in the report header. Verify against the latest published checklist before relying on the report for a submission. Open an issue at support@vulkro.com if the published checklist has changed and we have not yet updated the mapping.
Related
vulkro-sf scan .for the full Salesforce scan output without the AppExchange-checklist grouping.vulkro-sf compliance --profile owasp-asvsfor an OWASP-checklist view of the same findings.- The published AppExchange Security Review checklist itself: https://partners.salesforce.com/partner_program/security_review/