Newshot
Account

Agent-access-review – an access review for AI agents' MCP configs

Original text(via HN AI)

agent-access-review

PyPI
PyPI

User access reviews for AI agents. It finds every agent and MCP server an organization runs, works out what each one can read, write, execute and send, tests that access against 12 controls, and produces the packet an auditor expects: a reviewer sign-off sheet, hashed evidence, and OSCAL assessment results mapped to NIST 800-53, SOC 2, NIST AI RMF and the OWASP Top 10 for LLM Applications.

In one sentence: the quarterly "who has access to what?" review that companies already run for employees, applied to AI agents.
agent-access-review demo: scanning five agents, then the AAR-09 exfiltration-path finding
agent-access-review demo: scanning five agents, then the AAR-09 exfiltration-path finding
Real-world case study: what you get by copying the MCP configs from official READMEs: 8 of 9 unpinned, 7 of 9 with unreviewed write/send/execute access, and an exfiltration path once they're combined.
The sample report this tool produces, from sample-output/access-review.md
The sample report this tool produces, from sample-output/access-review.md

Quick start (2 minutes)

You need Python 3.11+. No cloud account, API keys or network access.


        pip install agent-access-review
agent-access-review demo
      

demo reviews five example agents and writes the packet to review-demo/. Open review-demo/access-review.md, or just read the sample report here without installing anything.

Then review your own setup:

ToolWhere its MCP config livesCommand
Claude Desktop (macOS)~/Library/Application Support/Claude/claude_desktop_config.jsonagent-access-review scan ~/Library/Application\ Support/Claude/claude_desktop_config.json
Claude Desktop (Windows)%APPDATA%\Claude\claude_desktop_config.jsonPowerShell: agent-access-review scan "$env:APPDATA\Claude\claude_desktop_config.json"
Cursor~/.cursor/mcp.json (global) or .cursor/mcp.json (project)agent-access-review scan ~/.cursor/mcp.json
VS Code.vscode/mcp.json in a projectagent-access-review scan .vscode/mcp.json
Your own agentsan agents.yaml you maintainagent-access-review scan agents.yaml

Secrets in your configs are masked before anything is written, so the output is safe to share.

TermMeaning
AI agentAn AI model that can take actions through tools: read files, query databases, send email, run commands.
MCP (Model Context Protocol)The standard way apps like Claude Desktop, Cursor and VS Code plug tools into an AI. Each "MCP server" in a config is one tool the agent can use.
User access review (UAR)The periodic check where each person's access is listed, an owner confirms it's still needed, and the rest is revoked. Auditors test it under SOX and SOC 2.
ITGCIT General Controls: the baseline controls (access, change management, operations) auditors test for financial reporting.
Non-human identityAn account used by software rather than a person: service accounts, API keys, and now AI agents.
Exfiltration pathA route for data to leave the organization. Here: an agent that can read sensitive data, reads content an attacker can write, and can send data out.
Prompt injectionHiding instructions in content an AI reads (an email, web page or ticket) so it does something its user never asked for.
OSCALNIST's machine-readable format for security controls and assessment results, so GRC tools can import findings automatically.

Problem

Every SOX and SOC 2 program runs quarterly user access reviews: list who has access to what, have an owner confirm it's still needed, revoke the rest, keep the evidence. AI agents now hold the same kind of access (API tokens, database connections, shell access, mailboxes), and almost nobody reviews them:

  • No owner, no approval. A developer adds an MCP server to their Claude Desktop or Cursor config and the agent instantly has their GitHub token and home directory. No ticket, no approver, and it never appears in an access review.
  • Over-broad by default. Setup guides tell people to grant the whole home directory, the full-control repo scope, or tenant-wide *.All Microsoft Graph permissions.
  • Secrets in plain text. MCP configs routinely hold raw tokens and database passwords.
  • A new attack path. An agent that can read sensitive data, read content an attacker wrote (a GitHub issue, an email, a web page), and send data out can be prompt-injected into leaking that data. No traditional access control looks at that combination.

