Skip to content

Arcjet decision inspection reference

The Arcjet decision inspection library provides a set of utilities to more easily interact with the decision returned from an Arcjet SDK.

What are Arcjet utilities?

Arcjet utilities are independent libraries that do not require the use of the main Arcjet SDK—they can be used with or without other Arcjet rules.

We take the pain out of implementing security tasks through these utilities to provide a security as code approach to developer-first security.

Why

In addition to providing an easy-to-consume security recommendation, each Arcjet SDK also provides a lot of metadata attached to every decision. Users can use all of these signals to inform application logic, but it can be quite verbose to extract the information.

As we notice common patterns, we provide optional utilities in the @arcjet/inspect package to streamline these operations.

Install

Terminal window
npm install -S @arcjet/inspect

Usage

// Replace with the framework SDK you're using e.g. `@arcjet/node`
import arcjet, { detectBot } from "@arcjet/next";
import {
isVerifiedBot,
isSpoofedBot,
isMissingUserAgent,
} from "@arcjet/inspect";
import type { NextApiRequest, NextApiResponse } from "next";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
detectBot({
mode: "LIVE",
allow: ["CATEGORY:SEARCH_ENGINE"],
}),
],
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const decision = await aj.protect(req);
// Allow any verified search engine bot without considering any other signals
if (decision.results.some(isVerifiedBot)) {
return res
.status(200)
.json({ name: "Hello bot! Here's some SEO optimized response" });
}
// Block a request if the SDK suggests it
if (decision.isDenied()) {
return res.status(403).json({ error: "Forbidden" });
}
// Blcok any request without a User-Agent header because we expect all
// well-behaved clients to have it
if (decision.results.some(isMissingUserAgent)) {
return res.status(400).json({ error: "You are a bot!" });
}
// Block any client pretending to be a search engine bot but using an IP
// address that doesn't satisfy the verification
if (decision.results.some(isSpoofedBot)) {
return res
.status(403)
.json({ error: "You are pretending to be a good bot!" });
}
res.status(200).json({ name: "Hello world" });
}

API

isSpoofedBot(result: ArcjetRuleResult)

Determines if a non-"DRY_RUN" bot rule detected a spoofed request. If true, the request was likely spoofed and you may want to block it.

For allow rules, Arcjet verifies the authenticity of detected bots by checking IP data and performing reverse DNS lookups. This helps protect against spoofed bots where malicious clients pretend to be a well-behaving bot.

Returns true if the bot rule result was not "DRY_RUN" and a spoofed bot was detected, false if the bot rule result was not "DRY_RUN" and a spoofed bot was not detected, or undefined if the rule result was from a "DRY_RUN" bot rule or a non-bot rule.

Types:

type ArcjetRuleResult = {
ruleId: string;
ttl: number;
state: ArcjetRuleState;
conclusion: ArcjetConclusion;
reason: ArcjetReason;
isDenied: () => boolean;
};

isVerifiedBot(result: ArcjetRuleResult)

Determines if a non-"DRY_RUN" bot rule detected a request from a verified bot. If true, the bot was verified as legitimate and you may want to ignore other signals.

For allow rules, Arcjet verifies the authenticity of detected bots by checking IP data and performing reverse DNS lookups. A verified bot is a bot that has passed these checks.

Returns true if the bot rule result was not "DRY_RUN" and a verified bot was detected, false if the bot rule result was not "DRY_RUN" and a verified bot was not detected, or undefined if the rule result was from a "DRY_RUN" bot rule or a non-bot rule.

Types:

type ArcjetRuleResult = {
ruleId: string;
ttl: number;
state: ArcjetRuleState;
conclusion: ArcjetConclusion;
reason: ArcjetReason;
isDenied: () => boolean;
};

isMissingUserAgent(result: ArcjetRuleResult)

Determines if a non-"DRY_RUN" bot rule errored due to a missing User-Agent header on the request. If true, you may want to block the request because a missing User-Agent header is a good indicator of a malicious request since it is recommended by RFC9110.

Returns true if the rule result was not "DRY_RUN" and the request was missing a User-Agent header, false if the rule result was not "DRY_RUN" and the request had a User-Agent header, or undefined if the rule result was from a "DRY_RUN" bot rule or a non-bot rule.

Types:

type ArcjetRuleResult = {
ruleId: string;
ttl: number;
state: ArcjetRuleState;
conclusion: ArcjetConclusion;
reason: ArcjetReason;
isDenied: () => boolean;
};

What next?

Arcjet can protect your entire app or individual routes with just a few lines of code. Using the main Arcjet SDK you can setup bot protection, rate limiting for your API, minimize fraudulent registrations with the signup form protection and more.

Discussion