Computer MCP / Learn / OWASP MCP Top 10
The OWASP MCP Top 10, answered with running code
All ten OWASP MCP risk categories, and what one macOS computer-use server actually does about each - including the four where the honest answer is "not our layer" or "this one cannot be closed".
The OWASP MCP Top 10 (2025) is the first dedicated OWASP list for Model Context Protocol implementations. It names ten risk categories. This page walks all ten and says, for each, what this server actually does - including the four where the honest answer is "that is not our layer" or "we cannot close this one".
Why a vendor page like this is worth reading anyway: every claim below points at either a measurement or a test that goes red if the behaviour changes. Where we have neither, it says so. A security page without a falsifiable claim is marketing with footnotes.
The ten, and what we do about each
| # | OWASP category | What this server does |
|---|---|---|
| MCP01 | Token Mismanagement and Secret Exposure | addressed There are no tokens. No account, no API key, no licence check - so there is nothing to mismanage. The related risk is the log: OWASP names "logs recording full prompts or responses without redaction" as a vulnerability in this category, and that is exactly what an audit log of every keystroke would be. Typed text is stored as a length plus a salted SHA-256 prefix. The salt is random per run and never written down, because a fingerprint without that random ingredient, of an eight-character password, is guessable offline by whoever ends up holding the file. |
| MCP02 | Privilege Escalation via Scope Creep | addressed Tools carry a tier, and
CMCP_MODE=readonly does not merely refuse the write tools - it
does not list them. A tool the model cannot see is a tool it cannot be
talked into trying. Measured: 22 tools in full mode, 11 in read-only. |
| MCP03 | Tool Poisoning | not our layer This is about a malicious server describing its tools deceptively to the model. We are a server, not a defence against other servers. What we can do is be describable: the tool descriptions say plainly what each one reaches, and the source is MIT so you can read them rather than trust them. |
| MCP04 | Software Supply Chain Attacks and Dependency Tampering | measured The npm package has one dependency,
the official MCP SDK. The Swift helper has zero - Package.swift
declares no dependencies at all. That is not a virtue by itself; it is a number
you can check, which is the point. |
| MCP05 | Command Injection and Execution | addressed, and tested There is no shell tool, no
arbitrary file access and no URL fetching. Each would be a few lines of code and
each is left out on purpose. The one place we build a command from text is the
consent dialog, which is assembled with JSON.stringify and handed to
execFile - no shell, one argument. A test fires three
break-out payloads at it and fails if any of them executes. It is
mutation-proven: replace the escaping with plain concatenation and the payload
runs and the test goes red. Worth taking seriously: a Cloud Security Alliance research note from May 2026 puts 43% of MCP CVEs in January and February 2026 in this class. their number, not ours |
| MCP06 | Intent Flow Subversion (Prompt Injection via Context) | cannot be closed A page or document the agent reads can tell it to do something you did not ask for. We do not claim to prevent that, and no MCP server can. What the design does is make it visible rather than impossible: writes pass a consent gate that names the app, password managers and terminals ask every single time regardless of mode, menu items that look destructive ask every time, and everything lands in a log that can only be added to, never edited you can read afterwards. That is a different promise from prevention and it is the one we make. |
| MCP07 | Insufficient Authentication and Authorization | different threat model This server has no network listener. It is started by your MCP client and speaks over standard input and output, so there is no endpoint to authenticate to. The authorisation boundary is the macOS permission system plus the consent gate, not a token. |
| MCP08 | Lack of Audit and Telemetry | addressed Every call is written to
~/.local/state/computer-mcp/audit.jsonl, only-grows, mode 0600,
directory 0700. One line per call: the tool, the target app, the outcome, and a
per-server session mark so two agents running at once can be told apart. OWASP
asks for immutable trails; only-grows on a 0600 file is what that means on a
single user's machine, and we would rather describe it precisely than call it
immutable. |
| MCP09 | Shadow MCP Servers | not our layer Unsanctioned servers in an organisation are a fleet problem, not something a single server solves. The one contribution we can make is being trivial to identify in a config: one npm package, one command, no installer, no daemon, no login item. |
| MCP10 | Context Injection and Over Sharing | addressed, with a named limit This is the one the whole product is built around. Secure text fields and the windows of listed password managers are painted opaque black on the bitmap in memory, before any PNG is written, so the unredacted image never exists on disk to leak. The limit, stated plainly: only what macOS itself marks as secure is covered. A password in a plain text editor or a token in a terminal buffer carries no such marking and is not hidden. The redaction is exactly as good as the application's own field types. |
What the scorecard actually says
Six addressed, two that are not this layer's problem, one with a different threat model, and one - prompt injection - that nobody can close and we do not claim to. That last row is the one worth dwelling on, because a security page that scored ten out of ten would be telling you something false.
The useful question is not "does this server pass a list" but "what happens on the day the agent does something you did not intend". The answer here is that it asks first on writes, it always asks near password managers and terminals, it never has your passwords in an image, and it writes down what it did. None of that is prevention. All of it is the difference between an incident you can reconstruct and one you cannot.
How to check any of this yourself
None of the claims above need to be taken on trust.
git clone https://github.com/Agent360dk/computerMCP
cd computerMCP
# MCP04 - count the dependencies
cat mcp-server/package.json | grep -A3 dependencies
grep -c "dependencies:" helper/Package.swift # 0
# MCP05 - the injection test, and the rest of the suite
./test/run-all.sh
# MCP01 / MCP08 - what the log actually holds
cat ~/.local/state/computer-mcp/audit.jsonl | tail -5
# And the one that matters most: is there any outbound call at all?
grep -rnE "fetch\(|https?://|net\.|axios" mcp-server/ helper/Sources/
The last one comes back with bundle identifiers and documentation links. If it ever comes back with a socket, that is the bug report we would want fastest.
Other taxonomies worth knowing
OWASP's is the most citable because it is numbered, but it is not the only one. The Coalition for Secure AI published an MCP security white paper through OASIS in January 2026 with a broader taxonomy - close to forty threats across twelve categories. If you are writing policy rather than choosing a tool, that is the more complete map. Our own MCP security checklist is the practical middle: ten things to run against every server you already have installed.
FAQ
What is the OWASP MCP Top 10?
A list of ten risk categories for Model Context Protocol implementations, published by OWASP in 2025 as the first OWASP project dedicated to MCP. It covers token mismanagement, privilege escalation, tool poisoning, supply chain attacks, command injection, prompt injection through context, weak authentication, missing audit trails, shadow servers, and context over-sharing.
Does Computer MCP address all ten?
No, and a server that claimed to would be overselling. Six are addressed, two are not this layer's problem (tool poisoning by other servers, shadow servers across a fleet), one has a different threat model (there is no network listener to authenticate to), and one - prompt injection - cannot be closed by any MCP server. We make it visible rather than impossible.
Can an MCP server prevent prompt injection?
No. A page or document the agent reads can always tell it to do something the person did not ask for. What a server can do is make the consequences visible: a consent gate on writes that names the target app, apps like password managers and terminals that ask every single time regardless of mode, and a log that can only be added to, never edited you can read afterwards. That is reconstruction, not prevention.
What is the most common MCP vulnerability in practice?
Command injection. 43% of MCP CVEs in January and February 2026 were of that class. It is worth asking any server whether it exposes a shell, and if it builds any command from text, whether that construction is tested against break-out payloads rather than merely reviewed.
Why does the audit log store hashes instead of the text?
Because a complete record of every keystroke is exactly the file an attacker would want, which would make the log the very thing the product is against. The hash proves two actions typed the same thing without storing what it was. It is scrambled with a random ingredient that only exists while it runs, because a fingerprint without that random ingredient, of a short password, can be guessed offline. The cost is honest: comparison works within a run, not across runs.
Does redaction cover every secret on screen?
No. Only what macOS itself marks as secure: password fields in native apps and login forms, plus whole windows of listed password managers. A password in a plain text editor, an API key in a terminal buffer or a token in a devtools panel carries no such marking and is not hidden. Before a long unattended run, that is the thing to look at - not the software, your own screen.
How can I verify these claims?
Clone the repository and run the test suite; every claim on this page points at either a measurement or a test. For the dependency count, read package.json and Package.swift. For outbound network calls, grep the source for fetch, http, net and axios - what comes back should be bundle identifiers and documentation links, nothing that opens a socket.