GitHub - BhaveshThapar/mcp-audit · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
BhaveshThapar
mcp-audit
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>1 Commit<br>1 Commit
manifests
manifests
.gitignore
.gitignore
LICENSE
LICENSE
README.md
README.md
RESULTS.md
RESULTS.md
run.sh
run.sh
run2.sh
run2.sh
summarize.py
summarize.py
View all files
Repository files navigation
mcp-audit
A harness that runs MCP servers in an instrumented sandbox and records what they<br>actually do at runtime — every network connection they open and every file<br>they touch — so you can see a server's real behavior instead of trusting its<br>description.
Why
The official MCP registry verifies who published a server (namespace<br>authentication tied to a GitHub account or domain). It does not verify what a<br>server does once you run it. The existing trust tooling in the ecosystem is<br>almost entirely static analysis — scanning source code and metadata. Static<br>scans miss an entire class of risk that only shows up at runtime:
a server that connects somewhere unrelated to its stated purpose
a server that reads credentials or files outside its lane
a "rug pull": a server whose behavior changes in a later version, after<br>you've already reviewed and trusted it
This project captures runtime behavior directly, which is the part almost nobody<br>is watching yet.
How it works
Each server is launched inside a disposable Linux container (Docker) under<br>strace, with syscalls for file access (openat) and network connections<br>(connect) logged. A fake credential is seeded into the environment as a canary,<br>so any attempt to read or transmit it is visible in the trace. The container is<br>throwaway; nothing the server does touches the host.
docker + strace ──► per-server syscall trace ──► behavior manifest
Everything runs locally. No server code executes on the host machine.
Results
70 MCP servers audited: the 20 most-downloaded on npm, plus 50 from the long<br>tail. Full per-server summaries are in manifests/; the headline<br>findings are in RESULTS.md.
67 clean at startup — no sensitive-file reads, no unexpected network.
3 made outbound HTTPS connections at startup (okx-trade-mcp,<br>razorpay/blade-mcp, notebooklm-mcp-server) to external hosts consistent<br>with each server's function (an exchange integration, a GitHub fetch, cloud/CDN<br>endpoints). None read sensitive files or touched the seeded canary.
1 (bullmq-mcp) reads /etc/passwd at startup via a standard glibc user<br>lookup — flagged by the harness, then verified benign : the contents never<br>leave the process.
No server transmitted sensitive data.
The value shown here isn't "everything was clean" — it's that the harness<br>surfaced the three servers that phone home and the one that touches a sensitive<br>file, and each could be run down to a verdict from the trace. That is behavior<br>static scanners don't see.
Scope note: this captures startup and idle behavior only — the server<br>booting and waiting. It does not yet exercise individual tool calls, which is<br>where more behavior lives. See roadmap.
Roadmap
Tool-call tracing — drive each server through its advertised tools and<br>record behavior per call, not just at boot. (The 3 outbound servers above are<br>the first place this matters.)
Version diffing — re-run servers across releases and diff behavior to<br>detect rug pulls — the highest-value, least-covered case.
Behavior manifests as a feed — a stable, diffable per-server output that<br>clients or registries could consume before install.
Wider coverage — deeper into the long tail of single-maintainer servers.
Run it yourself
&& cd mcp-audit<br>docker run --rm -v "$PWD":/audit -w /audit node:22 bash -c \<br>'apt-get update -qq && apt-get install -y -qq strace && bash run.sh' # batch 1<br># (run2.sh for the long-tail batch)
# distil the traces into readable manifests<br>python3 summarize.py"># needs Docker<br>git clone this repo> && cd mcp-audit<br>docker run --rm -v "$PWD":/audit -w /audit node:22 bash -c \<br>'apt-get...