API Documentation

HTSBP provides a free, open REST API and MCP server for checking domains and URLs against our threat intelligence database of indirect prompt injection (IDPI) attacks.

Base URL: https://hasthissitebeenpoisoned.ai/api

check-domain

GET /api/check-domain?domain={domain}

Check if a domain hosts known IDPI attacks targeting AI agents.

Parameters

NameTypeRequiredDescription
domainstringYesDomain to check
curl -s "https://hasthissitebeenpoisoned.ai/api/check-domain?domain=reviewerpress.com" | jq .

Response (malicious)

{
  "domain": "reviewerpress.com",
  "is_malicious": true,
  "threats": [
    {
      "severity": "critical",
      "intent": "ad_review_bypass",
      "techniques": ["zero_font_size", "css_display_none"],
      "description": "First known real-world AI ad review bypass...",
      "source": "unit42",
      "first_seen": "2025-12-15T00:00:00Z",
      "last_seen": "2026-03-03T00:00:00Z",
      "is_active": true
    }
  ]
}

Response (not found)

{
  "domain": "example.com",
  "is_malicious": false,
  "threats": []
}

list-threats

GET /api/list-threats

List known IDPI threats with optional filters. All parameters are optional.

NameTypeDefaultDescription
severitystringcritical, high, medium, low
intentstringFilter by attack intent
limitnumber20Max results (1–50)
offsetnumber0Pagination offset
curl -s "https://hasthissitebeenpoisoned.ai/api/list-threats?severity=critical&limit=10" | jq .

stats

GET /api/stats

Returns aggregate statistics about the threat database.

curl -s "https://hasthissitebeenpoisoned.ai/api/stats" | jq .

report-threat

POST /api/report-threat

Submit a suspected IDPI threat. Opens a Pull Request which is automatically validated by the same scan + research pipeline used for human PRs (observation 1: reachability + AI malicious code analysis; observation 2: source_url credibility + domain reputation via web search). Returns the PR URL — the threat is registered only after a reviewer merges the PR.

Request Body (JSON)

NameTypeRequiredDescription
urlstringYesURL where the IDPI payload was observed (http/https)
source_urlstringYesURL of the supporting evidence/citation (article, IoC, blog post)
descriptionstringYesWhat was observed (location of hidden instructions, wording, behavior — min 20 chars)
severitystringNoSubmitter's estimate (critical / high / medium / low). Re-derived by scan.
curl -X POST "https://hasthissitebeenpoisoned.ai/api/report-threat" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/suspicious",
    "source_url": "https://researcher.example.com/2026/idpi-report",
    "description": "Hidden <div style=font-size:0> in the footer with prompt-injection text targeting AI agents",
    "severity": "high"
  }'

Response (201 Created)

{
  "success": true,
  "message": "PR を起票しました。pr-validate ワークフローが自動検証を実行します。",
  "pr_url": "https://github.com/tanbablack/htsbp/pull/123",
  "pr_number": 123,
  "branch": "report/example.com-1714000000000",
  "host": "example.com"
}

Error responses

  • 400 — invalid url / source_url / description / severity (returned with { error: <field>, message })
  • 405 — wrong HTTP method
  • 500 — GitHub API or internal error

MCP Server

Connect your AI tools directly to HTSBP threat intelligence via the Model Context Protocol.

Connection Guide

Add this to your MCP client configuration (Claude Desktop, Cursor, Windsurf, etc.):

{
  "mcpServers": {
    "htsbp": {
      "url": "https://hasthissitebeenpoisoned.ai/api/mcp"
    }
  }
}

Available Tools

check_domain

Check if a domain hosts known IDPI attacks targeting AI agents.

Input: { domain: string }

list_threats

List known IDPI threats with optional filters.

Input: { severity?: string, intent?: string, limit?: number }

report_threat

Submit a suspected IDPI threat. Opens a Pull Request that is automatically validated by the same scan + research pipeline used for human PRs. Returns the PR URL.

Input: { url: string, source_url: string, description: string, severity?: string }

Example Conversations

