<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: xiwuqi</title>
    <description>The latest articles on DEV Community by xiwuqi (@xiwuqi_).</description>
    <link>https://dev.to/xiwuqi_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3896960%2F3183ee17-29e7-4cb2-8096-f000bc028382.jpeg</url>
      <title>DEV Community: xiwuqi</title>
      <link>https://dev.to/xiwuqi_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xiwuqi_"/>
    <language>en</language>
    <item>
      <title>Reviewing AI Agent Permission Changes Before Merge</title>
      <dc:creator>xiwuqi</dc:creator>
      <pubDate>Sat, 25 Apr 2026 04:18:11 +0000</pubDate>
      <link>https://dev.to/xiwuqi_/reviewing-ai-agent-permission-changes-before-merge-5a0m</link>
      <guid>https://dev.to/xiwuqi_/reviewing-ai-agent-permission-changes-before-merge-5a0m</guid>
      <description>&lt;p&gt;AI coding agents are changing what belongs in code review.&lt;/p&gt;

&lt;p&gt;A pull request may no longer be only application code. It might also add an MCP server, modify &lt;code&gt;AGENTS.md&lt;/code&gt;, change Cursor or Claude rules, expand GitHub Actions permissions, or add package lifecycle scripts.&lt;/p&gt;

&lt;p&gt;Those changes are worth reviewing because they can alter what tools an agent can run, which tokens it expects, or what CI automation can publish or deploy.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/xiwuqi/scopediff" rel="noopener noreferrer"&gt;ScopeDiff&lt;/a&gt; as a small local CLI to make those changes visible before merge.&lt;/p&gt;

&lt;p&gt;ScopeDiff is a review aid, not a complete security audit. It does not claim to prevent every AI agent or MCP risk. The goal is simpler: make permission and tooling changes easier to notice during ordinary PR review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr160qak8nu2hakqdye7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr160qak8nu2hakqdye7.png" alt="ScopeDiff overview showing the tagline: Review AI agent and workflow permission changes before merge." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Agent-related configuration is starting to live next to source code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP server definitions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; and other repo-level instructions&lt;/li&gt;
&lt;li&gt;Cursor rules&lt;/li&gt;
&lt;li&gt;Claude skills&lt;/li&gt;
&lt;li&gt;GitHub Actions workflows&lt;/li&gt;
&lt;li&gt;package lifecycle scripts&lt;/li&gt;
&lt;li&gt;Docker and compose files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of those files are harmless documentation. Some of them can change capability boundaries.&lt;/p&gt;

&lt;p&gt;For example, a PR might add an MCP server that expects &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;, switch a workflow to &lt;code&gt;pull_request_target&lt;/code&gt;, expand &lt;code&gt;contents&lt;/code&gt; from &lt;code&gt;read&lt;/code&gt; to &lt;code&gt;write&lt;/code&gt;, or add an unpinned &lt;code&gt;npx&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;None of those automatically means "bad". But they are review-worthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ScopeDiff checks
&lt;/h2&gt;

