plugins/power-pages/skills/security-review/SKILL.md
Runs a guided, end-to-end security review of a Power Pages site and consolidates every finding into one HTML report covering the live site, browser headers, firewall, authentication, and role-based permissions. Use when the user wants a full security review, a release-readiness check before publishing, an access-and-config check during development, live site monitoring, or asks open-ended questions like "review my site security", "is my site safe to ship", "do a security check", "monitor my site" — even if they do not name the individual checks.
npx skillsauth add microsoft/power-platform-skills security-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Plugin check: Run
node "${CLAUDE_PLUGIN_ROOT}/scripts/check-version.js"— if it outputs a message, show it to the user before proceeding.
Guide the user through a full security review of their Power Pages site. Runs the matching focused skills and assembles every finding into a single HTML report.
The skill never asks the user technical questions. The conversation stays in plain language.
Initial request: $ARGUMENTS
The skill has six phases. Phases 2–5 each map to one conversation beat with the user; phases 1 and 6 are silent setup and cleanup. See references/flow.md for the rationale behind each beat.
| Phase | What happens | User-facing beat | |-------|--------------|------------------| | 1 — Prerequisites | Locate project, set up working folders | (silent setup) | | 2 — Scope | Capture goal — one question, three answers, plain language | Ask the goal | | 3 — Skills | Run the matching skills, surface progress | Scan in progress | | 4 — Report | Build the consolidated report — totals + per-section findings | Results summary + Findings | | 5 — Present | Present results, offer remediation follow-ups | Next steps and guidance | | 6 — Cleanup | Remove temporary files | (silent cleanup) |
Create tasks in three groups. Mark each in_progress when starting, completed when done.
Group 1 — create at the start of prerequisites:
| Task subject | activeForm | |--------------|------------| | Check prerequisites | Checking prerequisites |
Only this one task. Do not create any other tasks until prerequisites complete.
Group 2 — create after prerequisites complete:
| Task subject | activeForm | |--------------|------------| | Capture goal | Capturing goal |
Group 3 — create after the goal is captured:
| Task subject | activeForm | |--------------|------------| | Run skills | Running checks | | Build the report | Building the report | | Present findings | Presenting findings | | Clean up | Cleaning up |
Use Glob to find **/powerpages.config.json. If none is found, tell the user the site needs to be created first with /create-site, then stop.
For the monitor and release goals (any goal that delegates to scan-site or manage-firewall), also confirm that .powerpages-site/website.yml exists. If it does not, the site has not been deployed yet — tell the user (in plain language) the site needs to be deployed once before a live security review can run, recommend /deploy-site, then stop. Do not try to identify the site by name or URL — different sites can share the same name.
For the access-config goal, the deploy check is not required: authentication, web roles, and table permissions are read from local YAML alone.
Create a fresh working directory: <SYSTEM_TEMP>/security-review/. The folder holds JSON data files emitted by each skill in review mode. The folder is removed in the cleanup step.
If the folder already exists from a previous interrupted run, delete its contents (not the folder itself) before continuing.
The final HTML always lives at <PROJECT_ROOT>/docs/security-review-<YYYY-MM-DD-HHMMSS>.html using the local timestamp at the start of the run (e.g. security-review-2026-05-14-053805.html). Always include the timestamp — do not use a bare security-review.html name. This keeps each run's report distinct.
Ask the user with a single AskUserQuestion call. If the user's initial request already answers it, skip and continue.
Question — What to review?
| Label | Description | |-------|-------------| | Access & config | Check authentication, web roles, and table permissions. Works on local files only. | | Release readiness | Full review before publishing — checks everything. (Recommended) | | Deployed site | Check the live site for issues. Requires deployment. |
Goal mapping (internal):
| Label | Goal id | Skills |
|-------|---------|------------|
| Access & config | access-config | audit-permissions, setup-auth (read-only) |
| Release readiness | release | scan-site, manage-headers, manage-firewall, audit-permissions, setup-auth (read-only) |
| Deployed site | monitor | scan-site |
Build a selectedSkills list based on the answer. Always include the read-only check of setup-auth for the access-config and release goals (it consists of reading existing YAML, not running the skill itself — see § 3.2 below). This is the Access & Data Security Validation component.
Spawn each selected skill as a background subagent via the Agent tool. Each subagent invokes its skill with the argument --review <SYSTEM_TEMP>/security-review/. Each skill handles its own authentication, error reporting, and progress.
Skills run as parallel subagents using the Agent tool.
Default — launch every Agent-eligible skill in one parallel batch. Spawn all selected subagents in a single message with multiple Agent tool calls so they start concurrently. Each subagent runs with run_in_background: true. The Agent-eligible set is scan-site, manage-headers, manage-firewall — these all support --review mode. scan-site is the slowest (server-side scan, several minutes); the others typically finish within seconds.
Fallback — staggered launch. If the harness rejects a parallel-batch call for any reason, launch scan-site first and then the remaining skills in a follow-up message. This is a tool-affordance fallback, not the preferred path.
Inline checks (run while subagents work). audit-permissions and setup-auth do not support --review and MUST NOT be launched via Agent — handle them inline as described in § 3.2.
Wait for all subagents to complete before proceeding to the report-building step.
Each subagent receives a self-contained prompt that includes:
--review argument with the temp directory pathExample subagent call:
Agent({
description: "Run scan-site",
prompt: "Invoke the skill `scan-site` with argument `--review <SYSTEM_TEMP>/security-review/`. The Power Pages project root is <PROJECT_ROOT>. <any additional scope parameters>. Write the **transform script stdout verbatim** to <SYSTEM_TEMP>/security-review/scan-site.json. Do NOT synthesize, augment, or re-classify the findings. If the skill fails, write { \"status\": \"skipped\", \"reason\": \"<plain-language reason>\" } instead.",
run_in_background: true
})
Verbatim rule: the subagent's output JSON must contain only the findings emitted by the skill's transform script. The orchestrator must not append findings, rewrite titles, add severity, or otherwise editorialize.
After all subagents complete, expect JSON files at <SYSTEM_TEMP>/security-review/<skill-name>.json. Each file has the shape { status, findings, details? } produced by the skill's transform script:
<SYSTEM_TEMP>/security-review/
├── scan-site.json
├── manage-headers.json
├── manage-firewall.json
└── audit-permissions.json (when invoked)
If a skill's subagent fails or is skipped, write a placeholder file with shape { "status": "skipped", "reason": "<plain-language reason>" }. The report-building step renders this as a single non-severity finding for that section (no severity field, to stay consistent with § 3.1.3).
Only findings that come from a tool that genuinely outputs severity may carry a severity field:
| Section | Source | Severity allowed? |
|---------|--------|-------------------|
| scan-site | deep-scan (ZAP) | Yes |
| manage-headers | transform-headers.js (inventory) | No |
| manage-firewall | transform-firewall.js (inventory) | No |
| audit-permissions | Web roles & table permissions audit | No |
| setup-auth | Site settings & auth-related source code audit | No |
For inventory sections, do not add severity to findings — not even info. The subagent and orchestrator must write the transform output verbatim without inserting opinionated severity-bearing findings. The tag field is also off-limits as a severity workaround: it is reserved for short mechanical identifiers from tools (e.g. ZAP rule ids, CWE codes) and MUST NOT carry severity-equivalent strings (critical, warning, info), since the report template renders it as a visible chip next to the title.
The transform scripts for manage-firewall and manage-headers produce only structured raw data — they do not hardcode plain-language descriptions. The subagent must generate an annotations JSON file and pass it to the transform via --annotations. The annotations supply:
See each skill's SKILL.md § 5.1 for the annotation file shape. The agent's job is to write accurate, terse descriptions based on the raw data — not to invent severities or fabricate issues.
--review modeaudit-permissions and setup-auth do not support --review. Handle them inline (not as background subagents):
Skill tool (not Agent). The skill audits both web roles and table permissions — capture both in its output. After it completes, read its output and write <SYSTEM_TEMP>/security-review/audit-permissions.json in the unified { status, findings, details? } shape (mapping each audit finding into the common finding fields: id, title, location, details, fix)..powerpages-site/site-settings/ YAML files directly and check for:
Authentication/OpenIdConnect/*/Authority)Authentication/Registration/ProfileRedirectEnabled = false)HTTP/SameSite/Default)Write the resulting findings to <SYSTEM_TEMP>/security-review/setup-auth.json in the same format.
Field policy for both sections — these are inventory sections, not tool-output severities (see § 3.1.3):
severity field on any finding.tag field. The tag field is reserved for short mechanical identifiers from tools (HTTP/X-Frame-Options, ZAP rule id 10055, CWE codes). It MUST NOT carry severity-equivalent strings (critical, warning, info) — the report template renders tag as a visible chip next to the title, so stashing LLM-judged severity there would visually re-introduce the severity bucketing this section explicitly forbids.Tell the user that all checks are running in parallel. As each subagent completes, give a short progress line (e.g., "Code check finished — 2 important issues, 4 smaller ones."). Avoid technical jargon. Do not narrate skill internal steps. Once all subagents have finished, confirm that all checks are complete before moving to the report-building step.
Write up to four plain-language next-step recommendations as a JSON string array to <SYSTEM_TEMP>/security-review/next-steps.json. Compose a 2–4 sentence plain-language summary of the overall state.
node "${CLAUDE_PLUGIN_ROOT}/scripts/build-review-data.js" \
--reportName "Security Review" \
--inputDir "<SYSTEM_TEMP>/security-review/" \
--siteName "<SITE_NAME>" \
--goalLabel "<GOAL_LABEL>" \
--scopeLabel "<SCOPE_LABEL>" \
--summary "<SUMMARY_TEXT>" \
--nextStepsFile "<SYSTEM_TEMP>/security-review/next-steps.json" \
--output "<SYSTEM_TEMP>/security-review/security-review-data.json"
node "${CLAUDE_PLUGIN_ROOT}/scripts/render-review.js" \
--output "<DOCS_PATH>" \
--data "<SYSTEM_TEMP>/security-review/security-review-data.json"
Open <DOCS_PATH> in the user's default browser.
Reference:
${CLAUDE_PLUGIN_ROOT}/references/skill-tracking-reference.mdUse
--skillName "SecurityReview".
Show a short plain-language summary in the chat: counts of critical / warning / info findings, where the report lives. Then offer the next action with AskUserQuestion:
| Question | Options | |----------|---------| | What would you like to do next? | Walk me through the fixes; Re-run the review; Done for now |
If the user picks "walk me through", group critical findings by section and offer the matching focused skill for each (/manage-headers, /manage-firewall, /audit-permissions, etc.).
If the user picks "re-run", invoke this skill again with the same goal and scope.
Delete the entire <SYSTEM_TEMP>/security-review/ folder. The final HTML, located in docs/, must remain. Confirm to the user that temporary files have been removed.
If the cleanup fails (file lock, permission), warn the user and continue — the report is already written and the temp folder can be removed manually later.
Agent tool, launched in a single message. Perform the inline read-only setup-auth check while subagents work. Use the staggered launch (§ 3.1 fallback) only if the harness rejects the parallel-batch call.--review mode.${CLAUDE_PLUGIN_ROOT}/scripts/lib/templates/security-review-report.html via scripts/render-review.js. Do not author per-skill HTML or duplicate the template; the generated report must match the existing audit-permissions report visually.--review mode during this orchestration. Apply changes only via the explicit "walk me through fixes" follow-up, after the user picks an action.references/flow.md — rationale and example phrasing for the conversation beats in phases 2–5tools
Configure the Canvas Authoring MCP server for the current coauthoring session. USE WHEN "configure MCP", "set up MCP server", "MCP not working", "connect Canvas Apps MCP", "canvas-authoring not available", "MCP not configured", "set up canvas apps". DO NOT USE WHEN prerequisites are missing — direct the user to install .NET 10 SDK first.
development
Use when the user asks to "set up authentication", "add login", "add logout", "add sign in", "enable auth", "add role-based access", "add authorization", "protect routes", "configure identity provider", "configure Entra ID", "configure Entra External ID", "configure OpenID Connect", "add OIDC", "set up SAML", "set up WS-Federation", "set up local login", "add username password", "add Facebook login", "add Google sign in", "add Microsoft Account", "set up invitation login", or otherwise wants to set up authentication (login/logout) and role-based authorization for their Power Pages code site using any supported identity provider (Microsoft Entra ID, Entra External ID, OpenID Connect, SAML2, WS-Federation, local authentication, Microsoft Account, Facebook, or Google).
development
Creates, updates, and deploys Power Apps generative pages for model-driven apps using React v17, TypeScript, and Fluent UI V9. Orchestrates specialist agents for planning, entity creation, and code generation. Use it when user asks to build, retrieve, or update a page in an existing Microsoft Power Apps model-driven app. Use it when user mentions "generative page", "page in a model-driven", or "genux".
development
Creates a new Power Pages code site (SPA) using React, Angular, Vue, or Astro. Guides through the full process from initial concept to deployed site: requirements discovery, scaffolding, component planning, design, implementation, validation, and deployment. Use when the user wants to create, build, or scaffold a new Power Pages website or portal.