Audit the submission AS THE SALESFORCE REVIEWER WILL. Runs the Product-Security challenge checklist (reviewer-challenges.md) against the audit ledger + scan evidence + the scope manifest, and emits a "what the reviewer will see" report — every challenge marked WILL-FIND / ADDRESSED-fixed / ADDRESSED-refuted(FP) / NOT-STATICALLY-EXAMINED / UNEXAMINED, ranked by the reviewer's own attack priority (public reach → authz → injection → egress → package hygiene → infra), headed by the first things t...
Installs into .claude/skills of the current project.
Are you the author of Reviewer Simulation?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/runverdict-reviewer-simulation)
---
name: reviewer-simulation
description: Audit the submission AS THE SALESFORCE REVIEWER WILL. Runs the Product-Security challenge checklist (reviewer-challenges.md) against the audit ledger + scan evidence + the scope manifest, and emits a "what the reviewer will see" report — every challenge marked WILL-FIND / ADDRESSED-fixed / ADDRESSED-refuted(FP) / NOT-STATICALLY-EXAMINED / UNEXAMINED, ranked by the reviewer's own attack priority (public reach → authz → injection → egress → package hygiene → infra), headed by the first things they will hit. Use after audit-codebase + run-scans, before compile-submission; it reframes what the toolkit already found as what the human tester will reproduce.
allowed-tools: Read Grep Glob Write Bash(ls *) Bash(find *) Bash(cat *) Bash(git rev-parse *) Bash(git log *)
---
# Reviewer Simulation
Produce `<target>/docs/security-review/reviewer-simulation.md`: the submission seen
through Salesforce Product Security's eyes. The deepest thing a partner wants is
not "find my bugs" — it is *"tell me what the reviewer is going to see."* This
skill answers that from data the toolkit already produced (the audit ledger, the
scan evidence, the deployed-org audit if it ran), reframed and **ranked by the
reviewer's own order of attack** so the partner fixes the headline first.
It introduces no new findings and no new requirement — it is a synthesis layer.
Its honesty line is load-bearing: this is the toolkit's STATIC analysis framed as
reviewer intent, **not** the reviewer's live penetration test (CONVENTIONS §2).
## When to use
- After `/sf-security-review-toolkit:audit-codebase` and ideally
`/sf-security-review-toolkit:run-scans` — it reads their ledger + evidence
- Before `/sf-security-review-toolkit:compile-submission` — the reviewer-sim
report is a package artifact and its open-challenge list seeds the path-to-green
- Re-run after remediation — a challenge flips WILL-FIND → ADDRESSED as the fix
lands and the ledger entry moves to `fixed`
- NOT a substitute for the audit (it finds nothing new) and NOT the pen test
(Salesforce reproduces these live regardless)
## Prerequisites
- `<target>/.security-review/scope-manifest.json` — the elements filter the
checklist (a TLS challenge for a package-only listing is N/A, never reported);
refuse to run without it
- `<target>/.security-review/audit-ledger.json` — the source of WILL-FIND /
ADDRESSED verdicts; degrade gracefully if thin, but say plainly the simulation
is weaker for it
- `${CLAUDE_PLUGIN_ROOT}/methodology/reviewer-challenges.md` — the challenge
checklist (the data); read it, do not reinvent the tiers
- Optionally the scan evidence under `<target>/.security-review/evidence/` and the
deployed-org audit report — they answer the scan-family and dynamic challenges
## Steps
1. **Load the manifest and filter the checklist.** Read `reviewer-challenges.md`
and keep only the challenges whose element is present in the manifest —
matching element types through their canonical form (synonyms per
`harness/render-detected-elements.mjs`'s `ELEMENT_TYPE_SYNONYMS`, e.g.
`external-web-app` ≡ `external-endpoint`), so a synonym-typed manifest keeps
exactly the challenges its canonical twin would. A
challenge for an absent element is N/A — drop it silently (it would read as
false coverage), but record the dropped count in the run log so "0 MCP
challenges" is visible as a scoping fact, not a gap.
2. **Map each applicable challenge to a verdict from the ledger + evidence.**
For each challenge, search the audit ledger and scan evidence for a matching
entry (by the dimension/baseline id the challenge names, and the file/finding):
- **WILL-FIND** — a `confirmed`/`regressed` ledger entry (or a scan finding)
matches. This is the headline case: the reviewer WILL reproduce it. Carry
the finding's `adjusted_severity`, file:line, and one-line description.
- **ADDRESSED** — carry the evidence pointer, and **sub-label it by provenance
so the table can never be skim-read as "we fixed it" when we did not**:
- **ADDRESSED-fixed** — a `fixed` ledger entry: a real remediation landed,
backed by a fix commit + a clean re-scan. Disclose as resolved.
- **ADDRESSED-refuted(FP)** — a `refuted` entry whose verifier reasoning is
the non-exploitability argument, or a satisfied control with evidence.
This is **NOT a remediation** — it is "we considered this and it does not
apply / is not exploitable," disclosed via the FP dossier. Never present
a refuted entry as a fix.
The distinction is load-bearing: a partner who reads a bare "ADDRESSED" in
the table and discloses a refuted finding to Salesforce as *fixed* would be
disclosing a non-fix. The sub-label makes the two paths un-confusable.
- **NOT-STATICALLY-EXAMINED** — no ledger/scan signal AND the challenge is
genuine pen-test territory (runtime CSP, live error hygiene, the Agentforce
two-account probe, a logic bug reachable only at a specific record/permission/
utterance combination). Name it explicitly; NEVER mark it ADDRESSED on the
strength of silence. If the challenge is statically answerable but the
toolkit simply did not run that dimension/scan, mark it **UNEXAMINED — run
<dimension/family>** and route back, not ADDRESSED.
- **DYNAMICALLY-OBSERVED (S2 agent-trace evidence)** — when the S2 agent-trace
probe (`harness/agent-trace-probe.mjs`, evidence under
`evidence/deployed-package/agent-trace-{actions,errors,routing}-<date>.json`)
ran against the activated agent, the agent-RUNTIME challenges that would
otherwise sit at NOT-STATICALLY-EXAMINED may instead carry a
**dynamically-observed pointer** — a real executed-action + egress-host
observation from the trace. This applies to challenge **2.2** (record-handle
leak), the **4.x** egress / third-party-LLM challenges, and the Agentforce
two-account probe (per `methodology/reviewer-challenges.md` challenges 2.2 /
4.x). Cite the specific action name + egress host from the trace, and label it
**"dynamically observed for the scripted utterances"** — this MOVES the
challenge from NOT-STATICALLY-EXAMINED *toward* dynamically-observed, it does
NOT make it ADDRESSED: the trace shows what the agent DID for those utterances,
not the full reachable surface, and an empty `actions` dimension stays
"no observed actions" (never a pass). It remains coverage-bounded, not a
substitute for Salesforce's live pen test (see the honesty floor below).
Never invent a verdict. The mapping is mechanical: a challenge is WILL-FIND
only with a real matching open entry, ADDRESSED only with a real fixed/refuted
entry or satisfied control + evidence, otherwise it is one of the un-examined
states. A simulation that reports ADDRESSED without an evidence pointer is the
exact dishonesty CONVENTIONS §2 forbids.
3. **Rank and write the report.** Order by the reviewer's tiers (Tier 1 public
reach first). Write `<target>/docs/security-review/reviewer-simulation.md`:
- **Headline — "The first things the reviewer will hit."** The top 3–5
WILL-FIND challenges in tier order, each one line: severity · the reviewer's
action · file:line · the one-line fix. This is what the partner reads first
and fixes first.
- **The full challenge table**, tier by tier: challenge · verdict
(WILL-FIND / ADDRESSED-fixed / ADDRESSED-refuted(FP) / NOT-STATICALLY-EXAMINED
/ UNEXAMINED) · evidence or finding pointer · the reviewer's probe. Use the
ADDRESSED sub-labels in the cell — never a bare "ADDRESSED" — so a glance at
the table can never read a refuted (false-positive) finding as a remediation.
N/A challenges are omitted (their count is in the run log).
- **No-surprises disclosures** — the ADDRESSED-via-refuted challenges, each
with the verifier's non-exploitability reasoning, written for direct reuse in
the FP dossier (these are what you tell the reviewer you already considered).
- **What this simulation did NOT examine** — the NOT-STATICALLY-EXAMINED +
UNEXAMINED challenges, named. This section is mandatory; its absence makes the
report dishonest by omission. State plainly: Salesforce reproduces every
challenge live on the installed package + running endpoint with org-specific
context a static pass cannot enumerate; ADDRESSED means "no open finding
within the audited dimensions," never "the reviewer finds nothing."
- The mandatory provenance footer (CONVENTIONS §2): generation date,
`git rev-parse HEAD`, the ledger pass/tier it synthesized, and that this is
static synthesis, not a scan or a pen test.
4. **Feed the downstream skills.** The report is a package artifact
`/sf-security-review-toolkit:compile-submission` includes; its open-challenge
list (the WILL-FIND + UNEXAMINED rows) seeds the `path-to-green` remediation
sequence; its ADDRESSED-via-refuted rows seed the FP dossier. Do not register a
new baseline requirement or SCI gate — the simulation surfaces what the ledger +
SCI already know, reframed; the SCI's numbers are the authority, this report is
the narrative.
## Automated vs. manual recap
**Automated:** checklist filtering by manifest elements, the ledger/evidence →
verdict mapping, ranking, report writing, the FP-dossier disclosure extraction.
**Manual:** deciding to fix vs. document each WILL-FIND, and reading the
NOT-STATICALLY-EXAMINED list as the live-test surface to harden before submission.
Nothing here is a scan or a pen test — it is a reframing of static findings as
reviewer intent, and Salesforce runs its own penetration test regardless.
## What feeds the next skill
The **WILL-FIND** ranking and the **ADDRESSED-refuted(FP)** rows feed
`/sf-security-review-toolkit:compile-submission` — the fix-vs-document decisions and the
FP dossier it cross-checks before the SCI gate. The **NOT-STATICALLY-EXAMINED** list feeds
`/sf-security-review-toolkit:prepare-test-environment` as the live-test surface to harden
before the review window opens.