Plugin check: Run
node "${PLUGIN_ROOT}/scripts/check-version.js"— if it outputs a message, show it to the user before proceeding.
Scan a Power Pages site project's source files and dependencies for security issues. Runs opengrep (static analysis) and trivy (dependency/secret/license scanning), then surfaces findings.
Initial request: $ARGUMENTS
WARNING: Before proceeding, inform the user: "This skill uses opengrep and trivy, only if they are installed on your local machine. These third-party, open-source tools scan your source code and dependencies and might collect or transmit data under their own terms, privacy policies, and data-handling practices. Microsoft does not control these. If you select the AI fallback, the AI service processes your source code. Review your organization's policies and applicable third-party terms before continuing."
check-tools.js to verify. If either is missing, offer an agent-driven review fallback (see Step 1.2).--severity flag.********).Create tasks in three groups. Mark each in_progress when starting, completed when done.
| Group | When to create | Tasks |
|---|---|---|
| 1 | At start | Check prerequisites |
| 2 | After prerequisites pass | Choose scope (skip in review mode) |
| 3 | After scope is decided (or in review mode) | Run scans · Summarize (always) |
Use Glob to find **/powerpages.config.json. If $ARGUMENTS contains --review <out-dir>, remember the output directory — Step 2 is skipped (run all checks at Advanced depth), and Step 4 writes JSON only.
node "${PLUGIN_ROOT}/skills/scan-code/scripts/check-tools.js"
If either tool is missing, tell the user which tool is missing. Then offer an agent-driven review as a fallback:
In review mode (non-interactive), do not offer the agent-driven review. It needs an interactive opt-in, and the orchestrator expects a JSON file. Write { "status": "skipped", "reason": "<which tool> is not installed" } to <REVIEW_DIR>/scan-code.json and stop.
🚦 Gate (plan · scan-code:1.agent-review-fallback): When a scanning tool is missing, offer the agent-driven review as a fallback before doing any work. It reads the source with
Glob/Read/Grepand has high token consumption, so the user must opt in.Trigger: Step 1.2, only when
check-tools.jsreports a missing tool (interactive mode only — review mode never reaches here because it stops when tools are missing). Why we ask: Auto-starting the agent-driven review burns a large amount of tokens without consent; the user may prefer to install the tool and re-run instead. Cancel leaves: Nothing — no files read, no scan run.
Framing — all user-facing text (the warning, any AskUserQuestion option labels, and the summary): MUST NOT call this a "manual review". It is agent-driven — describe it as you reviewing the code yourself, e.g., "I can look through your code directly and flag issues."
Warn the user that this review reads many files and uses a large amount of tokens, then detect the git context:
main, master, or equivalent): offer to review only the changes in the current branch (git diff <main-branch>...HEAD).If the user accepts, use Glob + Read + Grep to review the relevant files for common security patterns (hard-coded secrets, unsafe API usage, missing input validation, exposed endpoints, etc.) and present findings. Never surface a secret value anywhere — never output a credential's raw value in any output (your context, the session, chat, logs, etc.), not even partially; where a value would otherwise be shown, replace it with a mask (e.g. ********). Do not attempt to install the tools.
Skip in review mode — run both tools at Advanced depth.
Ask the following in order. Each is a separate AskUserQuestion call — do NOT combine. If the user's initial request already answers a question, skip it and move to the next.
🚦 Gate (plan · scan-code:2.scope-choice): Choose what to scan — code, packages, or both — before running any tool. Determines which scanners run.
Trigger: Phase 2 entry (interactive mode only — review mode scans everything at Advanced depth without asking). Skipped if the initial request already names the scope. Why we ask: Auto-scanning everything can run tools the user did not want (e.g., a slow code pass when they only asked about packages); the wrong scope produces a report that misses what they cared about. Cancel leaves: Nothing — no scanner has run.
Question 1 — What to check?
| Label | Description |
|---|---|
| Everything | Check both code and packages. (Recommended) |
| Code only | Check source files for security problems. |
| Packages only | Check installed packages for known issues. |
🚦 Gate (plan · scan-code:2.depth-choice): Choose how thorough the code check is. Only asked when code checking is included.
Trigger: Phase 2, after the scope choice includes code (interactive mode only). Skipped if the initial request already names the depth or code checking was excluded. Why we ask: The thorough option runs a deeper rule set that takes longer; auto-picking it can slow a large project unexpectedly, while auto-picking the quick option can silently skip weaknesses the user expected to catch. Cancel leaves: Nothing — no scanner has run.
Question 2 — Only if code checking is included: How thorough?
| Label | Description |
|---|---|
| Advanced | Covers common risks and deeper code weaknesses. (Recommended) |
| Basic | Covers common risks only. |
Depth mapping (internal, not shown to user): Advanced = p/default,p/owasp-top-ten,p/cwe-top-25. Basic = p/default,p/owasp-top-ten.
Both tools accept custom rules. Do not proactively offer — only use when the user provides them.
--rulesets accepts comma-separated registry packs and local file paths. Custom rulesets are appended to the depth's defaults, not replacing them.--secretConfig for custom secret detection patterns, --ignoreFile for suppressing known findings, --trivyConfig for license classification and other settings, --no-licenseFull to skip source-level license scanning for faster runs.Save each tool's raw JSON output to a temporary file. The transform script in Step 4 normalizes them.
node "${PLUGIN_ROOT}/skills/scan-code/scripts/run-opengrep.js" --projectRoot "<PROJECT_ROOT>" --rulesets "<comma-separated-rulesets>" > "<TEMP_DIR>/opengrep.json"
Pass the rulesets for the chosen depth (Basic or Advanced). Append any user-provided custom rulesets. Run with run_in_background: true for large projects.
node "${PLUGIN_ROOT}/skills/scan-code/scripts/run-trivy.js" --projectRoot "<PROJECT_ROOT>" > "<TEMP_DIR>/trivy.json"
--licenseFull is on by default — source code headers and LICENSE files are scanned alongside package metadata. Run with run_in_background: true for large projects.
node "${PLUGIN_ROOT}/skills/scan-code/scripts/transform-scan-code.js" --opengrepFile "<TEMP_DIR>/opengrep.json" --trivyFile "<TEMP_DIR>/trivy.json" --projectRoot "<PROJECT_ROOT>"
Pass only the files for tools that actually ran. Stdout has the unified { status, findings } shape.
In review mode, write the transform-scan-code.js stdout to <REVIEW_DIR>/scan-code.json. Then stop — the orchestrating skill handles presentation.
Skip in review mode.
Render uses the same shared template as the consolidated security review. First write the Step 3 Normalize stdout to <TEMP_DIR>/scan-code.json, then build a single-section review-data payload and render:
node "${PLUGIN_ROOT}/scripts/build-review-data.js" \
--reportName "Code Scan" \
--inputDir "<TEMP_DIR>" \
--siteName "<SITE_NAME>" \
--goalLabel "Code & Packages scan" \
--scopeLabel "<SCOPE_LABEL>" \
--summary "<SUMMARY_TEXT>" \
--output "<TEMP_DIR>/data.json"
node "${PLUGIN_ROOT}/scripts/render-review.js" \
--data "<TEMP_DIR>/data.json" \
--output "<PROJECT_ROOT>/docs/code-scan-<YYYY-MM-DD-HHMMSS>.html"
<TEMP_DIR> also holds the intermediate opengrep.json/trivy.json from Step 3 alongside scan-code.json; build-review-data.js reads only scan-code.json and ignores the rest. The filename must include the local timestamp (e.g., code-scan-2026-05-14-053805.html). Delete <TEMP_DIR> after the render succeeds. Open the rendered HTML in the browser.
Skip in review mode.
Plain-language summary: total findings, count by category (code patterns, vulnerable packages, secrets, licenses), and what the user should look at first.
Reference:
${PLUGIN_ROOT}/references/skill-tracking-reference.mdUse
--skillName "ScanCode".
If findings map to other skills, suggest them:
/manage-headers
/manage-firewall
/audit-permissions to review existing permissions, and/or /create-webroles to set up role-based access/setup-auth
If no meaningful follow-up exists, end the skill.
run_in_background: true for large projects.********) applies only where a secret value would otherwise be shown; you are not required to display it.references/commands.md — script flags and response shapes. Read when constructing script invocations.