I find where an autonomous agent's tool boundaries leak, then close them.
sushant.poudel2028@gmail.com · Bhaktapur, Nepal (remote, worldwide)
github.com/sushant-me ·
linkedin.com/in/sushant-poudel2028 ·
sushantpoudel2028.com.np
Agent & LLM security Memory-safety in C/C++ Evaluation design Edge / offline inference
git clone https://github.com/sushant-me/reputation && cd reputation && python3 verify_evidence.py
Your agent executes actions — calls tools, touches files, moves money, runs commands — and role-based access control authenticates the identity without having any opinion about whether a given action should happen. I review the stack for the failure modes that actually occur: prompt injection through retrieved content, tools that shadow framework built-ins, confirmation gates that fail open, and destructive actions reachable without an independent check.
A tool description is not documentation: it is injected into the model's context, so it
can carry instructions. I review the declarations your client receives from a server's
tools/list — and pin them, so a description that changes after you approve
it is reported instead of silently steering the agent.
readOnlyHint, and unconstrained sink parameters — plus a lock file that
turns the next change into a diff.mcp-audit-sample is a deliberately risky vendor server and the audit I would return for it — a critical name collision, an instruction hidden in the Unicode tag block, a description that tells the model to add credentials to its summary, a destructive tool declaring readOnlyHint, and a look-alike name pair. Ten findings, two clean tools, the generated policy, and a demo.py that exits non-zero if a finding stops reproducing. Synthetic target, clearly labelled — not a client engagement.uses: sushant-me/mcpaudit@v1 with the lock file committed — so a
declaration that changes after approval fails the build instead of being noticed later.
The agent review has the equivalent in uses: sushant-me/agentbound@v1.readOnlyHint. Its CI asserts what a checker usually gets wrong: that it
exits non-zero on input it cannot parse, and that all three checks still fire on a
server built to trip them. A checker that reports "clean" when it could not read its input
is worse than no checker at all.
Memory bugs in the libraries everything else is built on, plus the harnesses meant to catch them.
I filed five memory-safety issues against Google's s2geometry — a NULL dereference on
the documented traversal path, an out-of-bounds read, a 16 GiB allocation from a 117-byte input, and
a 2.4 GiB allocation reachable from a 28-byte input — each with a standalone reproducer.
In libphonenumber I found an OSS-Fuzz harness that was asserting 0.00% line
coverage of the code it targeted; the corrected one reaches 93%.
"It works" is not a measurement. I design evaluations with controls that can fail: a shuffled-label floor, an ablation that must collapse, a deliberately broken system that must be caught. My current paper ran 600 policy scenarios per condition on a 3.8B model inside a 4.2 GiB budget, and the headline is the result that contradicted my hypothesis — JSON-constrained output without a reasoning field was the least safe configuration of the three, at 46.2% unsafe accepts against 17.2% unconstrained.
| what | check it |
|---|---|
A maintainer independently reproduced my finding before accepting it — auditing six AI-action rules in sisaku-security/sisakulint surfaced defects in five. Rather than take the premise on trust, maintainer on-keyday built both revisions of the rule and ran them over the same inputs, then wrote "the gap is real and the direction you took to it is a reasonable one" and filed three tracked issues from the audit. The pull request itself was closed for review capacity, not for being wrong — #644 says exactly that. The quotation is machine-checked in my reputation repo: edit that comment and the claim goes red |
#644 · #646 · #647 · #648 |
Security patch authored, merged, then generalised into google/go-github — my #4556 refused a release-asset upload whose URL pointed off-host; the maintainer replaced it the next day with the broader #4564, "credentials are sent only to configured origins", which is what master implements today and which carries the commit "Address feedback from sushant-me"; my name is in the project's AUTHORS file on master |
#4556 · #4564 · AUTHORS |
Four published security advisories from auditing my own tools — each with a reproduction and a regression test: an authorization bypass in my own policy gate (a glob deny rule stepped around with a newline, so the call fell through to a broader allow), a scanner a hostile server could kill before it reported anything, a masker that deleted the word a rule matched on, and a Unicode range list covering 16 of 256 variation selectors. CVE identifiers requested from GitHub's CNA |
GHSA-qwvv-fcmm-r3j2 (high) · GHSA-wcqw-86xv-w95q · GHSA-mffv-hhg5-mm33 · GHSA-62f4-h552-54wc |
A merged feature in a third-party bug-bounty engine — auditing Claude-BugHunter's skill routing found 22 of its 58 hunt-* skills had no mapping, so they could never be selected and the loop silently fell back to hunt-misc. Completed the class, technique and probe mappings, extended the deterministic classifier so those classes are emitted at all, covered every routed class in the weight table, and added a coverage check that reports any unreachable skill |
#81 |
Five memory-safety issues in google/s2geometry, each with a reproducer; two hardening pull requests under review. The maintainer's reply, quoted rather than paraphrased: "It's not really a DoS since these are assumed to only operate on trusted data. We should document the assumptions better." — a disagreement about severity and threat model, not about whether the reads are out of bounds |
#674, #676–#679, PR #682 |
| MCP tool-shadowing fixes open against three of Google's agent frameworks | adk-go #1606 · adk-java #1515 · adk-python #7145 |
| Rank #1, HackingHub Q3 2026 global leaderboard — 177 flags, 18,125 XP | leaderboard API |
| 1st place, NullOrigin CTF 2026 Grand Finale — 2nd in South Asia in the qualifier, then won the eight-team final: 16,850 pts, 40 of 42 challenges, window closed 25 Sep 2026 | certificates (NO-2026-GF-229CF4) |
| A benchmark I wrote found a false positive in my own released scanner — a 23-case labelled corpus (5 of which score my scanner; the rest score a second tool), precision on my scanner's own cases 0.750 → 1.000, with the failing case named in CI instead of deleted | tool-boundary-corpus · the writeup |
| Two IEEE papers accepted — local policy verification for agents; predictive bandwidth scaling for WebRTC over LEO links (2026 IEEE RTC, Chicago) | paper, code, raw outputs |
| Tools I maintain: agentbound, toolgate (Rust), mcp-nameguard, mcpaudit, policygate, trajectorycheck | each has releases, tests and CI |
| Two years as an AI engineer at Atmos SoftTech — production ML, full-stack delivery, offline-first agent pipelines | signed experience letter on request |
Open to contract and freelance engagements now, and to full-time AI security / agent safety roles from graduation. Final-year Computer Engineering at Nepal Engineering College, so I keep one client engagement at a time alongside it.