Agents are non-human identities. They need the same joiner/mover/leaver and recertification controls as people, plus a few that are specific to AI.

What it checks

IDControlSeverityFrameworks
AAR-01Every agent has an accountable human ownerhighNIST 800-53 AC-2 · SOC 2 CC6.2 · AI RMF GOVERN 2.1
AAR-02Access is approved and recertified within 90 dayshigh / mediumAC-2 · CC6.2, CC6.3
AAR-03Privileged actions (write, delete, send) need human approvalhigh / mediumAC-6 · CC6.3 · AI RMF MAP 3.5 · OWASP LLM06
AAR-04Least privilege: no home directories, wildcards, admin or tenant-wide scopeshighAC-6 · CC6.3 · LLM06
AAR-05Code and shell execution is sandboxedhighCM-7, AC-6 · LLM05, LLM06
AAR-06No hardcoded credentialshighIA-5 · CC6.1
AAR-07Credentials rotated within 90 daysmedium / lowIA-5 · CC6.1
AAR-08Dormant access removed after 90 daysmedium / lowAC-2(3) · CC6.2
AAR-09No exfiltration path (sensitive data + untrusted input + egress, with no human gate)highAC-4 · AI RMF MEASURE 2.7 · LLM01, LLM02
AAR-10Tool packages pinned to a version or image digestmediumSR-3 · LLM03
AAR-11Remote MCP servers use HTTPShighSC-8 · CC6.7
AAR-12Every tool's capabilities are inventoriedmediumCM-8 · AI RMF GOVERN 1.6
AAR-13No deprecated or archived MCP servers (names the maintained replacement)highSA-22, SI-2 · CC7.1 · LLM03
AAR-14No MCP server versions with known vulnerabilities, and no packages published as malware (from an OSV snapshot)high / medium / lowRA-5, SI-2 · CC7.1 · LLM03

Each control is defined once in controls.yaml and cross-walked to every framework, so one test produces evidence for all of them. The mappings are my own judgment and should be checked against official crosswalks before being relied on in a real audit.

The AI-specific risk: exfiltration paths (AAR-09)

Traditional access reviews look at one permission at a time. For AI agents, the danger is a combination: an agent that can read sensitive data, reads content an outsider wrote, and can send data out. Each leg is harmless alone. Together, one prompt injection hidden in an email, ticket, issue or web page can instruct the agent to leak the data. A human approval step on any leg breaks the chain.


        flowchart TB
    subgraph BAD["❌ finance-ops-agent: flagged AAR-09"]
        direction LR
        U1["📨 Untrusted input<br/>anyone can email the AP inbox"] -->|"hidden instruction:<br/>forward vendor bank details"| A1(("🤖 agent"))
        D1[("🔒 Restricted data<br/>NetSuite vendor bills")] -->|reads| A1
        A1 -->|"sends email<br/>no human approval"| X1["🌐 Egress<br/>any recipient"]
    end
    subgraph GOOD["✅ support-copilot: passes"]
        direction LR
        U2["📨 Untrusted input<br/>customer tickets"] --> A2(("🤖 agent"))
        D2[("🔒 Confidential data<br/>ticket history")] --> A2
        A2 -->|"drafts reply"| H{{"👤 Human approves"}}
        H -->|sends| X2["Customer"]
    end
    BAD ~~~ GOOD

    classDef risk fill:#fee2e2,stroke:#dc2626,color:#7f1d1d
    classDef safe fill:#dcfce7,stroke:#16a34a,color:#14532d
    classDef gate fill:#fef3c7,stroke:#d97706,color:#78350f
    class U1,D1,X1 risk
    class U2,D2,X2 safe
    class H gate
      

This maps to OWASP LLM01 (prompt injection) and LLM02 (sensitive information disclosure), NIST 800-53 AC-4 (information flow enforcement) and NIST AI RMF MEASURE 2.7 (AI security and resilience).

