Protocol fingerprinting
Custom TLS stacks via uTLS, ClientHello construction, HTTP/2 frame and settings behavior, header canonicalization, and how each becomes a durable client identifier.
I build automation at the protocol level — TLS, HTTP/2, and the browser runtime. The request is never the interesting part. What matters is the gap between the client a connection claims to be and the signals it actually emits. I've spent years on both sides of that gap, and I ship tools that measure it.
What I actually do
Each came out of shipping production systems, not reading about them.
Custom TLS stacks via uTLS, ClientHello construction, HTTP/2 frame and settings behavior, header canonicalization, and how each becomes a durable client identifier.
CDP-driven instrumentation and scoped interception, hardware and environment surface, anti-virtualization checks, SSL-interception detection, and time-drift monitoring.
Proof-of-work challenge analysis, enterprise vs. standard behavior, and computer-vision classification of image challenges with custom-trained models.
Semaphore-bounded worker pools sustaining thousands of simultaneous operations, state-machine workflows, warm process pools, real-time event fan-out.
Coverage
Hands-on at the protocol and runtime layer — building against them, and building the tooling that measures them.
Proof, not claims
Most of my work is proprietary. So I publish the parts that aren't — code and writing you can inspect line by line.
An HTTP client that presents as Chrome at every layer it can be measured on — TLS ClientHello, HTTP/2 frames, QUIC transport parameters, WebSocket upgrade, and header order down to the capitalisation. It also reproduces the per-connection extension shuffling that makes a real browser's JA3 differ on every handshake, so a stable hash never gives it away. The profiles aren't hand-written: they're generated from byte-exact captures of the browser and re-verified against those captures by the test suite, so a new Chrome release is a re-capture rather than a rewrite.
A TLS ClientHello parser and JA3/JA4 fingerprint analyzer that scores handshakes against reference client profiles to surface inconsistencies. Zero dependencies outside the standard library.
An HTTP/2 client fingerprinter that derives Akamai-format fingerprints from SETTINGS frame values, window updates, and priority-tree ordering — the part of a connection a client can't fake without reimplementing its own stack.
Log-based intrusion detection in Go: brute force and credential-stuffing detection, impossible-travel correlation across geolocated sessions, and path-enumeration scoring — the defensive counterpart to everything else here.
Longform writeups on how detection actually works — what each layer measures, why clients fail it, and what that means for building or defeating it. Technique and analysis, not recipes.
Teardowns
Three representative teardowns. Targets are public commercial products; client-specific detail and working payloads are omitted.
The challenge ships a per-seed virtual machine that rebuilds its own handler set at runtime, so nothing lifted from one session survives into the next. Work at this level means recovering the interpreter's structure rather than any single payload — identifying the dispatch mechanism, separating the WASM-backed engine from the handlers it drives, and rebuilding the cryptographic path as clean primitives validated against published known-answer vectors instead of trusting a match on live traffic.
A set of scored fields on a hold-style challenge had a widely accepted explanation — one my own earlier notes repeated. Tracing the deobfuscated bundle line by line showed the accepted model was wrong: the values originate in a different subsystem entirely, and anything built on the prior reading was fitting the wrong function. The useful output wasn't a payload; it was knowing which parts of the analysis were load-bearing and which constants shift on every build. Details stay with the work.
Where a challenge's proof-of-work changes shape every build, reimplementing it is a treadmill. The durable approach is an execution environment faithful enough to run the vendor's own logic directly — which turns the problem from cryptography into environment engineering: enough of a browser to satisfy everything the bundle probes, without the weight or the footprint of a real one. Knowing which surfaces are actually inspected, and how deeply, is the entire job.
Selected work
Architecture and implementation on all of these. Client-specific details omitted.
A cross-platform desktop platform built as two cooperating processes: a Node/Electron shell that owns the windows and supervises the runtime, and a Go engine that holds all state and does all the work. Task orchestration, profile and proxy management, a custom TCP auth protocol, and a signed, obfuscated build pipeline for macOS, Windows, and Linux.
The engine underneath the platform. Custom uTLS with per-profile fingerprint control, browser signature emulation across desktop and mobile, cryptographic session storage, dynamic proxy rotation, and an integrity layer detecting interception and clock manipulation before a session is trusted.
Machine classification of image-grid challenges: a YOLO-based classifier with a custom training pipeline, and a DINOv3 frozen-backbone probe benchmarked head-to-head against frontier vision models — paired with protocol-side proof-of-work analysis.
An offline Go binary source-recovery pipeline built for malware analysis. Recovers symbols and moduledata from stripped binaries, reconstructs types and package structure, drives Ghidra decompilation, then maps recovered capabilities to MITRE ATT&CK and generates YARA rules. Read-only by design — it never executes the sample or touches the network.
Recovering the semantics of obfuscated PerimeterX and Shape sensor scripts so rotating field keys can be mapped without hand-reversing every build. Static analysis over instrumented JS sandboxes and WASM execution traces, with proxy-backed differential probing to confirm which fields the server actually validates. Runs fully offline.
A hosted backend where all solving and module logic lives server-side and desktop clients stay thin — no credentials or detection logic ever ship to a client. Tenant isolation, API key management, usage metering, and an admin dashboard over SQLite, with deploy tooling for self-hosting.
A production AI platform built end to end for a client: Go/FastHTTP backend on Firestore, React and TypeScript frontend, Stripe subscription billing, email verification, and admin dashboards — deployed on a VPS behind nginx with Let's Encrypt. Full ownership from schema to TLS certificate.
Inside the platform
The system I own outright — architecture, engine, interface, and release pipeline. Described at the level of design decisions; internals and framework specifics stay private.
A Node/Electron shell owns the windows and supervises a Go engine that holds all state. The interface talks to the engine over a real local TLS channel rather than shell IPC — the UI is a client, not a privileged parent. Credentials are established per launch and the shell exposes only what the engine genuinely cannot do itself.
The engine is supervised with bounded, backing-off restarts, and the interface runs its own health loop with a retry queue so work in flight survives a restart. Integrity-triggered exits are deliberately treated differently from ordinary crashes and are never restarted.
A single authoritative engine holds inputs, runtime state, per-task cancellation, and rate limiting. Async work reaches the interface through typed event pipelines fanned out over a persistent WebSocket, so thousands of concurrent tasks report progress without the UI polling anything.
Semaphore-bounded worker pools and state-machine workflows sustain 3,500+ simultaneous operations per instance, with pool sizing derived from Little's Law rather than guessed. Per-site limiters keep one slow dependency from starving the rest.
Eight independent integrations behind one handler interface, each implementing a complete flow against a different target's authentication, session, and payment behavior. Shared task and session abstractions mean a new integration is a package, not a fork — with a dedicated harness for exercising flows in isolation.
Proof-of-work payload analysis and challenge solving, with a token pool that decouples acquisition from consumption. Image challenges are classified by a model I trained, served by an on-device inference runtime bundled with the app and process-managed separately on each operating system.
Custom TLS and HTTP/2 fingerprint control, browser signature emulation, encrypted session storage, dynamic proxy rotation through a local origin-scoped proxy, device and metadata generation matching several commercial fraud-signal formats, and one-time-code handling.
A runtime integrity layer watching for attached debuggers, network interception, clock manipulation, and screen capture — reporting and quarantining rather than failing silently. Log output is redacted at the boundary so diagnostics never leak session material.
Signed and notarized macOS builds with entitlements, obfuscated shell code, the engine binary embedded into the installer, and CI-driven releases for all three platforms.
A client-side update flow with a separate hotfix channel, so a targeted fix can reach users without a full release cycle — and a rollback path when one shouldn't have.
Experience
Four years shipping production Go, on top of a security-operations background.
Before engineering
The defensive half of the background — how I learned what detection looks like from the other side of the console.
Stack
Contact
Open to senior engineering roles in bot detection, fraud, and anti-abuse. Remote or hybrid.