Fingerprinting
5 min read
Device fingerprinting is how TrustLens identifies the actor behind a checkout request. Card-testing botnets routinely rotate IP addresses to evade simple IP-based rate limits, but they have a much harder time rotating the full set of browser and device characteristics that make up a fingerprint. This page describes what TrustLens fingerprints, why those specific signals, and how the Pro tier extends the fingerprint with an additional layer.
What’s in the Fingerprint #
The Free fingerprint is built from four signals:
| Signal | Source | Why Useful |
|---|---|---|
| User-Agent string | HTTP header | Browser version, OS, sometimes device. Coarse but reliable. |
| Accept-Language header | HTTP header | Language preferences in priority order — botnets often have generic or missing values |
| Viewport dimensions | Client-side JS | Screen and window size — bots running headless often have unusual viewports |
| Canvas hash | Client-side JS | Hash of a small rendered canvas; differs between browser/OS combinations due to font and rendering differences |
The four signals are concatenated and hashed with the plugin’s keyed HMAC-SHA256 secret to produce the fingerprint. Like address and IP hashes elsewhere in TrustLens, the raw signal values are never stored — only the resulting hash.
Pro: The 12-Font Signal #
Pro adds a fifth signal: a 12-font detection check. The script measures the baseline rendering width of 12 specific fonts and produces a per-system signature based on which fonts are installed and how they render.
Why fonts: card-testing botnets are usually run on compromised hosts (residential proxies, virtual machines, hijacked browsers) where the attacker has limited control over installed software. The font set on each compromised host is whatever happens to be there — and replicating a target font set consistently across many botnet nodes is significantly harder than spoofing User-Agent strings.
The 12-font signal makes fingerprint collisions across botnet nodes much rarer, which means lockouts catch more attempts before the bot has time to switch fingerprints.
How Stable Is the Fingerprint? #
A legitimate customer’s fingerprint is stable across multiple checkout attempts in the same session — same browser, same window, same device. It can change when:
- The customer switches browsers (Chrome → Firefox) — different User-Agent and canvas hash
- The customer switches devices (laptop → phone) — different User-Agent, viewport, canvas
- The customer resizes the browser window meaningfully — different viewport
- Browser update changes rendering — slightly different canvas hash
- Operating system update — possibly different font set (Pro)
For card-testing-defense purposes, this stability is sufficient. Legitimate customers rarely change devices mid-checkout-burst; attackers can change User-Agent strings but struggle to fake the full fingerprint consistently.
What the Fingerprint Is Used For #
| Use | Description |
|---|---|
| Velocity counters | Counts declines per fingerprint over rolling 60s and 10m windows |
| Lockout enforcement | Stores the locked-out fingerprint hash with a 90s expiry |
| Linked Accounts module | Fingerprint match is one of six link types |
| Customer scoring | Customers whose fingerprints match recent attacks get a Card-Testing signal applied to their score |
| Attack History (Pro) | Top-10 attacking fingerprints displayed for forensic review |
| Allowlists (Pro) | Explicit allowlist accepts a fingerprint hash or pattern |
Privacy #
The raw fingerprint inputs (User-Agent, viewport, canvas, fonts) are read from the request and immediately hashed. The plugin never stores or transmits the raw values. The keyed HMAC-SHA256 secret is plugin-instance-specific, so the same browser visiting two different TrustLens-protected stores produces two different hashes — fingerprints cannot be cross-correlated between stores.
For GDPR data export requests, the customer’s fingerprint hashes are included in the export (since they’re processed personal data). Erasure requests wipe them.
Fingerprint Collisions #
It’s theoretically possible for two different devices to produce the same fingerprint hash — two users on the same browser version, same OS, same viewport, same fonts. In practice:
- Free fingerprint (4 signals): collisions are uncommon but occur, especially among customers on similar setups (e.g. iPhones with default font sets)
- Pro fingerprint (5 signals including 12-font): collisions are rare
The defense design accounts for occasional collisions:
- Lockouts are short (90s default) so a colliding legitimate customer is delayed, not blocked
- VIP bypass insulates the most valuable customers from collision effects
- Allowlisting (Pro) provides an explicit override
Fingerprint Visibility #
The fingerprint hash is visible in several admin contexts:
- Card Testing → Recent Events — each velocity event shows the fingerprint hash
- Attack History (Pro) — top-10 attacking fingerprints with counts
- Customer Detail — fingerprints associated with the customer
- Linked Accounts panel — when a link was produced by fingerprint, the hash is shown
The hash is opaque — there’s no way to decode it back to the raw inputs. Admin tooling exposes only the hash plus any associated metadata (which customer’s checkouts produced it, when it was last seen, etc.).
Customizing Fingerprint Inputs #
Developers can modify the fingerprint computation via the trustlens/fingerprint_inputs filter:
add_filter( 'trustlens/fingerprint_inputs', function( $inputs, $request ) {
// Add a custom signal — e.g. a header your CDN sets
$cdn_id = $request->get_header( 'x-cdn-client-id' );
if ( $cdn_id ) {
$inputs['cdn_client'] = $cdn_id;
}
return $inputs;
}, 10, 2 );
The returned array is hashed to produce the final fingerprint. Be careful when modifying — changes invalidate all existing fingerprint state (lockouts, linked accounts, attack history) because previously-stored hashes were computed against the old input set.
What Fingerprints Don’t Do #
Worth being explicit about what the fingerprint is not:
- Not biometric. No fingerprint reader, no facial recognition. “Fingerprint” here is metaphor for device-and-browser identity.
- Not tracking. The fingerprint isn’t used to track customers across the web — it only matches against requests to your store.
- Not credential-based. The customer doesn’t need to be logged in. Fingerprints work for guest checkout.
- Not deterministic identity. Two customers can share a fingerprint if they have very similar setups — the fingerprint is one signal among many, not a sole identity proof.