How it works


        flowchart LR
    subgraph IN["📥 Inputs"]
        A["Claude Desktop / Cursor<br/>MCP configs"]
        B["VS Code<br/>.vscode/mcp.json"]
        C["agents.yaml<br/>LangChain · CrewAI · custom"]
    end
    subgraph CORE["⚙️ agent_access_review"]
        P["Parsers<br/>secrets redacted here"]
        K[("Capability catalog<br/>catalog.yaml")]
        I["Normalized inventory<br/>agent → grants + credentials"]
        X["14 checks<br/>AAR-01 … AAR-14"]
        M[("Control catalog<br/>controls.yaml")]
    end
    subgraph OUT["📤 Audit outputs"]
        R["access-review.md<br/>reviewer packet + sign-off"]
        S["access-review.csv<br/>Keep / Modify / Revoke"]
        E["evidence/*.json<br/>SHA-256 hashed"]
        O["OSCAL 1.1.2<br/>assessment results"]
    end
    A & B & C --> P --> I --> X
    K -. "what each server can do" .-> I
    M -. "NIST · SOC 2 · AI RMF · OWASP" .-> X
    X --> R & S & E & O

    classDef input fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
    classDef core fill:#ede9fe,stroke:#7c3aed,color:#3b0764
    classDef data fill:#fef3c7,stroke:#d97706,color:#78350f
    classDef output fill:#dcfce7,stroke:#16a34a,color:#14532d
    class A,B,C input
    class P,I,X core
    class K,M data
    class R,S,E,O output
      
  • Discover. Point it at files or folders. It reads two formats: MCP configs (Claude Desktop, Cursor, VS Code .vscode/mcp.json): local npx / uvx / docker servers and remote HTTP servers. These carry no owner or approval, which is exactly why they're the shadow-AI problem. Agent manifests (agents.yaml): a governed record for LangChain, CrewAI or custom agents, with owner, approval, tools, scopes, credentials and last-used dates.
  • MCP configs (Claude Desktop, Cursor, VS Code .vscode/mcp.json): local npx / uvx / docker servers and remote HTTP servers. These carry no owner or approval, which is exactly why they're the shadow-AI problem.
  • Agent manifests (agents.yaml): a governed record for LangChain, CrewAI or custom agents, with owner, approval, tools, scopes, credentials and last-used dates.
  • Classify. An MCP config only says which server runs, not what it can do. The capability catalog turns a server name into a grant: actions, data classification, whether it ingests untrusted content and whether it can send data out. Unknown servers are flagged (AAR-12), never assumed safe.
  • Redact, then hash. Secrets are masked during parsing, before anything is stored, so evidence can be shared with auditors. Each agent's inventory and redacted source record are hashed with SHA-256 over canonical JSON, so any later edit to the evidence is detectable.
  • Review. Every tool grant gets a recommended decision (Keep / Modify / Revoke / Investigate) and an empty column for the reviewer, the same shape as a user access review spreadsheet.
  • Export. OSCAL 1.1.2 assessment results: one observation per agent pointing at its evidence file and hash, and one finding per NIST 800-53 control objective.

The review cycle

It's the same quarterly user access review that SOX and SOC 2 auditors already test for people, run on agents:


        flowchart LR
    D["1 · Discover<br/>configs + manifests"] --> C["2 · Classify<br/>capability catalog"]
    C --> T["3 · Test<br/>12 controls"]
    T --> R{"4 · Owner review<br/>per tool grant"}
    R -->|Keep| E["5 · Evidence<br/>hashed JSON + OSCAL"]
    R -->|"Modify / Revoke"| F["Remediate<br/>ticket + fix"]
    F -->|re-scan| T
    E --> Q["6 · Recertify<br/>every 90 days"]
    Q -.-> D

    classDef step fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
    classDef decision fill:#fef3c7,stroke:#d97706,color:#78350f
    classDef fix fill:#fee2e2,stroke:#dc2626,color:#7f1d1d
    classDef done fill:#dcfce7,stroke:#16a34a,color:#14532d
    class D,C,T,Q step
    class R decision
    class F fix
    class E done
      
