Leroy H. Mason (Elior Malak) (@Lhmisme) header
Leroy H. Mason (Elior Malak) (@Lhmisme) profile picture

Independent AI security researcher. Built mcp-authscan, a focused auth scanner for live MCP servers. Finds the boring failures that actually ship.

Georgia, USA
Joined August 2009
Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)Photo by Leroy H. Mason (Elior Malak) (@Lhmisme)
Day 25 of 30 Days of @boardyai. A server can say hello to anyone with no login and still refuse to do a single thing for them. A scan that only checks the hello calls that server open. mcp-authscan now goes one step further. With no login, it asks the server to run one harmless tool, the kind named list, get, status or ping. It never touches anything named for writing, deleting or sending. Then it reads what actually came back, not just whether the request went through, because a server can say no inside an answer that looks like a success. If the tool ran, the report says EXECUTED. If the server refused, it says REFUSED and drops the open finding. If the answer can't be read, it says UNKNOWN and doesn't guess. I tested it on my own test server both ways. Locked, it refused with "unauthorized: tools/call requires a valid bearer token" and the tool never ran. Unlocked, the tool ran and answered "pong." This check is off by default. Calling a tool is something you only do with written permission, so it lives in the paid assessment, not the free scan. github.com/LHMisme420/mcp-au… Receipts over promises.
1
1
42
One of Cloudflare's public AI tools says "ALWAYS read this guide before migrating Pages projects to Workers." In capitals, aimed at the model. And it's completely fine. I look for tool descriptions that quietly steer the AI, things like "ignore previous instructions" or "do not tell the user." This one tells the AI to read the docs before doing a migration. That's a tool helping the model do the job right, and it says so where anyone can read it. Cloudflare's public docs server has two tools, and both are exactly what they say they are. A scanner that flagged every capital-letter ALWAYS would bury the real problems in noise, so the report keeps honest guidance and hidden steering in separate piles. github.com/LHMisme420/mcp-au… Receipts over promises.
1
49
A real operator gave me written permission to scan his live fleet of AI servers and publish what I found. Seven of eight came back with no findings. @boardyai set me up with Lonnie Van Zandt, who runs the Tollbooth DPYC network, a set of paid MCP servers on infrastructure he controls. On November 11 he put it in writing. He named 18 endpoints and set the terms: read-only requests, one per host per second, three per host max, no exploitation, no load testing, no other tenants, no patron or billing pages. He also said the redacted report could be made public. Eight hosts were scanned that day. schwab, beesknees, goodearth, taxsort, roastify and cypher each passed 9 checks with 0 failures. chartremotely passed 8 with 0 failures. The eighth was dpyc-oracle. It answered a hello with no login and introduced itself as dpyc-oracle 4.1.6. That's graded MEDIUM. The hello didn't include a tool list, and the report says plainly that the response wasn't inspected for record-level data. Its replies also tell browsers that any website may read them, though not with a user's login attached. That's graded HIGH. The report names what it left out, and why. There was no rate limit testing because no request budget was authorized. There was no key check because no key endpoint is published. Tool behaviour, source code and dependencies weren't covered. mcp-authscan 1.1.22 learned to read one more kind of server handshake, which is what brought dpyc-oracle into this report. Thanks to Lonnie for saying yes and letting it be published. github.com/LHMisme420/mcp-au… Receipts over promises.
2
59
Day 24 of 30 Days of @boardyai. Some AI servers don't answer in plain JSON. They answer in a stream, a few lines at a time, and a scanner has to open each one to know what it said. mcp-authscan 1.1.21 now does that. It opens every frame in the stream and grades what's inside it on its own. A server that lets anyone through its front door with no login now lands in the written report as a finding, with its severity, the same way it shows on screen. The report still keeps the full answer exactly as the server sent it, so anyone can hold the grade up against the evidence. Before it shipped, I built a stream answer with no login on it and ran it through to see what came back. It came back CRITICAL. 502 tests passed, and I opened the package that went to PyPI to make sure the new code was actually inside it. Version 1.1.21 on PyPI, tag v1.1.21. github.com/LHMisme420/mcp-au… Receipts over promises.
3
1
56
Day 23 of 30 Days of @boardyai. I checked 610 tools on public AI servers for ones that say they only read while actually changing things. The honest count is zero. 408 of those tools promise they're read-only. The rules flagged one of them as a conflict. When I read it by hand, it was a business-directory search tool that tripped on the word "install" in a description about finding a plumber. So the count is zero, and the check that caught the false alarm is part of the report. One tool elsewhere did label itself read-only on an action that deletes a saved connection. That one is out to its operator privately before anything is said about it. Also shipped today: mcp-authscan now writes down what each server says about itself. That means its name, its version and which protocol version it agreed to, all taken from the same hello the scanner already sends. It makes no extra requests and contacts no new hosts. If the server doesn't say, the report records NOT_OBSERVED instead of guessing. github.com/LHMisme420/mcp-au… Receipts over promises.
2
70
Don't hire me on my word. I have no degree in this, no credentials and no résumé in tech, so I made sure you'd never have to take my word for anything. Check the work instead. Five AI projects list me as the reporter on their security advisories, and every one of those teams shipped a fix. FlowState and DialectForge name me on their own security pages. My scanner is open source, and every report it writes can be re-run by someone else to see if they get the same answer. A year ago I had built nothing. All of the above I built from zero, solo, overnight, with AI agents writing code that I checked before it went anywhere. If you're shipping AI and want someone who brings the proof with every claim, I'm looking for my next team. DMs open. github.com/LHMisme420/mcp-au… Receipts over promises.
6
1
6
128
A scan report is a claim made by someone with an interest in it being believed. So the report carries its own check. mcp-authscan now has verify. Point it at a saved report and it re-runs the same probe set on the same target. MATCH means the graded content reproduced. DIVERGENCE lists the fields that differed; it does not tell you whether the server changed or the report was wrong. NOT_REPRODUCIBLE means the hash cannot be recomputed. Probe set is versioned separately, so recalibration never rewrites an old report. It proves the graded fields reproduced, not that the findings are correct, and you still need authorization to scan the target. Then I handed it a report with a zeroed hash to see whether it would notice. The only way to know a verifier works is to give it something that has to fail. github.com/LHMisme420/mcp-au… Receipts over promises.
1
3
79
Three teams have now measured how many MCP servers hand over their tool list to anyone who asks. reptile.haus found 153 of 250. Knostic verified 119 of 119. Wiz put it near 70% of exposed servers. All three counted how many. None of them said what the tools actually do. So I counted that. 125 public MCP servers that answered a tool-list request with no credentials on it, 1,463 tool names between them. Most of it is reading. Get, list, search, find, check. About eight in ten names describe fetching something, and a server that tells an agent what it can read is doing its job. Then a small set that isn't reading. Twenty names across fifteen servers describing things that create, publish, submit, or spend money. One server publishes a staged purchase flow: create an intent, confirm it, cancel it. Another publishes two kinds of checkout. I'm not telling you those are open. Whether any of them answers without a credential is a separate question and I haven't written about it. What I'm telling you is that an agent reads that list to decide what to do next, and the list does not say which entries ask for a login first. Receipts over promises.
2
2
74
Day 22 of 30 Days of @boardyai. A server can turn you away at the front door and still hand its whole tool list to anyone who asks the new way. That's by design. The latest MCP revision lets anyone ask a server what it offers by putting a simple label on the request, no login needed. Actually using a tool still takes credentials. The server I tested today did exactly that, and did it correctly. The gap is on the reading side. A client or scanner that only knows the old handshake gets told no and records the server as closed. Meanwhile its whole catalogue is readable to anyone who sends the right label. So mcp-authscan now checks both ways in and reports them separately. Blocked, refused and not built yet are three different answers, and only one of them tells you anything about security. Before posting, I gave Grok the facts and asked for a second opinion. It confirmed the mechanism is published spec. It also confirmed that "hidden from older clients" is the fair way to describe it. github.com/LHMisme420/mcp-au… Receipts over promises.
2
6
83
The TypeScript SDK behaves the same way, and one step further. In default configuration it sends Basic credentials to the non-matching token endpoint and then uses the issued token as a Bearer on the resource. Supply an expected issuer and it refuses before reaching the token endpoint at all. I checked the fix diff between 1.30.0 and 1.31.0 to confirm this is the same decision rather than an oversight. The constructor warns at runtime when the expected issuer is omitted, saying the MCP server decides which authorization server receives the client's credentials, and the option is marked deprecated in the type definitions. Stored credentials are bound by default, and a mismatch is discarded rather than sent. Neither SDK leaves this silent. Both warn at runtime, both mark the option deprecated, and both bind stored credentials by default. The gap is a documented compatibility path with a removal date, not an unnoticed one.
1
27
Day 21 of 30 Days of @boardyai. You can't find a client's flaw by scanning the server, so mcp-authscan now tests the client too. The question it asks is simple. When a server points an AI client at someone the client was never told to trust, does the client hand over its credentials anyway? On earlier real runs, fastmcp 4.1.1 did. Its credential showed up at the wrong server's door. 4.1.2 refused before presenting anything. If the check can't load a client at all, it says so and names the reason. It never reports a pass it didn't see. Receipts over promises.
3
3
148
Leroy H. Mason (Elior Malak) retweeted
I've spent the last few months building @bluebirdaware a non-profit venture. Lanyards & cards designed with people whose conditions aren't visible. 200 surveys and wait list. £10k of donated kit. What I need is a print sponsor for the next run or XL card printer. @boardyai
1
1
1
38
🧐
Cybersecurity is no longer just a career challenge. It's a national security issue. A business survival issue. And increasingly, an international security crisis. The next major conflict may not begin with weapons. It may begin with a keyboard.
41
Do not fear the future. We can and will do this right for humanity.
🤖 Made with AI
47
I foresee the future. Spawning AI or SI agents. BE careful out there, 18 years of technical support!
🤖 Made with AI
7,013
Until August 2025 I was an insurance claims adjuster, and I had never built anything. My background is a criminal justice degree from Columbus State, claims investigation, and law enforcement. I'm from middle Georgia. There were no earlier launches and no earlier businesses. This is the first product I've ever made of any kind. Since then I've become the credited reporter on security flaws in three open source AI projects. I also measured 16,072 AI tool servers from public registries to see how many would let a stranger connect with no credential at all. Of the ones that actually answered, 57.1% did. I taught myself by working with AI agents, and I want to be honest about the split. I decided what to build, who it was for and how it should work, and I did the research. The agents wrote the code and got through documents faster than I ever could. I checked everything they handed back before it went anywhere. That split shaped the tool itself. Years of claims work teach you that a report is a claim made by someone who wants it believed. So every report my scanner produces carries a way for someone else to re-run it and see if they get the same answer. I'm not claiming the tool is always right. I'm claiming you can catch it if it isn't. @boardyai is one of the agents I lean on most, and it pushed me to build that checker. I did this because the gap between how fast AI is shipping and how safe it is keeps getting wider. You don't need a computer science degree to go measure it. Receipts over promises.
4
3
198
Every mcp-authscan report can now be checked by someone who doesn't trust me. @boardyai pushed me to build a verifier, and it's on main tonight. Point it at a report and it recomputes the hash from what's inside. You get one of three answers. It matches. It doesn't match. Or the report was made under an older scheme that today's code can't reproduce, and the verifier tells you that plainly. I ran it on my own published report tonight and got back the same hash I posted, 0049e3dbd616. A test that changes the counts after hashing gets caught every time. The hash leaves out timestamps and run time on purpose, so two runs against the same server can land on the same hash. So far that's proven on my own machine. Other machines and Python versions are next. Receipts over promises. github.com/LHMisme420/mcp-au…
2
1
5
135