DEV Community

Mustafa Güngör
Mustafa Güngör

Posted on

Synapse Shield v0.10.0: Bringing Behavioral Bot Detection to Mobile (Without Building an App)

TL;DR

Synapse Shield is an open-source, self-hosted behavioral biometrics engine for bot mitigation. It scores mouse, touch and keystroke dynamics instead of showing CAPTCHAs, and it collects no PII (only relative millisecond timings).

v0.10.0 adds the mobile leg: a Mobile SDK v2.0 across the vanilla JS, React and Vue packages, plus matching changes in the Python engine and the native Rust core.


The problem: desktop heuristics punish real phones

The first versions were tuned on mouse trajectories. Mobile traffic exposed five false-positive cases, all of which looked like bots to desktop-oriented rules:

Scenario Why it was flagged
Single tap (no drag) A single point gives the 1D-CNN a zero-padded 60-step tensor, which it scored as a bot. A hard rule also flagged 1-2 mouse points as "teleportation".
Flick-scroll, then tap elsewhere Fitts's Law deceleration and click-to-cursor distance checks assume a persistent cursor.
iOS / WebView radiusX == 0 Touch radius is quantized or zero, which looked like a synthetic constant-radius touch.
Android Gboard / IME Soft keyboards emit key="Unidentified" with 0-5 ms synthetic dwell times, tripping the mechanical-key rules.
Touch drawing on the demo canvas The cockpit canvas only listened for mousemove.

What changed in v0.10.0

1. Client SDK (JS, React, Vue)

  • Tap hold time (touchend - touchstart) is recorded as tap_duration_ms.
  • Touch points carry source: "touch" and a 3-decimal average radius, so WebViews that report r = 0 can still be recognized as touch input.
  • The synthetic click that browsers fire after touchend is de-duplicated.
  • A passive devicemotion listener computes motion_variance (handheld micro-tremor, no permission prompt needed where the browser allows it).
  • device_pixel_ratio, orientation and the WebGL renderer string are included for cross-validation.

2. Engine rules

  • GPU mismatch: a mobile-sized touch viewport reporting SwiftShader, llvmpipe or a desktop NVIDIA/AMD renderer scores +85 risk.
  • Tap timing: an average tap under 8 ms scores +55. Three or more taps with near-zero duration variance score +50. A tap of 15-800 ms is a small bonus.
  • IME-aware keystrokes: Unidentified / Process keys are exempt from the mechanical dwell-time penalties. Flight-time and entropy checks still apply.
  • Short touch sessions: the desktop 1D-CNN is skipped below 12 points on touch devices, Fitts's Law is not applied to touch, and click-to-cursor compares against the nearest recorded touch point.

3. Rust parity

The six new features (tap_count, avg_tap_duration, tap_duration_var, device_pixel_ratio, motion_variance, is_mobile_gpu_mismatch) exist in both the Rust SIMD core (synapse_core_rs) and the Python fallback. A new parity test runs both implementations on the same telemetry and compares the results.

Verifying it

The full suite passes with 141 tests, including new cases for:

  • a genuine single tap
  • iOS-style zero-radius touches
  • Android IME typing
  • swipe followed by a distant tap
  • an emulator spoof (NVIDIA renderer on a 390 px touch viewport with a 2 ms tap), which is blocked

There is also a new mobile_emulator_spoof_plugin in the built-in red-team orchestrator.

pip install -U synapse-shield
synapse-shield run --port 8000
synapse-shield redteam
Enter fullscreen mode Exit fullscreen mode

Honest limitations

  • The models and thresholds were validated on synthetic and hand-built telemetry. Real-world device diversity (old Android builds, cracked screens, unusual WebViews) still needs field data.
  • devicemotion availability varies by browser and permission policy, so it is a bonus signal, never a requirement.
  • This is a web SDK for mobile browsers, PWAs and WebViews. There is no native Swift or Kotlin SDK yet.
  • It does not do TLS / JA3 fingerprinting, so it works at the application layer only.

What's next

  • Field data collection to recalibrate the mobile thresholds
  • A native mobile bridge
  • Network-layer fingerprinting through a reverse-proxy plugin

Feedback, issues and PRs are welcome. If you try it on a real device fleet, I would like to hear which false positives you hit.

Top comments (0)