User access review (people)Agent access review (this tool)
HR feed lists every employeeConfigs and manifests list every agent and MCP server
Manager confirms each entitlementAgent owner marks each tool grant Keep / Modify / Revoke
Terminated users removedUnowned agents flagged (AAR-01), unused tools revoked (AAR-08)
Privileged access gets extra scrutinyWrite, send, delete and shell access need a human gate (AAR-03, AAR-05)
Screenshots and spreadsheets as evidenceHashed JSON evidence and OSCAL output

Sample run

The bundled examples are a developer's Claude Desktop config, a VS Code MCP config and three governed agents. The full output is committed in sample-output/: the reviewer packet, the decision sheet, hashed evidence and OSCAL.


        $ agent-access-review demo
AGENT                        TOOLS  HIGH   MED   LOW
support-copilot                  2     0     0     0
finance-ops-agent                4     4     3     0
devops-agent                     2     6     1     1
claude-desktop-config            6    12     5     1
vscode-mcp                       3     6     2     3
      

5 agents · 17 tool grants · 44 findings


        %%{init: {"themeVariables": {"pie1": "#dc2626", "pie2": "#f59e0b", "pie3": "#16a34a", "pieSectionTextColor": "#ffffff", "pieStrokeColor": "#ffffff"}}}%%
pie showData title Findings by severity
    "High" : 28
    "Medium" : 11
    "Low" : 5
      
ControlAgents failing
AAR-02 · Approved and recertified within 90 days4 / 5
AAR-03 · Human approval for privileged actions4 / 5
AAR-08 · Dormant access removed4 / 5
AAR-01 · Accountable owner3 / 5
AAR-04 · Least privilege3 / 5
AAR-09 · No exfiltration path3 / 5
AAR-05, 06, 07, 10, 122 / 5 each
AAR-11, 13, 141 / 5 each
ToolActionsDataRecommendedReviewer decision
netsuiteread, writerestrictedModify☐ Keep ☐ Modify ☐ Revoke
outlookread, sendconfidentialModify☐ Keep ☐ Modify ☐ Revoke
sharepointreadconfidentialModify☐ Keep ☐ Modify ☐ Revoke
expense-ocrreadconfidentialRevoke☐ Keep ☐ Modify ☐ Revoke
CheckSeverityFinding
AAR-09highExfiltration path: reads sensitive data, ingests untrusted content (outlook) and can send data out (outlook) with no human approval.
AAR-03highnetsuite can write restricted data without a human approving each action.
AAR-03highoutlook can send confidential data without a human approving each action.
AAR-04highOver-broad access on sharepoint: Sites.Read.All .
AAR-02mediumAccess was last approved 216 days ago by cfo-office (limit 90).
AAR-07mediumnetsuite.NETSUITE_TOKEN was last rotated 315 days ago (limit 90).
AAR-08mediumexpense-ocr has not been used for 164 days.

Some of what it finds:

  • finance-ops-agent reads vendor bills in NetSuite (restricted data), reads an inbox vendors can email (untrusted input) and can send email (egress), with no human approval. That's an AAR-09 exfiltration path: one crafted invoice email could get the agent to mail out vendor banking details. Its approval is also 216 days old, and its OCR tool hasn't been used in 164 days, so it's marked Revoke.
  • claude-desktop-config gives an agent the whole /Users/dev home directory, an unsandboxed terminal, a GitHub token and a database password in plain text, and runs four unpinned packages.
  • support-copilot passes every check: it writes to tickets, but a human approves before anything is sent.

CI regenerates sample-output/ on every push and fails if it differs from what's committed, so the sample always matches the current code.

How to read the results

Recommended decision (one per tool grant, in the packet and the CSV):

DecisionMeaningWhat the owner does
KeepNo findings on this toolConfirm it's still needed and sign off
ModifyThe access is needed but unsafe as configuredNarrow scopes, add human approval, move secrets to a vault, pin the version
RevokeUnused for 90+ daysRemove it; re-request if it's needed again
InvestigateThe tool isn't in the capability catalog, so its access can't be judgedFind out what it can do, then add it to catalog.yaml

