Kunal-Murarka/powerapps-codeapps-pac-scan

GitHub: Kunal-Murarka/powerapps-codeapps-pac-scan

面向 Power Apps Code Apps 的构建时安全扫描器,在开发阶段离线检测 DLP 违规、CSP 违规、硬编码凭据、不安全网络请求和依赖项漏洞,避免策略冲突在运行时才以静默故障暴露。

Stars: 0 | Forks: 0

# pac-scan **[Power Apps Code Apps](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview) 的构建时安全扫描器**(React / Vue + Vite)。 pac-scan 能够在 DLP 违规、CSP 违规、硬编码的秘密信息、不安全的 fetch 调用以及易受攻击的依赖项**演变成 Power Apps Player 沙箱中静默的运行时故障之前**将它们捕获。 ## 什么是 Code Apps? [Power Apps Code Apps](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview) 允许开发者将 Power Apps 的功能引入到在代码优先 IDE 中构建的自定义 Web 应用中。你可以使用 React 或 Vue 等框架在本地进行构建,然后在 Power Platform 中发布并托管该应用——它将在平台的**托管策略**下运行:DLP、CSP、条件访问和连接器权限。 由于这些策略是由 Power Platform 管理员(而非开发者)设置的,因此违规行为在开发期间是静默的,只有在 Power Apps Player 沙箱内部运行时才会以故障的形式暴露出来。pac-scan 通过拉取实时策略的快照并在**构建时完全离线**运行所有检查来弥补这一差距。 ### pac-scan 能捕获的问题一览 | 规则 | 检测内容 | 严重性 | 漏检后果 | |---|---|---|---| | **PAC001** | 硬编码的秘密信息(API 密钥、token、GUID) | CRITICAL | 缓存包中的凭据泄露 | | **PAC002** | 对未加入允许列表的域的 `fetch()` / XHR 调用 | HIGH | 运行时出现静默网络故障 | | **PAC003** | 受阻或非业务连接器的使用 | CRITICAL | 应用崩溃且无回退机制 | | **PAC004** | `eval()`、`innerHTML`、宽松的 CSP 头 | HIGH | Player 沙箱内出现 CSP 拒绝 | | **PAC005** | npm audit 严重/高危公告 | CRITICAL | 生产包中存在可被利用的依赖项 | ## 前置条件 | 需求 | 说明 | |---|---| | **Node.js 18+ (LTS)** | [下载](https://nodejs.org/) | | **pac CLI** | 仅 `pac-scan fetch` 需要。安装命令:`npm install -g @microsoft/powerplatform-cli` · [文档](https://learn.microsoft.com/power-platform/developer/cli/introduction) | | **已启用 Code Apps** | Power Platform 管理员必须在目标环境中启用 Code Apps:管理中心 → 环境 → 选择环境 → 设置 → 功能 → **启用代码应用**。 | | **Power Apps 高级版许可证** | 运行代码应用的最终用户需要拥有 [Power Apps 高级版许可证](https://www.microsoft.com/power-platform/products/power-apps/pricing)。 | ## 为什么需要它 Power Apps Code Apps 运行在 Power Apps Player 内部,这是一个受两层策略严格管理的紧密沙箱 iframe: | 层级 | 执行内容 | |---|---| | **DLP 策略** | 应用可以使用哪些连接器。管理员可以随时阻止某个连接器——你的应用将停止工作,且没有任何构建时的警告。 | | **CSP 指令** | `fetch()` / XHR 可以访问哪些域,允许哪些脚本来源,以及哪些域可以嵌入播放器。 | 这两层均由 Power Platform 管理员配置,而非开发者。 **Solution Checker**——标准的 Power Platform 静态分析工具——涵盖了画布应用、模型驱动应用和 Power Automate 流。然而,**它并不分析 Code Apps 的源代码**,因为 Code Apps 是在平台的低代码创作界面之外构建的自定义 JavaScript/TypeScript 包。 pac-scan 填补了这一空白:它只需拉取一次实时策略的快照,随后的每次扫描都会完全离线运行——无需网络,无遥测,也没有数据流出边界。 ## 快速开始 ``` # 1. 安装 pac CLI(一次性操作 — 如已安装请跳过) npm install -g @microsoft/powerplatform-cli # 2. 认证 pac CLI(一次性操作 — 打开浏览器登录) pac auth create # 按照浏览器提示使用您的 Power Platform 账户登录。 # 验证:pac auth list(查找标有 * 表示当前活跃的条目) # 3. 安装 pac-scan npm install --save-dev github:Kunal-Murarka/powerapps-codeapps-pac-scan ``` 接下来,在你的项目根目录中创建 `pac-scan.config.yaml`(完整参考请参见[配置](#configuration-pac-scanconfigyaml))。最小示例: ``` default_environment: prod environments: prod: dlp_snapshot: .pac-scan/current/prod.json csp_snapshot: .pac-scan/current/prod.json environment_url: https://your-org.crm.dynamics.com/ fail_on_severity: prod: MEDIUM scan_paths: [src] scan_extensions: [.ts, .tsx, .js, .jsx] ``` ``` # 4. 拉取实时策略(写入 .pac-scan/current/prod.json) npx pac-scan fetch --env prod # 5. 扫描 npx pac-scan run --env prod # 不确定一切是否设置正确?先运行验证器: npx pac-scan validate ``` ## CLI 命令 ### `pac-scan fetch` 从 Power Platform 拉取实时的 DLP 和 CSP 策略,并将快照写入 `.pac-scan/current/.json`。 ``` pac-scan fetch --env prod pac-scan fetch --env dev --environment-id 00000000-0000-0000-0000-000000000000 pac-scan fetch --env uat --verbose ``` 选项: | 标志 | 默认值 | 描述 | |---|---|---| | `--env ` | 配置中的 `default_environment` | 目标环境名称 | | `--environment-id ` | 自动检测 | 覆盖 Power Platform 环境 GUID | | `--config ` | 自动检测 | `pac-scan.config.yaml` 的路径 | | `--verbose` | false | 打印详细的拉取进度 | 需要 pac CLI 已安装并完成身份验证: ``` npm install -g @microsoft/powerplatform-cli pac auth create # opens a browser — sign in with your Power Platform account ``` ### `pac-scan run` 根据保存的快照扫描源文件。完全离线运行。 ``` pac-scan run --env prod pac-scan run --env dev --fail-on CRITICAL pac-scan run --env uat --output ./reports --format json ``` 选项: | 标志 | 默认值 | 描述 | |---|---|---| | `--env ` | 配置中的 `default_environment` | 目标环境 | | `--fail-on ` | 配置中的 `fail_on_severity` | 覆盖失败阈值 | | `--path ` | `cwd` | 要扫描的根目录 | | `--output ` | `cwd` | 写入 JSON 报告的目录 | | `--format terminal\|json` | `terminal` | 输出格式 | | `--verbose` | false | 扫描时打印每个文件 | 退出代码 0 = 通过,退出代码 1 = 失败或错误。 ### `pac-scan diff` 比较同一环境的两个快照,显示日期之间的策略变化。适用于解答“为什么在管理员更改 DLP 策略后,我的扫描开始失败了?” ``` pac-scan diff --env prod --from 2026-05-01 --to 2026-05-05 pac-scan diff --env prod --from 2026-05-01 --to 2026-05-05 --format json ``` 选项: | 标志 | 默认值 | 描述 | |---|---|---| | `--env ` | 必填 | 要比较的环境 | | `--from ` | 必填 | 基准日期 (`YYYY-MM-DD`) —— 查找最近的快照 | | `--to ` | 必填 | 目标日期 (`YYYY-MM-DD`) —— 查找最近的快照 | | `--format terminal\|json` | `terminal` | 输出格式 | | `--config ` | 自动检测 | 配置文件路径 | ### `pac-scan policy` 显示当前策略快照的格式化视图——DLP 策略、连接器风险层级、端点过滤器 URL 和 CSP 指令。 ``` pac-scan policy --env prod pac-scan policy --env dev --format json ``` 选项: | 标志 | 默认值 | 描述 | |---|---|---| | `--env ` | 配置中的 `default_environment` | 目标环境 | | `--format terminal\|json` | `terminal` | 输出格式 | | `--config ` | 自动检测 | 配置文件路径 | ### `pac-scan validate` 检查你的设置是否完整且正确。在建立新项目或调试意外故障时,请首先运行此命令。 ``` pac-scan validate pac-scan validate --env dev ``` 检查项: - 配置文件存在且语法有效 - 所有配置的快照文件均存在于磁盘上 - pac CLI 已安装并在 PATH 中 - pac CLI 至少有一个已认证的配置文件 ## 配置:`pac-scan.config.yaml` 将此文件放置在你的项目根目录中(pac-scan 会从 `cwd` 向上搜索以找到它): ``` default_environment: prod environments: dev: dlp_snapshot: .pac-scan/current/dev.json csp_snapshot: .pac-scan/current/dev.json environment_url: https://org-dev.crm.dynamics.com/ # environment_id: 00000000-0000-0000-0000-000000000000 # optional: skip pac org list lookup uat: dlp_snapshot: .pac-scan/current/uat.json csp_snapshot: .pac-scan/current/uat.json environment_url: https://org-uat.crm.dynamics.com/ prod: dlp_snapshot: .pac-scan/current/prod.json csp_snapshot: .pac-scan/current/prod.json environment_url: https://org.crm.dynamics.com/ # 按环境划分的导致构建失败的最低严重级别 fail_on_severity: dev: CRITICAL uat: HIGH prod: MEDIUM # 要扫描的源文件 scan_paths: [src] scan_extensions: [.ts, .tsx, .js, .jsx] ``` ## Git hook 当任何发现项达到 `dev` 阈值(默认为 CRITICAL)时,阻止提交。 ``` # 安装(跨平台,覆盖前会提示) npm run install-hooks # 或在 Unix/macOS 上手动执行 bash scripts/install-hooks.sh # 或在 Windows (PowerShell) 上 .\scripts\install-hooks.ps1 ``` 在紧急情况下跳过检查:`git commit --no-verify` ## Azure DevOps 流水线 完整的 4 阶段流水线请参见 [examples/azure-devops-pipeline.yml](examples/azure-devops-pipeline.yml)。 快速参考——将以下两个步骤添加到任何现有流水线中: ``` - script: npm install -g pac-scan displayName: 'Install pac-scan' - task: PACSecurityScan@1 displayName: 'Run Security Scan' inputs: command: run environment: prod failOnSeverity: HIGH outputPath: $(Build.ArtifactStagingDirectory)/scan-report.json ``` **将 `PACSecurityScan@1` 任务发布到你的 Azure DevOps 组织:** ``` # 1. 安装扩展打包工具 npm install -g tfx-cli # 2. 构建任务 cd azure-devops-task npm install npm run build # 3. 在 https://marketplace.visualstudio.com/manage/publishers 创建发布者 # 然后在下方将 PUBLISHER 设置为您的发布者 ID # 4. 打包扩展(创建一个 .vsix 文件) tfx extension create --manifest-globs vss-extension.json # 5. 发布(或通过 Marketplace 门户手动上传 .vsix) tfx extension publish --publisher ``` 或者,将 `azure-devops-task/` 文件夹直接复制到你的流水线仓库中,并通过将 `task.json` 的 `execution.Node20.target` 设置为正确的相对路径,将其作为本地任务引用。 ## GitHub Actions 完整的 5 作业工作流请参见 [examples/github-actions-workflow.yml](examples/github-actions-workflow.yml)。 快速参考——将此步骤添加到任何作业中: ``` - uses: your-org/pac-scan-action@v1 id: scan with: command: run environment: prod fail-on-severity: HIGH output-path: ./pac-scan-report.json ``` **发布该 Action 以便工作流可以引用它:** ``` # 1. 构建该 action cd github-action npm install npm run build # 2. 为该 action 创建一个新的 GitHub 仓库 # 例如:your-org/pac-scan-action gh repo create your-org/pac-scan-action --public # 3. 复制 action 文件到该仓库并 push cp -r github-action/. /path/to/pac-scan-action/ cd /path/to/pac-scan-action git init && git add -A git commit -m "feat: initial release v1" git tag v1 git remote add origin https://github.com/your-org/pac-scan-action.git git push origin main --tags ``` 然后在工作流中引用它:`uses: your-org/pac-scan-action@v1`。 ## 5 项规则 ### PAC001 — 硬编码的秘密信息 (CRITICAL) 检测源文件中硬编码的 API 密钥、Bearer token、客户端密码、租户/应用程序 GUID、Azure 存储账户密钥和私钥头。 **重要性:** Power Apps Player 可能会将应用包缓存在浏览器存储中,并且 Code Apps 有时会被部署到共享租户中。泄露的密钥就是泄露的密钥。 **排除项:** 测试文件(`*.test.ts`、`*.spec.ts`)、引用环境变量的代码行(`process.env.`、`import.meta.env.`、`EnvVar(`、`getEnvironmentVariable(`)以及注释行不会被标记。 **修复方法:** 使用 `@microsoft/powerplatform-envvar` 在运行时读取环境变量。切勿将凭据放入源代码中。 ### PAC002 — 对未加入允许列表的域的原始 fetch 请求 (HIGH / MEDIUM) 检测指向不在快照的 `connect_src` 列表或连接器端点过滤器中的域的 `fetch()`、`axios.*()` 和 `XMLHttpRequest.open()` 调用。 | 严重性 | 触发条件 | |---|---| | HIGH | 静态 URL,明确不在允许列表中 | | MEDIUM | 动态 URL(带有插值的变量或模板字面量) | **重要性:** Power Apps Player CSP 会阻止对不在 `connect-src` 中的任何域的 `fetch()` 调用。该调用会在运行时以网络错误静默失败——这不是一个有用的错误提示。 **修复方法:** 将该域添加到 Power Platform 管理中心的 DLP 策略端点过滤器中,然后运行 `pac-scan fetch` 刷新快照。 ### PAC003 — DLP 连接器违规 (CRITICAL / HIGH / MEDIUM) 检测在环境的 DLP 策略中被分类为已阻止或非业务的连接器的导入、`connectorName:` 赋值和 `useConnector()` 调用。 | 严重性 | 分类 | |---|---| | CRITICAL | 连接器在**已阻止**列表中 | | HIGH | 连接器在**非业务**列表中 | | MEDIUM | 在快照中完全找不到该连接器 | **重要性:** 被阻止的连接器调用会在 Power Apps Player 运行时引发错误。且没有任何回退机制。 ### PAC004 — CSP 违规 (HIGH / MEDIUM) 检测 Power Apps Player CSP 会拒绝的模式: - `eval()`、`new Function(string)`、`setTimeout(string, ...)` —— 违反 `script-src` - 包含 `` —— 违反 `frame-ancestors` - `vite.config` CSP 头包含 `'unsafe-inline'`、`'unsafe-eval'`、`*` 或 `data:` —— 宽松的 CSP 会泄露出去 **修复方法:** 用 JSON 解析器或合适的表达式库替换 `eval()`。用箭头函数替换基于字符串的 `setTimeout`。对动态内容使用 `textContent` 而不是 `innerHTML`。 ### PAC005 — 易受攻击的依赖项 (CRITICAL / HIGH) 在项目目录中运行 `npm audit --json`,并将严重和高危的公告作为发现项列出。 **重要性:** Code Apps 作为静态包部署。包中易受攻击的依赖项与任何 Web 应用中的一样容易被利用。 **优雅降级:** 如果找不到 npm、缺少 `package.json` 或审计超时,PAC005 会发出一条 INFO 发现项并干净地退出——它绝不会阻止扫描。 ## 如何阅读报告 ### 终端输出 ``` ┌─────────────────────────────────────────────────────┐ │ pac-scan v1.0.0 env: prod 2026-05-06 14:32:01 │ └─────────────────────────────────────────────────────┘ environment prod snapshot age 2h 14m files scanned 47 rules run 5 ❌ [PAC001] CRITICAL src/services/api.ts:12:17 Hardcoded secret: "apiKey" pattern matched Fix: Use @microsoft/powerplatform-envvar ───────────────────────────────────────── 11 | const config = { > 12 | apiKey: "sk-live-abc123def456ghi789", 13 | endpoint: "https://api.example.com", ``` ### JSON 报告 以 `pac-scan-report--.json` 形式写入输出目录。 关键字段: ``` { "scan_id": "uuid", // unique per run "result": "PASS | FAIL", "snapshot_age_hours": 2.2, // hours since fetch "snapshot_warned": false, // true when > 24 hours "summary": { "total": 5, "critical": 1, "high": 2, "medium": 2 }, "findings": [ { "rule_id": "PAC001", "severity": "CRITICAL", "file": "src/services/api.ts", "line": 12, "column": 10, "message": "Hardcoded secret: ...", "remediation": "Use @microsoft/powerplatform-envvar", "code_snippet": "..." } ] } ``` ## 故障排除 ### "找不到 pac CLI" pac-scan 仅在 `fetch` 命令中调用 Microsoft `pac` CLI。`run`、`diff`、`policy` 和 `validate` 命令完全离线运行。 **修复方法:** ``` npm install -g @microsoft/powerplatform-cli pac auth create ``` 验证:`pac --version` ### "找不到环境的 snapshot" 尚未对该环境运行过 `fetch` 命令,或者快照被写入到了不同的路径。 **方法:** ``` pac-scan fetch --env ``` 快照保存至 `.pac-scan/current/.json`。请将 `snapshots/` 目录提交到版本控制中,以便 CI 代理无需实时 `fetch` 步骤即可访问。 ### "Snapshot 已过期" 快照存在时间超过 24 小时。这是一个警告,而非错误——扫描仍会运行。 **修复方法:** ``` pac-scan fetch --env ``` 对于 CI/CD,请包含一个专用的 fetch 作业(或步骤),在扫描作业之前运行,并将快照作为流水线构件上传。请参见 `examples/` 中的示例流水线。 ## VS Code 扩展 `vscode-extension/` 文件夹包含一个功能齐全的 VS Code 扩展,它可以: - 当工作区包含 `pac-scan.config.yaml` 时自动**激活** - 在行内**波浪线提示**发现项(红色代表 CRITICAL/HIGH,黄色代表 MEDIUM) - 显示按文件分组的**结果面板** (webview) —— 点击任意发现项即可跳转 - **状态栏**项显示实时状态:`$(shield) PAC Scan` → `$(sync~spin) PAC: Scanning…` → `$(pass-filled) PAC: Clean` / `$(error) PAC: N issues` **命令面板中可用的命令:** | 命令 | 描述 | |---|---| | `PAC: Run Security Scan` | 在工作区上运行完整扫描 | | `PAC: Scan This File` | 在 `.ts` / `.tsx` 文件上的上下文菜单 | | `PAC: Refresh Policy Snapshot` | 为当前环境运行 `pac-scan fetch` | | `PAC: Show Last Report` | 打开结果 webview 面板 | **设置:** ``` // .vscode/settings.json { "pac-scan.environment": "dev" // override default_environment from config } ``` **本地构建和安装:** ``` # 1. 安装 VS Code 扩展打包工具 npm install -g @vscode/vsce # 2. 构建扩展 cd vscode-extension npm install npm run build # 3. 打包为 .vsix 文件 vsce package # 生成文件:pac-scan-vscode-0.1.0.vsix # 4. 在 VS Code 中安装 # 扩展面板 (Ctrl+Shift+X) → ⋯ 菜单 → Install from VSIX → 选择该 .vsix 文件 # 或通过终端: code --install-extension pac-scan-vscode-0.1.0.vsix ``` ## 仓库结构 ``` powerapps-codeapps-pac-scan/ ├── src/ │ ├── cli.ts ← entry point (all 5 commands registered) │ ├── commands/ ← fetch, run, diff, policy, validate │ ├── rules/ ← PAC001–PAC005 scan rules │ ├── scanner/ ← file walker + scan orchestrator │ ├── reporter/ ← terminal + JSON report writers │ ├── snapshot/ ← schema + loader │ └── config/ ← config loader (yaml + validation) ├── vscode-extension/ ← VS Code extension (diagnostics + webview) ├── azure-devops-task/ ← Azure Pipelines task (PACSecurityScan@1) ├── github-action/ ← GitHub Actions action ├── scripts/ ← git hook installers (bash / PS / Node) ├── examples/ ← complete pipeline YAML examples ├── .pac-scan/ ← snapshot storage (commit this directory) │ ├── current/.json ← latest snapshot per environment │ └── snapshots// ← full history (used by diff) └── pac-scan.config.yaml ← project configuration ``` ## 贡献 / 开发设置 ``` # 安装根目录依赖项 npm install # 构建 CLI npm run build # 从源码运行 CLI node dist/cli.js --help # 构建 VS Code 扩展 cd vscode-extension && npm install && npm run build # 构建 Azure DevOps 任务 cd azure-devops-task && npm install && npm run build # 构建 GitHub Action cd github-action && npm install && npm run build ``` ## 许可证 MIT
标签:CSP, DevSecOps, DLP, MITM代理, npm audit, Power Apps, Power Platform, React, Syscalls, Vite, Vue, Web安全, 上游代理, 云安全监控, 代码安全, 依赖漏洞扫描, 内容安全策略, 前端安全, 安全助手, 安全合规, 安全扫描, 安全标准, 文件系统扫描, 时序注入, 构建时检查, 沙箱, 漏洞枚举, 硬编码密钥检测, 离线安全扫描, 网络代理, 自动化攻击, 蓝队分析, 规则仓库, 静态分析