Building a bot detection engine is challenging, but making it resilient against adversarial attacks, denial-of-service (DoS), and subtle concurrency bottlenecks in production is an entirely different battle.
A few days ago, we conducted an end-to-end security and algorithmic audit on Synapse Shield—our open-source, privacy-first alternative to commercial CAPTCHAs and proprietary cloud WAFs.
In this post, we'll walk through the actual architectural vulnerabilities we identified, how we patched them in v0.9.3, and what you can learn when designing high-throughput Python and Rust security middleware.
What is Synapse Shield?
Synapse Shield is a self-hosted, sub-millisecond bot mitigation engine. Instead of forcing legitimate users to click distorted fire hydrants or crosswalks, it analyzes behavioral biometrics (neuromuscular micro-tremors via jerk analysis, differential cursor curvature κ(t), and keystroke dynamics) along with network kinematics using a hybrid Python + Rust SIMD core.
However, security software must itself be impervious to abuse. Here are the vulnerabilities we audited, the real-world risks they posed, and how we resolved them.
1. Algorithmic DoS: The Poisson Factorial Bottleneck
The Problem
To detect abnormal request velocity (rate anomalies), we evaluate Poisson distribution probabilities for incoming IP request spikes. In earlier iterations, the cumulative probability was calculated using:
# Vulnerable code:
term = (math.pow(lambda_val, i) * math.exp(-lambda_val)) / math.factorial(i)
When an attacker flooded the endpoint with high request bursts (k >= 500), math.factorial(i) rapidly consumed excessive CPU cycles and raised an OverflowError. This opened up an Algorithmic Denial-of-Service (DoS / CPU Starvation) vector: an attacker could deliberately trigger extreme CPU exhaustion simply by generating large request counts.
The Fix
In v0.9.3, we replaced factorial computation with an O(1) iterative multiplicative recurrence. Furthermore, because Poisson cumulative probability approaches 1.0 when k >= 30 under standard baselines, we added a fast short-circuit cutoff:
# Hardened v0.9.3 implementation:
def poisson_anomaly_score(k: int, lambda_val: float = 2.0) -> float:
if k <= 1:
return 0.0
if k >= 30:
return 1.0 # Instant thresholding: avoids unnecessary math loops
if lambda_val <= 0.0:
return 0.0
cumulative_prob = 0.0
term = math.exp(-lambda_val)
for i in range(k):
if i > 0:
term = term * lambda_val / i
cumulative_prob += term
return min(1.0, max(0.0, cumulative_prob))
Execution time dropped to < 0.1 ms, completely eliminating CPU starvation even under 100,000 incoming burst counts.
2. Keystroke Dynamics: O(N²) List Shifting
The Problem
During client-side keystroke hold-time analysis, timestamps for keydown and keyup events are paired. The previous implementation used a standard Python list:
# Vulnerable code:
down_t = pending_downs[k_code].pop(0) # O(N) memory shift operation!
In Python, list.pop(0) shifts every subsequent element in memory to the left, making it an O(N) operation. When a user or scraper submitted long text inputs, the overall tokenization degraded to O(N²), blocking the asynchronous Event Loop.
The Fix
We switched the queue data structure to collections.deque:
from collections import defaultdict, deque
pending_downs = defaultdict(deque)
# ...
down_t = pending_downs[k_code].popleft() # True O(1) popping
With popleft(), element extraction is now strictly O(1), ensuring zero event loop stalling even on massive typing payloads.
3. Reverse Proxy IP Spoofing & IPv4-Mapped IPv6 Masking
The Problem
In modern deployments, microservices sit behind Cloudflare, Nginx, or AWS ALBs. Blindly trusting X-Forwarded-For or X-Real-IP headers allows attackers to spoof their IP address.
Additionally, IPv4-mapped IPv6 addresses (e.g., ::ffff:192.168.1.1) caused subnet masking routines to misclassify addresses or fail strict GDPR/KVKK anonymization policies.
The Fix
-
Dynamic Trusted Proxies: Added the
SYNAPSE_TRUSTED_PROXIESenvironment variable configuration to restrict header traversal strictly to recognized proxies. - Proper IPv6 Normalization & Unwrapping:
def mask_ip(ip_str: str) -> str:
"""GDPR/KVKK compliance: Mask the last octet of IPv4 or last 4 blocks of IPv6."""
try:
ip = ipaddress.ip_address(ip_str)
# Unwrap IPv4-mapped IPv6 addresses (e.g., ::ffff:10.0.0.1 -> 10.0.0.1)
if getattr(ip, "ipv4_mapped", None):
ip = ip.ipv4_mapped
if ip.version == 4:
network = ipaddress.ip_network(f"{ip}/24", strict=False)
return f"{network.network_address.exploded.rsplit('.', 1)[0]}.*"
else:
network = ipaddress.ip_network(f"{ip}/64", strict=False)
prefix = network.network_address.exploded.split(":")[:4]
return f"{':'.join(prefix)}:*:*:*:*"
except ValueError:
return "unknown"
4. Preventing Arbitrary Code Execution on Model Loading & Path Traversal
The Problem
Synapse Shield uses pre-trained neural weights to evaluate client-side trajectory kinematics. Using numpy.load(weights_path) without restrictions can potentially allow arbitrary object unpickling (Arbitrary Code Execution / RCE) if a malicious file replaces the weights. Furthermore, the retrainer module lacked strict path validation.
The Fix
Enforced strict disallowed pickling and explicit canonical path validation:
# 1. RCE Guard (Pickling strictly disabled):
with np.load(weights_path, allow_pickle=False) as data:
self.conv_w = np.array(data["conv_w"])
# 2. Path Traversal Guard (Canonical resolution & extension validation):
resolved = os.path.abspath(output_path)
if not resolved.endswith(".npz"):
raise ValueError(f"Invalid output weights file extension: {output_path} (must be .npz)")
Benchmark Results (v0.9.3)
Following the audit, our test suite was updated to cover all targeted attack surfaces:
$ pytest tests -q
85 passed, 12 skipped in 6.74s (100% Success)
$ ruff check src tests
All checks passed!
Key performance metrics:
- Overhead Latency: < 0.5 ms per incoming request (microsecond range).
- Memory Footprint: Capped with O(1) LRU cache eviction.
- Zero PII Exposure: Fully masked, GDPR/KVKK-compliant network telemetry.
Getting Started in 30 Seconds
You can integrate Synapse Shield into any FastAPI or ASGI application:
pip install synapse-shield
from fastapi import FastAPI
from synapse_shield import SynapseShieldMiddleware
app = FastAPI()
# Add Synapse Shield protection middleware
app.add_middleware(
SynapseShieldMiddleware,
protected_paths=["/api/v1/auth/login", "/api/v1/checkout"],
action="block" # Options: 'block', 'challenge', 'log'
)
@app.get("/")
async def root():
return {"status": "protected"}
Open Source & Community
Security is not a static state; it is a continuous process of verification, testing, and refinement. We welcome feedback, code contributions, and security reviews from the community.
- GitHub Repository: 0xStoic-bit/Synapse_Shield
- PyPI: pypi.org/project/synapse-shield
If you find this project useful for protecting your endpoints against modern botnets, feel free to give the repository a star ⭐ and share your thoughts in the comments!
Top comments (0)