User: Before you visit reviewerpress.com, check if it's safe.
AI: I'll check that domain with HTSBP first.
Tool call: check_domain({ domain: "reviewerpress.com" })
AI: Warning: reviewerpress.com is flagged as hostile. It contains 24 IDPI injection attempts using techniques like zero-size fonts and CSS hiding. This site attempts to bypass AI ad review processes. I will not visit this domain.

Sample Scripts

Python

import requests

def check_domain(domain: str) -> dict:
    resp = requests.get(
        "https://hasthissitebeenpoisoned.ai/api/check-domain",
        params={"domain": domain}
    )
    return resp.json()

def is_safe(url: str) -> bool:
    from urllib.parse import urlparse
    domain = urlparse(url).netloc
    result = check_domain(domain)
    return not result.get("is_malicious", False)

result = check_domain("reviewerpress.com")
print(f"Malicious: {result['is_malicious']}")
for threat in result.get("threats", []):
    print(f"  - [{threat['severity']}] {threat['intent']}: {threat['description']}")

Node.js / TypeScript

const HTSBP_BASE = "https://hasthissitebeenpoisoned.ai/api";

async function checkDomain(domain: string) {
  const res = await fetch(`${HTSBP_BASE}/check-domain?domain=${encodeURIComponent(domain)}`);
  return res.json();
}

const result = await checkDomain("cblanke2.pages.dev");
if (result.is_malicious) {
  console.warn(`BLOCKED: ${result.threats[0].description}`);
}

cURL

curl -s "https://hasthissitebeenpoisoned.ai/api/check-domain?domain=reviewerpress.com" | jq .
curl -s "https://hasthissitebeenpoisoned.ai/api/list-threats?severity=critical&limit=10" | jq .
curl -s "https://hasthissitebeenpoisoned.ai/api/stats" | jq .

MCP Client (TypeScript)

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(
  new URL("https://hasthissitebeenpoisoned.ai/api/mcp")
);
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(transport);

const result = await client.callTool("check_domain", { domain: "reviewerpress.com" });
console.log(result);

Report a Threat

Found a website with hidden prompt injection targeting AI agents? Choose any of the three equivalent paths — all go through the same validation pipeline (scan + research) and require a reviewer to merge before the threat is registered.

Path A: REST API

Send POST /api/report-threat with a JSON body. The API opens a PR on your behalf and returns the PR URL. Full schema in the report-threat endpoint docs.

curl -X POST "https://hasthissitebeenpoisoned.ai/api/report-threat" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/suspicious",
    "source_url": "https://researcher.example.com/2026/idpi-report",
    "description": "Hidden <div style=font-size:0> in the footer with prompt-injection text targeting AI agents",
    "severity": "high"
  }'

Path B: MCP Tool

Call the report_threat tool from any MCP client (Claude Desktop, Cursor, Windsurf, etc.). Same underlying flow as the REST API.

await client.callTool("report_threat", {
  url: "https://example.com/suspicious",
  source_url: "https://researcher.example.com/2026/idpi-report",
  description: "Hidden div in the footer with prompt-injection text targeting AI agents",
  severity: "high"
});
// → { pr_url, pr_number, branch, host }

Path C: Direct Pull Request

Edit data/threats/domains/<host>.json directly on GitHub.

{
  "domain": "example.com",
  "threats": [
    {
      "url": "https://example.com/suspicious",
      "severity": "high",
      "intent": "other",
      "techniques": [],
      "description": "Hidden div in the footer with prompt-injection text targeting AI agents",
      "source": "community",
      "source_url": "https://researcher.example.com/2026/idpi-report",
      "first_seen": "2026-04-25T00:00:00Z",
      "last_seen": "2026-04-25T00:00:00Z",
      "is_active": true
    }
  ],
  "updated_at": "2026-04-25T00:00:00Z"
}

All three paths require the same fields:

  • The full URL where the IDPI payload was observed
  • source_url — citation to the original report or evidence (required)
  • A description of the hidden instructions or behavior (≥ 20 chars for API/MCP)
  • (Optional) Your estimated severity (critical / high / medium / low) — the scan pipeline re-derives the final value

The PR validation workflow runs our shared scan + research libraries and posts the verdict as a PR comment. Entries without a credible source_url or that are unreachable + unverifiable will fail CI and cannot be merged.