Threat Scoring
WebDecoy uses a sophisticated deception-first scoring system to evaluate every visitor and request. This page explains exactly how scores are calculated, what each category detects, and how to interpret the results.
Overview
Section titled “Overview”The Threat Score is a number from 0-100 that measures the likelihood a visitor is automated or malicious. It combines signals from 9 detection categories using weighted averages, with the strongest evidence contributing the most to the final score.
┌─────────────────────────────────────────────────────────────────┐│ THREAT SCORING PIPELINE │├─────────────────────────────────────────────────────────────────┤│ ││ Visitor Request ││ │ ││ ▼ ││ ┌───────────────────────────────────────────────────────┐ ││ │ 9 DETECTION CATEGORIES │ ││ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ ││ │ │Honeypot │ │ Attack │ │Fingerprnt│ │Behavior │ │ ││ │ │ 38% │ │ 24% │ │ 11% │ │ 10% │ │ ││ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ ││ │ │ │ │ │ │ ││ │ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │ ││ │ │ TLS │ │ Geo │ │ IP │ │ Headers │ │ ││ │ │ 7% │ │ 5% │ │ 3% │ │ 1% │ │ ││ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ ││ │ │ │ │ │ │ ││ │ ┌─────────┐ │ ││ │ │ User │ │ ││ │ │Agent 1% │ │ ││ │ └────┬────┘ │ ││ └───────┼───────────┼───────────┼───────────┼───────────┘ ││ │ │ │ │ ││ └───────────┴─────┬─────┴───────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ WEIGHTED SUM │ ││ │ = Final Score │ ││ └────────┬────────┘ ││ │ ││ ▼ ││ ┌───────────────────────────────┐ ││ │ Threat Score: 0-100 │ ││ │ + Category Classification │ ││ │ + Confidence Percentage │ ││ └───────────────────────────────┘ │└─────────────────────────────────────────────────────────────────┘Key Principles
Section titled “Key Principles”| Principle | Description |
|---|---|
| Deception-First | Honeypot signals are weighted highest because legitimate users never interact with hidden traps |
| Weighted Averages | Categories are multiplied by their weight, not simply summed |
| Defense in Depth | Multiple signals provide stronger evidence than any single indicator |
| Low False Positives | Easily-spoofed signals (User-Agent, headers) have minimal impact |
How Scoring Works
Section titled “How Scoring Works”The scoring calculation follows a simple three-step process:
Step 1: Category Scoring
Section titled “Step 1: Category Scoring”Each detection category analyzes incoming requests and produces a score from 0-100:
Category Score = Analysis of signals within that category (0 = no suspicious signals, 100 = maximum suspicion)Step 2: Weight Application
Section titled “Step 2: Weight Application”Each category score is multiplied by its weight percentage:
Weighted Score = Category Score × Weight PercentageStep 3: Final Calculation
Section titled “Step 3: Final Calculation”All weighted scores are summed to produce the final Threat Score:
Final Score = Sum of all Weighted ScoresExample Calculation
Section titled “Example Calculation”Consider a visitor who triggered some honeypot signals and has suspicious headers:
| Category | Raw Score | Weight | Weighted Score |
|---|---|---|---|
| Honeypot Signals | 30 | × 38% | = 11.4 |
| Attack Signatures | 0 | × 24% | = 0 |
| Browser Fingerprint | 0 | × 11% | = 0 |
| Behavioral Analysis | 0 | × 10% | = 0 |
| TLS Fingerprint | 0 | × 7% | = 0 |
| Geo Consistency | 0 | × 5% | = 0 |
| IP Reputation | 0 | × 3% | = 0 |
| HTTP Headers | 15 | × 1% | = 0.15 |
| User Agent | 0 | × 1% | = 0 |
| Total: | 12 |
Result: This visitor receives a Threat Score of 12 (Minimal risk).
Detection Categories & Weights
Section titled “Detection Categories & Weights”Categories are weighted by reliability. High-confidence signals like honeypot triggers contribute more than easily-spoofed signals like User-Agent strings.
Weight Distribution
Section titled “Weight Distribution”| Priority | Category | Weight | Why This Weight |
|---|---|---|---|
| Highest | Honeypot Signals | 38% | Core deception signal - legitimate users never trigger these |
| High | Attack Signatures | 24% | Active exploitation attempts are clear malicious intent |
| Medium | Browser Fingerprint | 11% | Automation tools have detectable anomalies |
| Medium | Behavioral Analysis | 10% | Non-human patterns are reliable indicators |
| Medium | TLS Fingerprint | 7% | JA3/JA4 fingerprints are hard to spoof |
| Low | Geo Consistency | 5% | Timezone, language and WebRTC mismatches indicate VPN or proxy |
| Low | IP Reputation | 3% | High false-positive potential (VPN users) |
| Low | HTTP Headers | 1% | Easily spoofed by sophisticated bots |
| Low | User Agent | 1% | Trivially spoofed, catches only obvious cases |
Visual Weight Comparison
Section titled “Visual Weight Comparison”Honeypot Signals ██████████████████████████████████████ 38%Attack Signatures ████████████████████████ 24%Browser Fingerprint ███████████ 11%Behavioral Analysis ██████████ 10%TLS Fingerprint ███████ 7%Geo Consistency █████ 5%IP Reputation ███ 3%HTTP Headers █ 1%User Agent █ 1% ───────────────────────────────────────── 0% 25% 50% 75% 100%Category Details
Section titled “Category Details”Honeypot Signals (38% Weight)
Section titled “Honeypot Signals (38% Weight)”Priority: Highest
Detects visitors who access hidden decoy links, fill invisible form fields, or interact with trap endpoints.
| Signal Type | Description | Score Impact |
|---|---|---|
| Hidden field filled | Invisible form field populated (reported by the Detection Script) | +40 |
| Hidden link clicked | Hidden link followed (reported by the Detection Script) | +40 |
| Decoy link or decoy endpoint accessed | Trap resource fetched | +30 |
| SDK tripwire hit | Hidden tripwire path requested | +40 |
Points add up within the component, which is capped at 100.
Why it matters: Legitimate users never see or interact with these hidden elements. A trigger here is strong evidence of automated scanning or malicious reconnaissance. This is the cornerstone of WebDecoy’s deception-first approach.
Server-side traps score here too
Section titled “Server-side traps score here too”The hidden-field and hidden-link signals are reported by the browser-side Detection Script. A server-side trap (a decoy or tripwire) is a different shape of evidence: somebody fetched a hidden URL, ran no JavaScript, and reported nothing. Those hits score on this component in their own right.
This matters more categorically than numerically. Any honeypot score at or above 20 classifies the visitor as a scanner, so a client that reached a hidden resource is never filed as legitimate again, however clean the rest of its request looks. A detection that both fetched a decoy and reported a client-side trigger is counted once, not twice.
Sources that are not deception (the edge sensor, the detection script’s own beacon, ordinary SDK traffic) contribute nothing to this component.
Attack Signatures (24% Weight)
Section titled “Attack Signatures (24% Weight)”Priority: High
Identifies known attack patterns in request payloads including injection attempts and exploitation techniques.
| Attack Type | Pattern Examples | Score Impact |
|---|---|---|
| SQL Injection | ' OR '1'='1, UNION SELECT, ; DROP TABLE |
+50 |
| Command Injection | ; cat /etc/passwd, ` |
ls -la, `` whoami` `` |
| Cross-site Scripting (XSS) | <script>, javascript:, onerror= |
+40 |
| Path Traversal | ../../../etc/passwd |
+50 |
| Mass Assignment | Privilege fields such as is_admin in a JSON body |
+45 |
| XXE | <!DOCTYPE with <!ENTITY, SYSTEM "file: in an XML body |
+55 |
| PHP / Java deserialization | Serialized PHP objects, rO0AB Java streams |
+60 |
Each additional attack type in the same request adds +20. The component is capped at 100.
Why it matters: These are direct indicators of malicious intent. These patterns are rarely seen in legitimate traffic and represent active exploitation attempts.
Example Detection:
POST /api/users/login HTTP/1.1Content-Type: application/json
→ Attack Signature Score: 50 (SQL Injection detected)Browser Fingerprint (11% Weight)
Section titled “Browser Fingerprint (11% Weight)”Priority: Medium
Analyzes client-side fingerprinting data to detect headless browsers, automation tools, or spoofed environments.
| Signal | Detection Method | Score Impact |
|---|---|---|
| WebDriver detected | navigator.webdriver = true |
+65 |
| Automation framework | Puppeteer, Playwright or Selenium markers | +60 |
| Headless browser markers | Chrome headless signatures (desktop only) | +45 to +60 |
| CDP artifacts | Chrome DevTools Protocol markers | +50 |
| Canvas anomaly | Canvas fingerprint doesn’t match browser | +35 |
| WebGL anomaly | GPU fingerprint mismatch | +30 |
| Software renderer | SwiftShader and similar (also common on VMs) | +25 |
| Plugin anomaly | Plugin configuration inconsistent (desktop only) | +25 |
| No plugins | Empty plugins list (desktop only) | +10 |
| Lie/tampering | Native functions modified by stealth plugins | +8 each, +30 max |
| Mocked audio | Mocked or zeroed AudioContext | +15 to +20 |
AI browser extension flags also score here; see AI Detections.
Why it matters: Automation tools often have telltale fingerprint anomalies that are difficult to fake convincingly. While sophisticated bots can spoof some signals, maintaining consistent fingerprints across all dimensions is challenging.
Example Detection:
// Detected anomalies:navigator.webdriver = true // WebDriver flag setnavigator.plugins.length = 0 // No plugins (unusual)window.cdc_adoQpoasnfa76pfcZLmcfl_Array // ChromeDriver CDP artifact
→ Fingerprint Score: 100 (capped)Behavioral Analysis (10% Weight)
Section titled “Behavioral Analysis (10% Weight)”Priority: Medium
Examines interaction patterns including mouse movements, keyboard input, scroll behavior, and navigation timing.
| Signal | What It Detects | Score Impact |
|---|---|---|
| Ghost clicks | Clicks at positions with no prior mouse activity | +45 |
| Instant clicks | Clicks with no delay after the mouse stops | +30 |
| Low mouse count | Very few mouse movements on desktop | +25 |
| Linear mouse paths | Perfectly straight mouse paths | +20 |
| Clicks without movement | Clicks with no preceding mouse movement | +20 |
| Constant mouse velocity | No human acceleration | +15 |
| Instant mouse movements | Programmatic cursor jumps | +15 |
| Constant scroll speed | Robotic scrolling (desktop only) | +15 |
| Grid-aligned mouse | Movements aligned to a grid | +10 |
Mouse, click and scroll signals are skipped on mobile devices.
Why it matters: Bots typically exhibit non-human behavior patterns: too fast, too uniform, or missing expected interactions. Real humans have micro-movements, variable timing, and natural browsing patterns that are difficult to simulate perfectly.
Example Detection:
Session Analysis (illustrative):├── Mouse movements: 2 on desktop → low mouse count +25├── Click with no prior movement → ghost click +45└── Mouse path perfectly straight → linear path +20
→ Behavior Score: 90TLS Fingerprint (7% Weight)
Section titled “TLS Fingerprint (7% Weight)”Priority: Medium
Uses JA3/JA4 fingerprinting to identify the TLS client implementation and match against known automation tools.
| TLS Signal | What It Indicates | Score Impact |
|---|---|---|
| Minimal cipher suite | Far fewer ciphers than any browser offers | +50 |
| Low cipher count | Fewer ciphers than a browser | +25 |
| Minimal TLS extensions | Almost no extensions | +40 |
| Low extension count | Fewer extensions than a browser | +20 |
| JA3 with no extensions | Extension list empty | +30 |
| Known VPN/proxy fingerprint | Handshake matches a known VPN or proxy client | +25 |
| Low signature algorithm count | Typical of automation libraries | +20 |
| Browser UA without h2 ALPN | Claims a modern browser but does not offer HTTP/2 | +15 |
Why it matters: TLS fingerprints are generated at the protocol level before any application code runs, so a handshake that offers far less than a browser does gives away a script even when the User-Agent claims a browser. The JA3 and JA4 fingerprints are recorded on the detection; JA4 is the value WAF rules key on.
Geo Consistency (5% Weight)
Section titled “Geo Consistency (5% Weight)”Priority: Low
Cross-checks what the browser says about itself against where the connection appears to come from.
| Signal | What It Detects | Score Impact |
|---|---|---|
| WebRTC address mismatch | Real address differs from the connection address | +30 |
| Timezone mismatch | Browser timezone contradicts IP geolocation | +20 |
| Language mismatch | Browser language contradicts the country | +15 |
| Composite VPN likelihood | Several geo signals agreeing | +10 |
Why it matters: These are the signals that survive a good proxy. A scraper can route through a residential exit node and still be running on a machine set to a different timezone with a different locale. The weight is low on purpose, because privacy-conscious real people trip these constantly.
IP Reputation (3% Weight)
Section titled “IP Reputation (3% Weight)”Priority: Low
Checks IP addresses against threat intelligence feeds and identifies datacenter/proxy/VPN connections.
| Signal | Source | Score Impact |
|---|---|---|
| AbuseIPDB abuse confidence | AbuseIPDB | Scaled from the confidence score |
| Abuse report count | AbuseIPDB | Scaled from the number of reports |
| TOR exit node | GeoIP / VPN detection | +45 |
| Open proxy | GeoIP / VPN detection | +30 |
| VPN service | GeoIP / VPN detection | +25 |
| Datacenter hosting | IP belongs to a hosting provider | +20 |
| Anonymous IP | Flagged as an anonymity service | +20 |
| Privacy relay | iCloud Private Relay, WARP and similar | +15 |
| Many user agents on one IP | Distinct user agents from the address in 24h | Scaled |
| Impossible travel | Same client seen too far apart too quickly | Scaled |
Why it matters: Provides useful context but has high false-positive potential. Many legitimate users use VPNs for privacy, and datacenter IPs might be corporate proxies. That’s why this category only contributes 3% to the final score.
HTTP Headers (1% Weight)
Section titled “HTTP Headers (1% Weight)”Priority: Low
Analyzes HTTP request headers for missing standard headers or patterns associated with automated tools.
| Signal | What’s Detected | Score Impact |
|---|---|---|
| Missing standard headers | Accept, Accept-Language, Accept-Encoding and similar | +10 each |
| No Referer | Direct access to deep pages | +15 |
| Text-only Accept | Asks for text content only, no images | +15 |
| Missing Sec-Fetch-* | Modern browser UA without Sec-Fetch headers | Scaled |
| Missing Client Hints | Chrome 89+ UA without Client Hints | +12 |
| Sec-CH-UA without GREASE | Spoofed Client Hints | +10 |
| Accept-Language without quality values | Real browsers send ;q= weights |
+8 |
| Missing Priority header | Chrome 119+ UA without it | +6 |
| Generic Accept | */* |
+5 |
| No cookies | Stateless client or first visit | +5 |
Connection: close |
Uncommon for browsers | +5 |
Why it matters: Simple bots often omit headers that real browsers include automatically. However, this is easily spoofed by adding the expected headers, which is why the weight is low.
Example:
GET /api/data HTTP/1.1Host: example.comUser-Agent: Mozilla/5.0...# Missing: Accept, Accept-Language, Accept-Encoding, Cookie, Referer
→ Several header signals fire (missing headers, no cookies, no Referer)User Agent (1% Weight)
Section titled “User Agent (1% Weight)”Priority: Low
Examines User-Agent strings for bot signatures, outdated versions, or obvious automation markers.
A catalogued agent is scored by the registry
Section titled “A catalogued agent is scored by the registry”If the User-Agent matches an agent in WebDecoy’s shared agent registry, this component takes the registry’s base score for that agent. It does not guess from how the name is spelled.
That distinction turned out to matter a great deal. The old heuristic returned 100 for any User-Agent containing the substring bot, which meant:
| Agent | Registry base | Old heuristic score | Why |
|---|---|---|---|
| ChatGPT-User | 85 | 100 | Matched bot inside +https://openai.com/bot, the courtesy URL a crawler publishes so it can be identified |
| ByteSpider | 75 | 35 | Contains no bot anywhere, so it fell through to the generic suspicious-UA rule |
ByteSpider, the only one of those two that ignores robots.txt, was scoring roughly half its base while agents whose names happen to contain “bot” landed near theirs. Catalogued agents now sit in the order the registry assigns rather than the order their names are spelled.
Agents the registry has never heard of keep the older heuristics below, because that fallback is still the right answer for a self-identifying tool nobody has catalogued yet.
| Signal | Examples | Score Impact |
|---|---|---|
| Catalogued agent | GPTBot, ByteSpider, Googlebot, curl, python-requests | The registry’s base score for that agent |
| Uncatalogued bot or tool UA | Self-identifying tools nobody has catalogued | Heuristic, up to 100 |
| Empty User-Agent | No UA provided | +25 |
| Outdated browser | Chrome or Firefox many versions behind | +15 to +70 |
| Chromium UA with no client hints | Claims Chrome, sent no Sec-CH-UA |
+50 |
| Browser UA that never rendered | A request-log visit fetched pages but none of their scripts or styles | +45 |
| Browser UA that read crawler files | The same visit also asked for robots.txt, a sitemap, ads.txt or security.txt |
+30 |
A browser that never drew the page
Section titled “A browser that never drew the page”The last two rows come only from sources that log every request your site answers: the Vercel log drain and Fastly log streaming. A browser that opens a page goes on to fetch the page’s own scripts and styles. A scraper that copies a browser’s user agent takes the HTML and leaves.
Logs arrive in small deliveries, often a few requests at a time, so a page and the scripts its browser fetched a second later usually arrive separately. WebDecoy holds each browser-like page request for 45 seconds, then checks whether that browser (same site, address and user agent) fetched any of the site’s render assets. Render assets are /_next/static/ files, ?_rsc= payloads, /_next/data/, Vercel Analytics beacons, and same-site .js, .css and web fonts. Images, Open Graph cards and favicons do not count, because link-preview bots fetch those too.
That evidence is kept for 30 days as a keyed hash of the site, address and user agent, never the address itself, so every server handling your logs sees the same answer. Nothing else about the request is kept.
It is deliberately cautious:
- A browser that rendered at any point in the last 30 days is not flagged, so a returning visitor whose assets come from cache is not mistaken for a scraper. A visitor whose last rendered visit was longer ago than that, with every asset still cached, can be; those reports score MINIMAL.
- A page is left undecided, never flagged, when we have not recently seen your site serve render assets (asset logging may be off) or when the evidence cannot be read.
- One report per browser per site per 30 minutes, however many pages it reads.
- A person who opens
robots.txtby hand after reading the site is not flagged, because they rendered.
Visits that rendered are not reported or stored. A scraper that runs a full headless browser fetches the assets too and passes this check; the other signals on this page are still there for it.
An unverified claim may not profit from the identity it claims
Section titled “An unverified claim may not profit from the identity it claims”Granting every catalogued agent its base score has an obvious hole: 44 registry agents carry a base of 40 or less and publish no IP ranges anyone can check. Slackbot, Twitterbot, Discordbot, WhatsApp, TelegramBot, LinkedInBot, UptimeRobot, Pingdom, the Wayback Machine, YandexBot, Baiduspider, Yahoo! Slurp and Sogou are all in that set. For every one of them, simply claiming the identity would buy a low score.
Verification is what separates the two cases, so it does:
- A verified agent is scored exactly as the registry says.
- An unverified claim gets the worse of the registry base and the heuristic.
It can never be cheaper to claim an identity than to arrive without one. The rule only ever raises a score, so the registry fix survives intact: ByteSpider is unverified with a base of 75 against a heuristic of 35, and keeps the 75.
The major search engines were never exposed to this, because Googlebot, Bingbot, DuckDuckBot and Applebot all publish IP ranges, so a spoofed one hits the impersonation floor long before it reaches this rule. The gap was entirely in the crawlers that publish nothing, which is also where it is hardest to notice.
Why it matters: User-Agent is trivially spoofed by any bot, so it receives minimal weight (1%). It only catches the most obvious, unsophisticated bots that don’t bother to set a realistic User-Agent, plus the ones that catalogue themselves honestly.
Threat Levels
Section titled “Threat Levels”Scores are grouped into five threat levels for easier interpretation and action.
Level Overview
Section titled “Level Overview”| Score Range | Level | Confidence needed | Description | Recommended Action |
|---|---|---|---|---|
| 0-20 | MINIMAL | none | Very low risk, likely legitimate | Allow |
| 21-40 | LOW | none | Some signals, probably benign | Log |
| 41-60 | MEDIUM | 30% | Suspicious activity detected | Monitor/Challenge |
| 61-80 | HIGH | 50% | Strong bot/malicious indicators | Challenge/Block |
| 81-100 | CRITICAL | 70% | Almost certainly automated/malicious | Block |
The level is gated by confidence as well as score. A detection scoring 90 on signals the scorer is only 40% confident in is reported as MEDIUM, not CRITICAL: the number says how much evidence there is, and the level says how much of it we would stand behind.
The recommended actions are guidance for your own policy. WebDecoy does not block or challenge a request because of its level: that is decided by your protected paths, response actions and SDK or plugin mode (Monitor by default).
MINIMAL (0-20)
Section titled “MINIMAL (0-20)”Score: 12 | Level: MINIMAL | ● GreenCharacteristics:
- Few or no suspicious signals detected
- Normal browsing patterns observed
- Standard browser fingerprint
- Good IP reputation
Interpretation: This is normal, legitimate traffic. The visitor behaves like a real human using a standard browser.
Recommended Actions:
- Allow the request
- No special logging required
- No alerts needed
LOW (21-40)
Section titled “LOW (21-40)”Score: 35 | Level: LOW | ● LimeCharacteristics:
- Minor signals present (e.g., VPN usage, missing header)
- No honeypot triggers
- Mostly normal behavior patterns
- Could be privacy-conscious user or minor automation
Interpretation: Some signals are present but likely benign. Could be a legitimate user with a VPN or unusual browser configuration.
Recommended Actions:
- Allow the request
- Log for pattern analysis
- Monitor for escalation
MEDIUM (41-60)
Section titled “MEDIUM (41-60)”Score: 52 | Level: MEDIUM | ● YellowCharacteristics:
- Multiple suspicious signals
- Possible fingerprint anomalies
- Unusual behavior patterns
- May have triggered low-weight honeypots
Interpretation: Suspicious activity that warrants attention. Could be a scanner, scraper, or unsophisticated bot.
Recommended Actions:
- Consider CAPTCHA challenge
- Log with high priority
- Alert on repeated occurrences
- Manual review recommended
HIGH (61-80)
Section titled “HIGH (61-80)”Score: 73 | Level: HIGH | ● OrangeCharacteristics:
- Strong indicators of automation
- Likely honeypot triggers
- Fingerprint clearly indicates bot/headless browser
- Suspicious or malicious patterns
Interpretation: Almost certainly not a legitimate human user. This is likely a bot, scanner, or attacker.
Recommended Actions:
- Challenge or block
- Alert security team
- Add IP to watchlist
- Investigate the attack pattern
CRITICAL (81-100)
Section titled “CRITICAL (81-100)”Score: 92 | Level: CRITICAL | ● RedCharacteristics:
- Multiple high-confidence indicators
- Attack signatures detected
- Honeypot(s) triggered
- Clear malicious intent
Interpretation: This is definitely automated or malicious traffic. Active attack or aggressive scanning in progress.
Recommended Actions:
- Block immediately
- Alert security team
- Consider IP blocking at edge
- Investigate and document
- Report to threat intelligence if applicable
Threat Categories
Section titled “Threat Categories”Beyond the numeric score, visitors are classified into categories based on which signals triggered.
Category Classification Logic
Section titled “Category Classification Logic”Categories are determined by evaluating signals in priority order:
1. Attack Signatures ≥ 30 → ATTACKER2. Honeypot ≥ 40 AND Fingerprint ≥ 30 → BOT3. Honeypot ≥ 20 → SCANNER4. The agent registry names this agent's kind → that kind5. User Agent ≥ 90 → SCANNER6. User Agent ≥ 60 → CRAWLER7. Fingerprint ≥ 40 AND confidence ≥ 30% → SCRAPER8. User Agent ≥ 30 OR Headers ≥ 25 → SCRAPER9. Default → LEGITIMATEThe ordering is the design: evidence of what the request did (attack signatures, honeypot trips) beats identity (the registry’s answer for a named agent) beats inference (a kind guessed from the size of an anomaly score).
Category Descriptions
Section titled “Category Descriptions”| Category | Icon | Triggers | Description |
|---|---|---|---|
| Attacker | ⚠️ | Attack signatures (SQLi, XSS, etc.) | Active exploitation attempts |
| Bot | 🤖 | Honeypot + fingerprint anomalies | Automated traffic with technical non-human signs |
| Scanner | 📡 | Any honeypot/decoy trigger | Reconnaissance or vulnerability scanning |
| Crawler | 🕷️ | Known crawler User-Agent | Web crawlers and indexing bots |
| Scraper | 📋 | Fingerprint anomalies (no honeypot) | Content scraping or data harvesting |
| Legitimate | ✓ | All signals below threshold | Normal human visitor |
Category Examples
Section titled “Category Examples”Attacker:
Request: POST /api/loginBody: {"password": "' OR '1'='1"}Attack Signature Score: 50→ Category: ATTACKERBot:
Clicked a hidden link, then fetched /admin/backup.zip (decoy)Fingerprint: WebDriver=true, no pluginsHoneypot Score: 70, Fingerprint Score: 75→ Category: BOTScanner:
Accessed: /.git/config (decoy)Normal fingerprint otherwiseHoneypot Score: 30→ Category: SCANNERLegitimate:
Normal browsing patternNo honeypots triggeredAll signals < thresholds→ Category: LEGITIMATEConfidence Score
Section titled “Confidence Score”The Confidence percentage indicates how certain WebDecoy is about the threat assessment.
How Confidence is Calculated
Section titled “How Confidence is Calculated”Confidence is based on the number and quality of active signals:
| Factor | Impact |
|---|---|
| More signal categories active | Higher confidence |
| Attack signature at 50 or above | +30% confidence boost |
| Honeypot at 60 or above | +25% confidence boost |
| Fingerprint at 50 or above and at least one reliable automation flag | +20% confidence boost |
| Only 1-2 weak signals | Lower confidence |
Confidence Formula
Section titled “Confidence Formula”Base Confidence = (Active Categories / 9) × 100
Adjustments:+ 30% if attack signature score ≥ 50+ 25% if honeypot score ≥ 60+ 20% if fingerprint score ≥ 50 AND a reliable fingerprint flag firedInterpreting Confidence
Section titled “Interpreting Confidence”| Confidence | Meaning | Action |
|---|---|---|
| 80-100% | Very certain | Act on the score |
| 60-79% | Reasonably certain | Act with monitoring |
| 40-59% | Moderate certainty | Consider challenging |
| 20-39% | Low certainty | Log and observe |
| 0-19% | Very uncertain | Collect more data |
Verified identity changes what the numbers mean
Section titled “Verified identity changes what the numbers mean”The categories above measure how automated and how evasive a client looks. A verified identity (a match against the crawler’s published IP ranges, a forward-confirmed reverse DNS record, or a Web Bot Auth signature) answers both of those questions at once: a verified crawler is exactly as automated as it says it is, and hiding is the one thing it is not doing.
Two rules follow from that, and both were shipped after production data showed the scorer treating large legitimate crawler fleets as adversaries.
Rotation does not escalate a verified agent
Section titled “Rotation does not escalate a verified agent”A crawler fleet is one identity operating from many addresses by design. Before this rule, the rotation bonus escalated range-verified Bingbot and ChatGPT-User fetching ordinary pages into HIGH and CRITICAL.
The escalation is now skipped when the scorer confirmed the claimed identity. Spoofed and unverified claims still escalate, so a forged Googlebot arriving from residential ranges keeps scoring at the top. If a rotation bonus was recorded before verification resolved, it is dropped when the detection is rescored rather than carried forward.
A verified agent is capped at the top of MEDIUM
Section titled “A verified agent is capped at the top of MEDIUM”Even without the rotation bonus, verified agents kept landing in HIGH on anomaly evidence alone. Bingbot’s own renderer scored 91 and above, because its Chromium honestly reports navigator.webdriver and its fleet trips every datacenter, VPN and spoofed-UA heuristic there is. Verified PerplexityBot and GPTBot page reads sat at 74 to 75.
A detection whose identity verified is now capped at 60, the top of the MEDIUM band, applied after every score contribution including the client-side blend, so nothing downstream re-inflates it. The cap records itself as a signal carrying the pre-cap score, so the breakdown still shows what the anomaly tiers saw and why the ceiling applied.
Hostile acts bypass the ceiling. A honeypot trip or an attack signature is evidence of what the request did, not of what the client is, and a verified agent in a decoy is a real event whatever its identity. Spoofed and unverified claims are untouched.
Using Scores Effectively
Section titled “Using Scores Effectively”Suggested Thresholds for Your Own Logic
Section titled “Suggested Thresholds for Your Own Logic”WebDecoy has no score-threshold block setting. If you act on scores yourself (for example from a webhook or your own middleware), these are reasonable starting points:
| Use Case | Block Threshold | Challenge Threshold |
|---|---|---|
| Financial / Banking | 55 | 40 |
| E-commerce | 65 | 50 |
| Standard Websites | 75 | 60 |
| Public Content / Blogs | 85 | 70 |
| Monitoring Only | N/A (log only) | N/A |
Score-Based Decision Logic
Section titled “Score-Based Decision Logic”function handleRequest(detection) { // Field names from the detection API; confidence is 0 to 1 const { unified_score: score, confidence, threat_category: category } = detection;
// Critical threats - block immediately if (score >= 80 && confidence >= 0.6) { return blockRequest(); }
// High threats - challenge or block if (score >= 60) { if (category === 'attacker') { return blockRequest(); } return challengeWithCaptcha(); }
// Medium threats - log and monitor if (score >= 40) { logHighPriority(detection); return allowWithMonitoring(); }
// Low/Minimal threats - allow return allowRequest();}Filtering by Category
Section titled “Filtering by Category”Use category filters in the Detections table to focus on specific threat types:
- Attackers first: select
Attackerin the Threat Category panel to investigate active exploitation attempts - Scanner review: select
Scannerto see what reconnaissance activity is happening - Legitimate verification: select
Legitimatewith a high minimum threat score to find potential false positives
Tuning for Your Environment
Section titled “Tuning for Your Environment”Reducing False Positives:
- Raise the threshold your own logic blocks at (e.g., 75 → 85)
- Rely on verified identity: good bots (Googlebot, Bingbot) are verified by IP, and a verified agent is capped at 60
- Review medium-score detections manually, and mark wrong ones Not a bot
Catching More Threats:
- Lower the threshold your own logic blocks at (e.g., 75 → 65)
- Add more decoy links to pages
- Install the Detection Script for JavaScript and behavioral analysis
- Monitor category distribution for patterns
The score explains itself, per detection
Section titled “The score explains itself, per detection”Everything above describes the system in general. To see why one particular detection scored what it did, open it in the dashboard: the detection detail flyout carries a Threat Score Breakdown built from the per-signal attribution the scorer recorded at the time.
Each contributing signal is listed with its name, the points it added, the ceiling for that signal, a bar, and the description the scorer wrote for it:
Threat score: High 87 / 100 Honeypot path hit +40 Datacenter IP, no rDNS +22 of 25 Header order ≠ claimed UA +15 of 20Three things about that display are deliberate:
- The parts do not sum to the whole, and the panel says so. Categories are weighted and capped, so printing
40 + 22 + 15 = 87would be arithmetic that fails the first time anyone checks it. The listed points are what moved the score, largest first. - The ceiling is only printed when the signal did not reach it. Most signals contribute a fixed amount and therefore sit at their own ceiling by definition, so “+40 of 40” is noise on every line. “+10 of 30” says something: this one was dialled down and could have been worse.
- Bars compare signals to each other, not to 100. A bar scaled to an absolute maximum drew the largest contributor half full while a signal worth half as much drew a whole one, which ranked the picture in the opposite order to the numbers beside it.
Signals that scored zero are dropped from the list, because twelve “+0” rows under a score of 87 bury the four that produced it. The radar chart alongside is where “we looked at this category and saw nothing” belongs.
Confidence is stated in prose, and only when it is low enough to qualify the score.
A How scoring works link at the foot of the breakdown opens the general explainer, which is what this page describes.
Related Documentation
Section titled “Related Documentation”- AI Scraper Scoring - Separate scoring dimension for AI training crawlers
- Response Actions - Automated responses to threats
- Detection Script - JavaScript-based bot detection