{
  "id": "CB-M365-POWER-007",
  "standard": "m365",
  "version": "main",
  "url": "https://baselines.cirsec.org/b/m365/CB-M365-POWER-007",
  "json": "https://baselines.cirsec.org/b/m365/CB-M365-POWER-007.json",
  "yaml": "https://baselines.cirsec.org/b/m365/CB-M365-POWER-007.yml",
  "profiles_effective": [
    "baseline",
    "hardened"
  ],
  "license": "Text CC BY 4.0, code Apache-2.0",
  "attribution": "CIRSEC Baselines, https://baselines.cirsec.org",
  "control": {
    "id": "CB-M365-POWER-007",
    "title": "Enforce Content Security Policy for model-driven and canvas apps",
    "finding": {
      "title": "Content Security Policy is not enforced for Power Apps",
      "description": "Model-driven or canvas apps are served without an enforced Content Security Policy, so they can be framed by any site and get no browser-side protection against injected content."
    },
    "status": "active",
    "profiles": [
      "baseline"
    ],
    "risk": {
      "severity": "medium"
    },
    "assessment": "manual",
    "tags": [
      "power-platform",
      "power-apps",
      "csp",
      "clickjacking",
      "dataverse"
    ],
    "description": "In every Power Platform environment with a Dataverse database, the **Privacy + Security**\nsettings enforce Content Security Policy for both app types: **Enforce content security policy**\nis **On** for **Model-driven** and for **Canvas**. The `frame-ancestors` directive keeps its\ndefault value (`'self' https://*.powerapps.com`) or lists only the approved hosts that embed the\napps (Teams, Outlook, Power BI, intranet).\n",
    "rationale": "An enforced CSP header tells the browser which origins may frame the app and load resources.\nWithout it, a malicious site can embed a Power App in a hidden frame and trick users into\nclicking (clickjacking), and injected content is not constrained by the browser. Turning on\nenforcement is a low-cost, platform-provided layer of defense.\n",
    "impact": "Apps embedded in hosts not listed in `frame-ancestors` stop loading in those hosts. Strict mode\ncan block custom scripts or resources loaded from other origins. Enable reporting with an\nendpoint first (report-only mode), enforce on a test environment, then in production once no\nviolation is reported. Environments without Dataverse are out of scope.\n",
    "audit": {
      "manual": "1. Sign in to the Power Platform admin center (https://admin.powerplatform.microsoft.com) as at\n   least a Global Reader, or as an environment admin of each environment.\n2. Browse to **Manage** > **Environments** and, for each environment with Dataverse, select it,\n   then **Settings** > **Product** > **Privacy + Security**.\n3. Under **Content security policy**, check on both the **Model-driven** and **Canvas** pivots\n   that **Enforce content security policy** is **On**, and review the `frame-ancestors` sources.\n4. Alternative, read only: Dataverse Web API\n   `GET https://<org>.crm.dynamics.com/api/data/v9.2/organizations?$select=iscontentsecuritypolicyenabled,iscontentsecuritypolicyenabledforcanvas,contentsecuritypolicyconfiguration`\n   with a user who can read the organization table.\n5. Fail if enforcement is off for either app type in any Dataverse environment, or if\n   `frame-ancestors` contains a wildcard host.\n"
    },
    "remediation": {
      "manual": "1. For each Dataverse environment, browse to **Manage** > **Environments** > select it >\n   **Settings** > **Product** > **Privacy + Security**. Role: Power Platform Administrator, or\n   System Administrator of the environment.\n2. Turn on **Enable reporting** with a reporting endpoint, and leave enforcement off for a few\n   days to collect violations (report-only mode).\n3. Add the legitimate embedding hosts to `frame-ancestors` (for example\n   `https://teams.microsoft.com/` for Teams integration).\n4. Turn on **Enforce content security policy** on the **Model-driven** pivot, then on the\n   **Canvas** pivot, starting with test environments.\n5. Equivalent: set the organization columns `iscontentsecuritypolicyenabled` and\n   `iscontentsecuritypolicyenabledforcanvas` to `true` through the Dataverse Web API.\n",
      "rollback": "Turn **Enforce content security policy** off for the affected app type; keep reporting on.\n"
    },
    "references": [
      {
        "title": "Content security policy",
        "url": "https://learn.microsoft.com/power-platform/admin/content-security-policy",
        "publisher": "Microsoft",
        "kind": "vendor-doc",
        "accessed": "2026-10-24"
      },
      {
        "title": "CISA SCuBA Power Platform baseline",
        "url": "https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/baselines/powerplatform.md",
        "publisher": "CISA",
        "kind": "standard",
        "accessed": "2026-10-24"
      }
    ],
    "mappings": [
      {
        "framework": "cisa-scuba-m365",
        "framework_version": "2.0.0",
        "id": "MS.POWERPLATFORM.4.1v1",
        "relation": "equivalent"
      },
      {
        "framework": "nist-800-53r5",
        "framework_version": "5.1.1",
        "id": "SI-10",
        "relation": "related"
      },
      {
        "framework": "nist-800-53r5",
        "framework_version": "5.1.1",
        "id": "SC-18",
        "relation": "related"
      }
    ],
    "threats": [
      {
        "framework": "mitre-attack",
        "id": "T1189"
      }
    ],
    "authors": [
      {
        "name": "Alice",
        "github": "Sn0wAlice"
      }
    ],
    "introduced_in": "0.1.0",
    "created": "2026-10-24",
    "updated": "2026-10-24"
  }
}