&lt;p&gt;ScopeDiff scans or diffs repository files such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.mcp.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mcp.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.cursor/mcp.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.cursor/rules/**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.claude/settings.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.claude/skills/**/SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEMINI.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.github/workflows/*.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env.example&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It produces Markdown and JSON reports with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;finding title&lt;/li&gt;
&lt;li&gt;severity&lt;/li&gt;
&lt;li&gt;file and line evidence&lt;/li&gt;
&lt;li&gt;confidence&lt;/li&gt;
&lt;li&gt;whether the finding appears to add a new capability&lt;/li&gt;
&lt;li&gt;whether it appears to expand permissions&lt;/li&gt;
&lt;li&gt;suggested review steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8k0gdlm4c4dq8ypwmy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8k0gdlm4c4dq8ypwmy5.png" alt="ScopeDiff diff report showing review findings for MCP and GitHub Actions changes." width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A small example
&lt;/h2&gt;

&lt;p&gt;Suppose a PR adds this MCP config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@modelcontextprotocol/server-github"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GITHUB_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GITHUB_TOKEN}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ScopeDiff can report things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP server added&lt;/li&gt;
&lt;li&gt;credential-like env var referenced&lt;/li&gt;
&lt;li&gt;unpinned remote package&lt;/li&gt;
&lt;li&gt;executable command introduced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the same PR also changes a workflow from &lt;code&gt;pull_request&lt;/code&gt; to &lt;code&gt;pull_request_target&lt;/code&gt; and expands &lt;code&gt;contents&lt;/code&gt; to &lt;code&gt;write&lt;/code&gt;, ScopeDiff reports those changes too.&lt;/p&gt;

&lt;p&gt;The point is not to block the PR automatically. The point is to give the reviewer a concise checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this server needed?&lt;/li&gt;
&lt;li&gt;Should the package version be pinned?&lt;/li&gt;
&lt;li&gt;Does this token need write access?&lt;/li&gt;
&lt;li&gt;Is this safe for PRs from forks?&lt;/li&gt;
&lt;li&gt;Should this run in CI, or only in a trusted workflow?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;You can try the published package with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx scopediff@latest scan
npx scopediff@latest diff &lt;span class="nt"&gt;--base&lt;/span&gt; main
npx scopediff@latest report &lt;span class="nt"&gt;--format&lt;/span&gt; markdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ScopeDiff&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scopediff&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx scopediff@0.1.0 ci --fail-on high&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the CI mode writes to the GitHub Step Summary. It does not comment on PRs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpn3c4zz4j1hx33tibwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpn3c4zz4j1hx33tibwg.png" alt="GitHub Actions summary screenshot showing a ScopeDiff CI report." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety and privacy choices
&lt;/h2&gt;

&lt;p&gt;For v0.1.0, ScopeDiff is intentionally conservative:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local-first&lt;/li&gt;
&lt;li&gt;read-only scanning&lt;/li&gt;
&lt;li&gt;no telemetry&lt;/li&gt;
&lt;li&gt;no code upload&lt;/li&gt;
&lt;li&gt;no hidden network requests&lt;/li&gt;
&lt;li&gt;no &lt;code&gt;.env&lt;/code&gt; reading by default&lt;/li&gt;
&lt;li&gt;no PR comments by default&lt;/li&gt;
&lt;li&gt;no package reputation lookup&lt;/li&gt;
&lt;li&gt;no attempt to execute detected commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The report should help a maintainer decide what to review, not replace human judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;p&gt;ScopeDiff is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a complete security audit&lt;/li&gt;
&lt;li&gt;a vulnerability scanner&lt;/li&gt;
&lt;li&gt;an MCP firewall&lt;/li&gt;
&lt;li&gt;a package reputation service&lt;/li&gt;
&lt;li&gt;a sandbox&lt;/li&gt;
&lt;li&gt;a guarantee that a PR is safe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can miss things. It can also produce false positives. That is why the report includes evidence and suggested review actions instead of pretending every finding is an exploit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where feedback would help
&lt;/h2&gt;

&lt;p&gt;The most useful feedback right now is practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP config shapes ScopeDiff misses&lt;/li&gt;
&lt;li&gt;Cursor/Claude/Codex instruction patterns worth detecting&lt;/li&gt;
&lt;li&gt;GitHub Actions permission expansion cases that should be covered&lt;/li&gt;
&lt;li&gt;noisy findings that should be lower severity&lt;/li&gt;
&lt;li&gt;report wording that would help maintainers review faster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/xiwuqi/scopediff" rel="noopener noreferrer"&gt;https://github.com/xiwuqi/scopediff&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm: &lt;a href="https://www.npmjs.com/package/scopediff" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/scopediff&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If ScopeDiff helps you review agent/tooling changes, feedback is welcome. If it is useful, a star helps other maintainers find it.&lt;/p&gt;

&lt;p&gt;Disclosure: I used an AI coding assistant to help draft and edit this post, then reviewed and approved the content before publishing.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
