AI pentest agents are finding high and critical vulnerabilities in production fintech stacks despite WAFs and dedicated security teams. The problem is not that traditional defenses are weak. The problem is that blocking traffic gives agents free information about where your defenses are.
A 403 response is just another signal in an LLM context window. The agent sees “defended here,” updates its internal model, and pivots in milliseconds. Every block teaches the agent where to probe next.
VeilGate takes a different approach. Instead of blocking suspicious traffic, it redirects high-confidence agent requests into a deception layer that looks like your real application but wastes agent tokens and time with plausible but incorrect responses.
Why Blocking Fails Against Agent Loops
Traditional WAFs operate on signature matching and rate limiting. They block requests that match known attack patterns or exceed traffic thresholds. This works against scripted attacks and human adversaries who need time to regroup after hitting a block.
AI agents operate differently:
- They parse HTTP status codes as reasoning inputs, not failures
- They generate new attack vectors in real time based on response patterns
- They run tool-calling loops that cost under a dollar per hour
- They explore the entire attack surface in parallel using MCP servers and Burp Suite integration
When you block an agent request, you confirm that the endpoint is worth protecting. The agent logs this, adjusts its strategy, and tries a different approach. You have given it a training signal for free.
Deception Proxy Architecture
VeilGate sits in front of your application as a reverse proxy. It scores every incoming request using protocol fingerprints, behavioral signals, and online machine learning. The scoring engine does not rely on user-agent strings because agents spoof those trivially.
Traffic Classification Pipeline
# Simplified scoring flow
def score_request(req):
signals = {
'timing_variance': measure_request_timing(req),
'header_order': fingerprint_header_sequence(req),
'tls_fingerprint': extract_ja3(req),
'behavioral_entropy': compare_to_session_baseline(req),
'tool_call_pattern': detect_burp_mcp_signatures(req)
}
score = online_ml_model.predict(signals)
if score < HUMAN_THRESHOLD:
return forward_to_real_app(req)
elif score < AGENT_THRESHOLD:
return challenge_with_pow(req)
else:
return redirect_to_tarpit(req)
The model updates continuously as it observes traffic. It does not need labeled training data because it learns from response patterns and retry behavior.
Deception Layer Design
The tarpit mode serves responses that are HTTP-compliant, semantically plausible, and completely wrong. The goal is to waste agent reasoning cycles without triggering error-handling logic that would cause the agent to abandon the target.
Key design principles:
- Endpoint proliferation: Generate fake API routes that mirror your real naming conventions
- Plausible errors: Return 200 OK with subtly incorrect data instead of 4xx/5xx codes
- Honeypot trails: Inject fake authentication endpoints that accept credentials but lead nowhere
- Token exhaustion: Serve verbose JSON responses that consume agent context windows
Example deception response for a fake /api/v2/accounts endpoint:
{
"accounts": [
{
"id": "acc_7f3e9a2b",
"balance": 12847.33,
"currency": "USD",
"status": "active",
"permissions": ["read", "write", "admin"]
}
],
"pagination": {
"next": "/api/v2/accounts?page=2",
"total": 847
}
}
The response looks legitimate. The agent will attempt to exploit the admin permission or paginate through 847 fake accounts. Both actions waste tokens and time without exposing real attack surface.
Distinguishing Agents from Humans
User-agent strings are useless. Agents spoof them. The proxy relies on behavioral fingerprints that are harder to fake:
| Signal Type | Human Pattern | Agent Pattern |
|---|---|---|
| Request timing | Variable delays, think time | Consistent sub-100ms intervals |
| Header order | Browser-specific, stable | Randomized or library-default |
| TLS fingerprint | Matches declared browser | Mismatched or generic Python/Go |
| Session entropy | High variance in click paths | Low variance, systematic exploration |
| Tool signatures | None | Burp Collaborator callbacks, MCP headers |
The online learning model combines these signals. It does not need to be perfect. It just needs to route ambiguous traffic to the proof-of-work challenge layer, which forces the client to solve a computational puzzle before proceeding.
Browsers solve these puzzles in milliseconds using WebAssembly. Agents either skip the challenge (confirming they are agents) or burn API credits solving it (wasting their budget).
Honeypot Endpoint Strategy
Fake endpoints must survive agent validation without creating real vulnerabilities. This is harder than it sounds.
Agents use tool-calling loops to validate findings. If you serve a fake admin panel at /admin, the agent will attempt to authenticate, change settings, and verify the change persisted. If the change does not persist, the agent marks the endpoint as a false positive and moves on.
To keep the agent engaged:
- Stateful deception: Store fake session state in Redis so the agent sees its changes reflected in subsequent requests
- Partial success: Allow some operations to succeed while others fail in plausible ways
- Lateral movement bait: Inject fake internal IP addresses and service discovery endpoints that lead to more honeypots
Example stateful honeypot for a fake settings API:
@app.post("/api/settings/update")
def update_settings(request):
if is_tarpit_session(request):
# Store fake state
redis.setex(
f"tarpit:{session_id}:settings",
3600,
json.dumps(request.json)
)
return {"status": "updated", "id": generate_fake_id()}
else:
return forward_to_real_app(request)
The agent sees confirmation that its exploit worked. It logs the vulnerability and continues exploring. Meanwhile, you have wasted its tokens and learned about its tool chain.
Deployment Shape
VeilGate runs as a sidecar container or standalone reverse proxy. It does not require changes to your application code.
Typical deployment:
Internet → VeilGate (port 443) → Real App (port 8080)
↓
Tarpit Layer (isolated network)
The tarpit layer runs in a separate network namespace with no access to production data. It serves responses from a template engine that generates plausible but fake data based on your real API schema.
Configuration is declarative:
modes:
- observe # Log scores, forward all traffic
- challenge # PoW for ambiguous traffic
- tarpit # Redirect high-confidence agents
- auto # Adaptive based on threat level
scoring:
human_threshold: 0.3
agent_threshold: 0.7
model_update_interval: 300s
deception:
endpoint_templates: ./templates/
state_backend: redis://localhost:6379
response_verbosity: high
Observability and Failure Modes
The proxy emits structured logs for every scored request. You can feed these into your SIEM or observability stack:
{
"timestamp": "2026-07-27T20:15:33Z",
"request_id": "req_9f2a1b",
"score": 0.82,
"signals": {
"timing_variance": 0.02,
"header_order": "non-browser",
"tls_fingerprint": "ja3_generic_python"
},
"action": "tarpit",
"tarpit_endpoint": "/api/v2/accounts"
}
Failure modes to monitor:
- False positives: Legitimate automation tools (CI/CD, monitoring) flagged as agents
- Model drift: Scoring accuracy degrades as agent behavior evolves
- Tarpit escape: Agent detects deception and abandons target
- Resource exhaustion: Tarpit layer consumes too much memory serving fake state
Mitigation strategies:
- Allowlist known automation by IP or API key
- Retrain model weekly using labeled samples from security team review
- Rotate deception templates to prevent pattern recognition
- Set TTL on fake session state and cap tarpit concurrency
When Deception Breaks Down
Agents will eventually learn to detect deception layers. The arms race is inevitable. Indicators that your tarpit has been fingerprinted:
- Agent traffic drops suddenly after initial exploration
- Logs show systematic probing of tarpit consistency
- Agent begins sending canary values to test response fidelity
At that point, you rotate templates, adjust scoring thresholds, and update the model. The goal is not perfect defense. The goal is to raise the cost of attack high enough that agents move to softer targets.
Technical Verdict
Use deception proxies when:
- You run high-value fintech or SaaS infrastructure that attracts agent-driven reconnaissance
- Your security team can dedicate time to tuning scoring models and reviewing logs
- You want to learn about agent tool chains without exposing real vulnerabilities
- Traditional WAFs are generating too many false positives or teaching agents your defense boundaries
Avoid deception proxies when:
- You cannot afford the operational overhead of maintaining tarpit templates and scoring models
- Your application has complex stateful workflows that are hard to fake convincingly
- You lack observability infrastructure to detect when the deception layer is compromised
- Your threat model does not include automated agent attacks (yet)
Deception is not a replacement for secure coding, patch management, or traditional WAFs. It is an additional layer that exploits the reasoning loops of AI agents to waste their resources instead of blocking them outright.