docs: add threat analysis page - #949
davidmytton wants to merge 5 commits into
Conversation
Add an Advanced hub for blocking VPNs, proxies, Tor, and hosting IPs with filter rules and decision.ip, plus framework examples and links to the existing SDK IP analysis references. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Move the JS, Python, and Go inspect samples into the page so Astro check does not typecheck incomplete snippet fragments. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Regenerate changed chromium-linux screenshot and llms-txt snapshots after adding the Advanced hub page. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Arcjet Review — 🟢 Low Risk
Decision: Approved
Rationale: Documentation-only PR: adds a new /ip-threat-intelligence guide with per-framework code snippets, wires it into the sidebar, cross-links from the filters index, vpn-proxy-detection blueprint, and shared IPAnalysis reference partial, and refreshes the affected llms-txt and screenshot snapshots. No application code, auth, infrastructure, dependencies, or migrations are touched. All example code uses environment variables for the Arcjet key (no hardcoded secrets) and models the same defensive patterns already used elsewhere in the docs. Screenshot snapshot updates for adjacent pages are expected because the cross-link paragraph was added to them.
Summary of Changes
Adds a new IP threat intelligence documentation page (src/content/docs/ip-threat-intelligence.mdx) with 12 framework-specific example snippets showing how to deny hosting/VPN/proxy/Tor IPs via filters or by inspecting decision.ip. Adds a sidebar entry, cross-links from filters/index, blueprints/vpn-proxy-detection, and the shared IPAnalysis reference partial, updates public/llms-full.txt, refreshes llms-txt snapshots, and adds the new page to the screenshot test list with baseline images.
Notes
Diff is ~750 lines of additions, well under the 1000-line threshold. Binary screenshot baselines are listed in Files Changed but cannot be visually verified — assumed regenerated by the Playwright snapshot update commit.
Review: a0029e04 | Model: anthropic/claude-opus-4-7 | Powered by Arcjet Review
| const decision = await aj.protect(properties.event); | ||
|
|
||
| if (decision.isDenied()) { | ||
| return error(403, "Forbidden"); |
There was a problem hiding this comment.
SvelteKit's error() helper throws internally, so return error(403, "Forbidden") never actually returns — the throw happens first. More importantly, inside a handle hook you generally want to return a Response rather than rely on the error boundary; throwing from handle won't be rendered by your +error.svelte the way a load/action error would. Consider:
| return error(403, "Forbidden"); | |
| if (decision.isDenied()) { | |
| return new Response("Forbidden", { status: 403 }); | |
| } |
| app = FastAPI() | ||
|
|
||
| aj = arcjet( | ||
| key=os.environ["ARCJET_KEY"], # Get your site key from https://console.arcjet.com |
There was a problem hiding this comment.
The JS/TS snippets throw a friendly Cannot find \ARCJET_KEY` environment variableerror, butos.environ["ARCJET_KEY"]raises a bareKeyError: 'ARCJET_KEY'at import time. Consider matching the pattern used elsewhere, e.g.os.environ.get("ARCJET_KEY")` with an explicit check that raises a clearer message — same suggestion for the Flask snippet on line 10.
| `ip.src.relay` unless you intend to block those clients. | ||
|
|
||
| When threat intelligence is available, the JavaScript SDK exposes it as | ||
| `decision.ip.threat`, the Python SDK as `decision.ip_details.threat`, and the |
There was a problem hiding this comment.
The frameworks frontmatter list doesn't include nuxt, but this paragraph links to the Nuxt SDK reference alongside the other frameworks. Is that intentional (i.e. Nuxt users are expected to read this page for reference even though no Nuxt snippet is shown)? If so, worth a one-line note; if not, either add a Nuxt example or drop the Nuxt link to avoid the mismatch.
| In Go, the same signals are fields on `decision.IP`: `IsVPN`, `IsProxy`, | ||
| `IsTor`, `IsHosting`, `IsRelay`, `IsAbuser`, `Service`, and `ASNType`. | ||
|
|
||
| `asnType` is one of `isp`, `hosting`, `business`, or `education`. Real users |
There was a problem hiding this comment.
Nit: Start the rule in \DRY_RUN` if you want to log matches before you enforce them.— the example snippets all hardcodemode: "LIVE". Consider mentioning that readers need to change modein the snippet, or link to a docs section onDRY_RUN`, so this instruction isn't left as a dangling hint.
Show Next.js as an App Router route handler, add Nuxt and Go snippets, and document deny patterns on ip.threat fields. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Update the chromium-linux snapshots after the App Router, Nuxt, Go, and ip.threat example changes. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Page describing how to use Arcjet's threat analysis data.