Files
ai-llm-red-team-handbook/scripts/compliance/ai_recon_scanner_source.py
T
shiva108 b3d3bac51f Add practical scripts directory with 400+ tools
- Extracted all code examples from handbook chapters
- Organized into 15 attack categories
- Created shared utilities (api_client, validators, logging, constants)
- Added workflow orchestration scripts
- Implemented install.sh for easy setup
- Renamed all scripts to descriptive functional names
- Added comprehensive README and documentation
- Included pytest test suite and configuration
2026-01-07 11:39:46 +01:00

84 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""
The `AI_Recon_Scanner`
Source: Chapter_39_AI_Bug_Bounty_Programs
Category: compliance
"""
import aiohttp
import asyncio
from typing import Dict, List
import argparse
import sys
class AIReconScanner:
"""
Fingerprints AI backends by analyzing HTTP headers and
404/405 error responses for specific signatures.
"""
def __init__(self, targets: List[str]):
self.targets = targets
self.signatures = {
"OpenAI": ["x-request-id", "openai-organization", "openai-processing-ms"],
"Anthropic": ["x-api-key", "anthropic-version"],
"HuggingFace": ["x-linked-model", "x-huggingface-reason"],
"LangChain": ["x-langchain-trace"],
"Azure OAI": ["apim-request-id", "x-ms-region"]
}
async def scan_target(self, url: str) -> Dict:
"""Probes a URL for AI-specific artifacts."""
results = {"url": url, "backend": "Unknown", "confidence": 0}
try:
async with aiohttp.ClientSession() as session:
# Probe 1: Check Headers
async with session.get(url, verify_ssl=False) as resp:
headers = resp.headers
for tech, sigs in self.signatures.items():
matches = [s for s in sigs if s in headers or s.lower() in headers]
if matches:
results["backend"] = tech
results["confidence"] += 30
results["signatures"] = matches
# Probe 2: Check Standard API Paths
api_paths = ["/v1/chat/completions", "/api/generate", "/v1/models"]
for path in api_paths:
full_url = f"{url.rstrip('/')}{path}"
async with session.post(full_url, json={}) as resp:
# 400 or 422 usually means "I understood the path but you sent bad JSON"
# This confirms the endpoint exists.
if resp.status in [400, 422]:
results["endpoint_found"] = path
results["confidence"] += 50
return results
except Exception as e:
return {"url": url, "error": str(e)}
async def run(self):
tasks = [self.scan_target(t) for t in self.targets]
return await asyncio.gather(*tasks)
# Usage
# targets = ["https://chat.target-corp.com", "https://api.startup.io"]
# scanner = AIReconScanner(targets)
# asyncio.run(scanner.run())
def main():
"""Command-line interface."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
args = parser.parse_args()
# TODO: Add main execution logic
pass
if __name__ == "__main__":
main()