Severity: high means fix before the agent's next use (an unowned agent, plaintext secrets, an exfiltration path). Medium means fix within the review cycle (stale approval, unpinned package). Low means a gap in evidence rather than a risk (no usage logs, no rotation date).

The reviewer fills in the empty Reviewer decision column and the sign-off table. The completed packet plus the hashed evidence files are the audit evidence for the review.

Run it

Install from a release (shown in the Quick start), or work from source (dependencies are pinned exactly in requirements.txt):


        git clone https://github.com/Mihirajmera/agent-access-review.git
cd agent-access-review
python -m venv .venv && source .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install -r requirements.txt

python -m agent_access_review demo                    # writes review-demo/
pytest -q
      

scan options: --out DIR (default review/), --as-of YYYY-MM-DD (date used for recertification, rotation and dormancy), --fail-on high|medium|low (exit 1 if a finding is at or above that severity). agent-access-review --help lists examples.

As a CI gate

Keep your MCP configs and agents.yaml in the repo, and block pull requests that give an agent unpinned, archived, vulnerable or over-privileged access:


        # .github/workflows/agent-access.yml
on: pull_request
permissions:
  contents: read
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Mihirajmera/[email protected]   # or a commit SHA
        with:
          paths: .mcp.json .vscode/mcp.json agents.yaml   # files or folders; default "."
          fail-on: high                                    # high | medium | low | never
      

The review packet goes into the job summary, and the step fails on findings at or above fail-on. A repo with no configs gets a notice instead of a failure. The report output holds the packet's path, so you can upload the folder (default agent-access-review/) as an artifact.

Pin to a release tag or a commit SHA, not main, so a new version can't change your gate without review. That's control AAR-10 applied to this tool itself. Without the action, pip install agent-access-review and agent-access-review scan … --fail-on high do the same.

Design decisions

  • Agents are identities, not apps. The review is modeled on ITGC user access reviews (owner, approval, recertification, dormancy, credential hygiene) because that's the control framework auditors already test. AI-specific risks are added on top, not instead.
  • AAR-09 looks at combinations, not single permissions. Each leg of an exfiltration path is harmless alone. The risk only appears when one agent holds all three, which is why traditional permission reviews miss it. A human approval step on the untrusted-input or egress leg breaks the chain.
  • Fail closed on unknown tools. An unclassified MCP server is a finding, not a pass. The catalog is data, so a GRC team can extend it without touching code.
  • Redact before hashing. Evidence that contains secrets can't be shared, and redacting afterwards would break the hash. Redaction happens in the parser.
  • Docker tags count as unpinned. Only an image digest is immutable. :v1.0 can be re-pushed.

Limitations

  • It reviews configuration, not runtime behavior. It sees that an agent can send email, not what it actually sent. Usage dates come from the manifest, which in production would be fed from tool-call logs.
  • The capability catalog is approximate: it describes what a server can do by default, and a token's real scopes (for example, a fine-grained GitHub PAT) can be narrower. The manifest format lets you record exact scopes.
  • JSON-with-comments configs are skipped with a warning.

What I'd do at enterprise scale

  • Discover from endpoints, not files. Collect MCP configs from managed laptops through MDM or EDR, and agent identities from the IdP (service principals, OAuth apps), so shadow agents surface automatically.
  • Feed usage from logs. Populate last_used from MCP gateway or proxy logs so AAR-08 is evidence-based rather than self-reported.
  • Run the review in the GRC platform. Push the decision sheet into ServiceNow GRC or SailPoint as a certification campaign with owners, due dates and escalation, and auto-revoke grants that aren't certified.
  • Close the loop. Turn not-satisfied OSCAL findings into POA&M items with owners and due dates.

Contributing

The easiest way to help is to add an MCP server to the capability catalog: see CONTRIBUTING.md. Changes are listed in the CHANGELOG.

License

The text above was extracted automatically from the source page and may miss images, tables or code blocks. The original is authoritative.

Published by HN AI
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