manage-headers
The manage-headers skill inspects and configures HTTP security headers for Power Pages sites by reading and editing YAML site-setting files stored in `.powerpages-site/site-settings/`. Use it to review current header configuration, identify security gaps, apply header changes like Content-Security-Policy or X-Frame-Options, and verify the configuration is correct while avoiding platform-managed headers like HSTS and respecting runtime behaviors such as CSP nonce replacement and CORS wildcard specialization.
git clone --depth 1 https://github.com/microsoft/power-platform-skills /tmp/manage-headers && cp -r /tmp/manage-headers/plugins/power-pages/skills/manage-headers ~/.claude/skills/manage-headersSKILL.md
> **Plugin check**: Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.
# Manage Headers
Inspect and configure the HTTP security headers for a Power Pages site. Headers are configured as `HTTP/*` site settings stored in `.powerpages-site/site-settings/` YAML files.
**Initial request:** $ARGUMENTS
## Gotchas
- **Site settings are YAML files.** Each header is a separate `.yml` file in `.powerpages-site/site-settings/`. The file name uses `-` instead of `/` (e.g., `HTTP/X-Frame-Options` → `http-x-frame-options.sitesetting.yml`).
- **Absent = no header.** When a site setting is absent, the runtime omits that header entirely (except CSP on new sites — see headers-reference.md).
- **HSTS and Cache-Control are platform-managed.** Do not try to set `HTTP/Strict-Transport-Security` — the runtime does not recognize it and the setting has no effect.
- **Maker-mode bypasses headers.** Requests from Power Pages Studio skip all `HTTP/*` header emission. Verify headers in an incognito tab, not the studio preview.
- **CSP is pass-through.** The runtime emits the value verbatim — it does NOT merge runtime sources automatically. The CSP MUST include Power Pages runtime hosts or the site breaks.
- **CSP nonce.** When `script-src` contains `'nonce'`, the runtime replaces it per-request with `'nonce-<random>'` and auto-hashes inline event handlers. Scripts created dynamically via `document.createElement` do NOT receive the nonce.
- **`SameSite=None` requires HTTPS.** The runtime sets `Secure` on every cookie over HTTPS automatically.
- **CORS `*` is auto-specialized.** The runtime replaces `*` per-request with the specific requesting Origin — the browser sees a single-origin header, not a wildcard.
## Workflow
1. **Prerequisites** — Locate project, confirm site-settings directory exists
2. **Inspect current headers** — Read site-setting YAML files, identify configured and missing headers
3. **Assess and plan** — Identify gaps, present recommendations
4. **Apply changes** — Edit existing settings or create new ones
5. **Summarize** — Present results, record usage, offer follow-ups
## Task Tracking
Create tasks in four groups. Mark each `in_progress` when starting, `completed` when done.
| Group | When to create | Tasks |
|-------|----------------|-------|
| 1 | At start | Check prerequisites |
| 2 | After prerequisites pass | Inspect current headers · Assess and plan (skip "Assess and plan" in review mode) |
| 3 | After user approves changes | Apply changes (skip in review mode OR if no changes were accepted) |
| 4 | After apply or assess | Summarize (always) |
---
## 1. Prerequisites
### 1.1 Locate the project, detect review mode
Use `Glob` to find `**/powerpages.config.json`. If `$ARGUMENTS` contains `--review <out-dir>`, remember the output directory — Steps 3–4 are skipped and Step 5 writes JSON only.
### 1.2 Verify site-settings directory
Check that `.powerpages-site/site-settings/` exists. If not, the site has not been deployed yet — tell the user and recommend `/deploy-site`. Stop.
---
## 2. Inspect current headers
Use `Glob` to find all `*.yml` files in `.powerpages-site/site-settings/`. Use `Read` to read each file and extract the `name` and `value` fields. Identify all settings with an `HTTP/` prefix — these are the configured headers.
Compare against the recognized header catalogue in `references/headers-reference.md`. For each header in the catalogue:
- **Present** — record its current value.
- **Missing** — record it as absent and note the recommended value from headers-reference.md.
For CSP specifically: if `HTTP/Content-Security-Policy` is present, scan the project's source files using `Glob` + `Read` to find external URLs and check whether they are covered by the policy. Identify the site's cloud environment via `pac auth who` to determine the correct Power Pages runtime host (see headers-reference.md § "Power-Pages-runtime sources a CSP must allow").
---
## 3. Assess and plan
Skip in **review mode**.
MUST use plain language only. Never lead with words like CSP, CORS, HSTS, or MIME sniffing — explain using everyday language:
| Header concept | Plain-language name |
|----------------|---------------------|
| Content-Security-Policy | "which scripts and resources the browser is allowed to load" |
| X-Frame-Options / frame-ancestors | "whether other websites can put your site inside a frame" |
| X-Content-Type-Options | "stop the browser from guessing file types" |
| CORS headers | "which other websites can call your site's data" |
| SameSite cookies | "when the browser sends your sign-in cookie" |
### Default approach
Read `references/headers-reference.md` for recommended values and guidance. **Present the most important gaps first** — headers that are missing or misconfigured relative to the recommended values.
<!-- gate: manage-headers:3.per-finding | category=plan | cancel-leaves=nothing -->
> 🚦 **Gate (plan · manage-headers:3.per-finding):** Per-finding loop — for each header gap, prompt accept / customize / skip. Fires PER FINDING in the loop; skipped findings leave the header at its current value, accepted/customized findings get an Edit / create-script call in Phase 4.
>
> **Trigger:** Phase 3 entry has tallied header gaps against `references/headers-reference.md`.
> **Why we ask:** Auto-accepting can apply CSP/CORS values that break the site (legitimate scripts blocked, third-party widgets refused); auto-skipping leaves the site missing important headers.
> **Cancel leaves:** Nothing — Phase 4's Edit / create-script call only fires on accepted findings.
For each finding, present via `AskUserQuestion`:
- A plain-language explanation of why the change matters
- The recommended value
- Options: accept the recommendation, customize, or skip
Do NOT present all headers at once — present the important gaps first. For headers already set to recommended values, mention them in the summary wGuide the user to add a data source, connection, or API connector to a Canvas App via Power Apps Studio, then verify and continue. USE WHEN the user asks to add a data source, add a connection, add an API, add a connector, connect to SharePoint / Dataverse / SQL / Excel / OneDrive / Teams / Office 365, or any similar request to make new data available to the app. DO NOT USE WHEN the user is asking to list or describe existing data sources — call list_data_sources or list_apis directly instead.
Creates or edits a Power Apps Canvas App through the Canvas Authoring MCP coauthoring session. Handles new app generation from requirements, simple inline edits, and complex multi-screen changes with parallel screen builders. Triggers on requests to create, build, generate, modify, update, change, or edit a Canvas App or .pa.yaml files.
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.
[DEPRECATED — use canvas-app instead] Generate a complete Power Apps canvas app.
>
Adds Azure DevOps connector to a Power Apps code app. Use when querying work items, creating bugs, managing pipelines, or making ADO API calls.
Adds any Power Platform connector to a Power Apps code app. Generic fallback for connectors not covered by a specific skill.
Adds a data source or connector to a Power Apps code app. Asks what the user wants to accomplish and routes to the appropriate specialized skill.