@arcjet/node
弧喷 是您AI代码中的运行时安全平台。 检测出快速注射,授权代理工具呼叫,编辑敏感数据,并阻断bots和滥用. 在行动发生前,您在应用程序内拨打实时安全构件.
这是 弧喷 SDK 为 节点.js 请求保护 —— 说
使用它来保护HTTP路由处理器和API端点. 如果你需要保护
AI代理工具呼叫, MCP 服务器处理器, 或背景任务( 任何没有
hTTP 请求,参见 @arcjet/guard。 。 。 .
为什么是Arcjet?
您的应用程序的AI功能和代理采取真实的行动,呼叫工具,读取数据,打击API. Arcjet在代码内运行 让你实时执行每个动作的安全 然后审计发生了什么
开始
快速设置 AI 代理
- 登录 CLI :
npx @arcjet/cli auth login - 安装版本代理技能, 这样您的编码代理匹配 SDK :
npx @tanstack/intent@latest install - 告诉你的探员要保护什么 剩下的就交给他.
手动设置
- 登录 使用 CLI(或
app.arcjet.com:npx @arcjet/cli auth login npm install @arcjet/node- 设定
ARCJET_KEY=ajkey_yourkey在你的环境中 - 将 Arcjet 添加到您的服务器中 快速开始 下级
npm 软件包 | GitHub 来源 | 完整文档 | 其他 SDKs 软件
特征
以下所有特征均可使用 @arcjet/node 请求保护.
警卫保护(工具呼叫、MCP服务器、队列)见
@arcjet/guard。 。 。 .
| 特性 | @arcjet/node | @arcjet/guard |
|---|---|---|
| 限制费率 | ✅ | ✅ |
| 快速注射检测 | ✅ | ✅ |
| 敏感信息检测 | ✅ | ✅ |
| 瓶装保护 | ✅ | —— 说 |
| 盾牌 WAF | ✅ | —— 说 |
| 电子邮件验证 | ✅ | —— 说 |
| 注册表保护 | ✅ | —— 说 |
| 请求过滤器 | ✅ | —— 说 |
| IP 分析 | ✅ | —— 说 |
| 自定义规则 | —— 说 | ✅ |
- 🔒 快速注射检测 - 探测和阻断 在到达你的LLM前立即注射.
- 🤖 瓶装保护 · 停止刮刮机、证明材料和 AI爬行者滥用你的终点.
- 🛑 限制费率 - 标志桶、固定窗口和滑动 窗口算法; 每个用户的模型 AI 符号预算.
- 🕵️ 敏感信息检测 - 块 PII,信用卡和定制模式 从进入你的AI管道.
- 🛡️ 盾牌 WAF • 防止SQL注射、XSS和其他 常见的网络攻击.
- 📧 电子邮件验证 一次性、无效和 注册时无法提供地址 .
- 📝 注册表保护 结合机器人保护, 电子邮件验证, 以及限制您注册表格的速率 .
- 🎯 请求过滤器 ——IP,路径上以表达为主的规则, 标题和自定义字段.
- 🌐 IP 分析 地理定位、ASN、VPN、代理、Tor和托管 检测包括每个请求.
快开始
此示例保护一个带有bot检测器的Node.js HTTP服务器,Shield WAF, 和象征性的桶价格限制.
// index.ts
import arcjet, { detectBot, shield, tokenBucket } from "@arcjet/node";
import { isSpoofedBot } from "@arcjet/inspect";
import http from "node:http";
const aj = arcjet({
key: process.env.ARCJET_KEY!, // Get your key with: npx @arcjet/cli sites get-key
rules: [
// Shield protects your app from common attacks e.g. SQL injection
shield({ mode: "LIVE" }),
// Create a bot detection rule
detectBot({
mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only
// Block all bots except the following
allow: [
"CATEGORY:SEARCH_ENGINE", // Google, Bing, etc
// Uncomment to allow these other common bot categories
// See the full list at https://arcjet.com/bot-list
//"CATEGORY:MONITOR", // Uptime monitoring services
//"CATEGORY:PREVIEW", // Link previews e.g. Slack, Discord
],
}),
// Token bucket rate limit. Other algorithms are supported.
tokenBucket({
mode: "LIVE",
// Tracked by IP address by default, but this can be customized
// See https://docs.arcjet.com/fingerprints
refillRate: 5, // Refill 5 tokens per interval
interval: 10, // Refill every 10 seconds
capacity: 10, // Bucket capacity of 10 tokens
}),
],
});
const server = http.createServer(async function (
req: http.IncomingMessage,
res: http.ServerResponse,
) {
const decision = await aj.protect(req, { requested: 5 }); // Deduct 5 tokens
console.log("Arcjet decision", decision);
if (decision.isDenied()) {
if (decision.reason.isRateLimit()) {
res.writeHead(429, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Too many requests" }));
} else if (decision.reason.isBot()) {
res.writeHead(403, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "No bots allowed" }));
} else {
res.writeHead(403, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Forbidden" }));
}
} else if (decision.ip.isHosting()) {
// Requests from hosting IPs are likely from bots.
// https://docs.arcjet.com/blueprints/vpn-proxy-detection
res.writeHead(403, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Forbidden" }));
} else if (decision.results.some(isSpoofedBot)) {
// Verifies the authenticity of common bots using IP data.
// Verification isn't always possible, so check the results separately.
// https://docs.arcjet.com/bot-protection/reference#bot-verification
res.writeHead(403, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Forbidden" }));
} else {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "Hello world" }));
}
});
server.listen(8000);
全文见 Arcjet Node.js SDK 文档。 。 。 .
快速注射检测
检测和阻止快速注射攻击——试图推翻你的AI
模型的指示——在他们到达你的模型之前. 传递用户消息
通过 detectPromptInjectionMessage 每个 protect() 电话.
import arcjet, { detectPromptInjection } from "@arcjet/node";
import { readBody } from "@arcjet/body";
import http from "node:http";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
detectPromptInjection({
mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only
}),
],
});
const server = http.createServer(async function (req, res) {
const body = await readBody(req);
const { message } = JSON.parse(body);
const decision = await aj.protect(req, {
detectPromptInjectionMessage: message,
});
if (decision.isDenied() && decision.reason.isPromptInjection()) {
res.writeHead(400, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
error: "Prompt injection detected — please rephrase your message",
}),
);
return;
}
// Forward to your AI model...
});
瓶装保护
Arcjet允许您配置一个 bots 列表以允许或拒绝 。 指定
allow 意味着所有其他的bots被否定。 一个空的允许列表块全部块 .
可用类别 : CATEGORY:ACADEMIC, (中文(简体) ), CATEGORY:ADVERTISING, (中文(简体) ),
CATEGORY:AI, (中文(简体) ), CATEGORY:AMAZON, (中文(简体) ), CATEGORY:APPLE, (中文(简体) ), CATEGORY:ARCHIVE, (中文(简体) ),
CATEGORY:BOTNET, (中文(简体) ), CATEGORY:FEEDFETCHER, (中文(简体) ), CATEGORY:GOOGLE, (中文(简体) ),
CATEGORY:META, (中文(简体) ), CATEGORY:MICROSOFT, (中文(简体) ), CATEGORY:MONITOR, (中文(简体) ),
CATEGORY:OPTIMIZER, (中文(简体) ), CATEGORY:PREVIEW, (中文(简体) ), CATEGORY:PROGRAMMATIC, (中文(简体) ),
CATEGORY:SEARCH_ENGINE, (中文(简体) ), CATEGORY:SLACK, (中文(简体) ), CATEGORY:SOCIAL, (中文(简体) ),
CATEGORY:TOOL, (中文(简体) ), CATEGORY:UNKNOWN, (中文(简体) ), CATEGORY:VERCEL, (中文(简体) ),
CATEGORY:WEBHOOK, (中文(简体) ), CATEGORY:YAHOO。也可以允许或拒绝
按名称排列的特定块。 。 。 .
import arcjet, { detectBot } from "@arcjet/node";
import { isSpoofedBot } from "@arcjet/inspect";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
detectBot({
mode: "LIVE",
allow: [
"CATEGORY:SEARCH_ENGINE",
// See the full list at https://arcjet.com/bot-list
],
}),
],
});
// In your request handler:
const decision = await aj.protect(req);
if (decision.isDenied() && decision.reason.isBot()) {
res.writeHead(403);
res.end(JSON.stringify({ error: "No bots allowed" }));
}
// Verifies the authenticity of common bots using IP data.
if (decision.results.some(isSpoofedBot)) {
res.writeHead(403);
res.end(JSON.stringify({ error: "Forbidden" }));
}
瓶类
波茨可以被配置为 类别 和(或) 具体 机器人名称。例如,允许搜索引擎和OpenAI 爬行者,但否认 所有其他bots:
detectBot({
mode: "LIVE",
allow: ["CATEGORY:SEARCH_ENGINE", "OPENAI_CRAWLER_SEARCH"],
});
已验证 vs spoofed bots
自称是知名爬行者(如:Googlebot)的Bots通过验证
对照已知的 IP 范围检查他们的 IP 地址 。 如果一个机器人无法核实,
被贴上"被骗"的标签 使用 isSpoofedBot 从 @arcjet/inspect 检查 :
import { isSpoofedBot } from "@arcjet/inspect";
if (decision.results.some(isSpoofedBot)) {
res.writeHead(403);
res.end(JSON.stringify({ error: "Forbidden" }));
}
限制费率
Arcjet支持符号桶,固定窗口和滑动窗口算法.
Token桶是控制AI符号预算的理想工具——设置 capacity 改为
用户可以花费的最大代币, refillRate 以还原多少个令牌
百分比 interval,并通过 requested 内 protect()。 。 。 .
这个 interval 接受字符串( r)"1s", (中文(简体) ), "1m", (中文(简体) ), "1h", (中文(简体) ), "1d")或秒为
一个数字。 使用 characteristics 以跟踪每个用户的限制,而不是每个IP.
import arcjet, { tokenBucket } from "@arcjet/node";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["userId"], // Track per user
rules: [
tokenBucket({
mode: "LIVE",
refillRate: 2_000, // Refill 2,000 tokens per hour
interval: "1h",
capacity: 5_000, // Maximum 5,000 tokens in the bucket
}),
],
});
const decision = await aj.protect(req, {
userId: "user-123",
requested: estimate, // Number of tokens to deduct
});
if (decision.isDenied() && decision.reason.isRateLimit()) {
res.writeHead(429);
res.end(JSON.stringify({ error: "Rate limit exceeded" }));
}
敏感信息检测
检测和封存请求中的 PII 内容
@arcjet/sensitive-info-rampart, (中文(简体) ),
在本地运行着Rampart命名实体识别模型,所以没有数据
离开你的环境。 通过扫描传送内容 sensitiveInfoValue 打开
每个 protect() 电话 Rampart侦测到姓名、地址、政府和
财务识别符、电子邮件地址、电话号码、IP地址和卡片
数字。 添加识别器以检测自定义模式 .
npm install @arcjet/sensitive-info-rampart
import arcjet, { sensitiveInfo } from "@arcjet/node";
import { rampart } from "@arcjet/sensitive-info-rampart";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
sensitiveInfo({
mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only
deny: ["CREDIT_CARD_NUMBER", "EMAIL", "PHONE_NUMBER"],
backend: rampart(),
}),
],
});
const decision = await aj.protect(req, {
sensitiveInfoValue: userMessage, // The text content to scan
});
if (decision.isDenied() && decision.reason.isSensitiveInfo()) {
res.writeHead(400);
res.end(JSON.stringify({ error: "Sensitive information detected" }));
}
盾牌 WAF
保护您的应用程序免受常见的网络攻击, 包括 OWASP 排行前10名.
import arcjet, { shield } from "@arcjet/node";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
shield({
mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only
}),
],
});
电子邮件验证
验证和验证电子邮件地址。 拒绝类型 : DISPOSABLE, (中文(简体) ), FREE, (中文(简体) ),
NO_MX_RECORDS, (中文(简体) ), NO_GRAVATAR, (中文(简体) ), INVALID。 。 。 .
import arcjet, { validateEmail } from "@arcjet/node";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
validateEmail({
mode: "LIVE",
deny: ["DISPOSABLE", "INVALID", "NO_MX_RECORDS"],
}),
],
});
const decision = await aj.protect(req, {
email: "[email protected]",
});
if (decision.isDenied() && decision.reason.isEmail()) {
res.writeHead(400);
res.end(JSON.stringify({ error: "Invalid email address" }));
}
请求过滤器
使用基于表达式的规则对请求属性过滤请求(IP, 页: 1.
import arcjet, { filter } from "@arcjet/node";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
filter({
mode: "LIVE",
deny: ['ip.src == "1.2.3.4"'],
}),
],
});
按国家分列的区块
限制进入特定国家——有助于发放许可证、遵守或
区域推广。 这个 allow 拒绝所有未列入名单的国家:
filter({
mode: "LIVE",
// Allow only US traffic — all other countries are denied
allow: ['ip.src.country == "US"'],
});
屏蔽 VPN 和代理流量
防止匿名交通进入敏感终点——对 预防欺诈、实施地理限制并减少滥用:
filter({
mode: "LIVE",
deny: [
"ip.src.vpn", // VPN services
"ip.src.proxy", // Open proxies
"ip.src.tor", // Tor exit nodes
],
});
对于更细致的处理,使用 decision.ip 呼叫后帮助 protect()数字 :
const decision = await aj.protect(req);
if (decision.ip.isVpn() || decision.ip.isTor()) {
res.writeHead(403);
res.end(JSON.stringify({ error: "VPN traffic not allowed" }));
}
见 请求过滤文件, (中文(简体) ), IP 地理定位蓝图,以及 VPN/Proxy检测蓝图 更多细节.
知识产权分析
Arcjet用IP元数据丰富了每个请求. 使用这些助手来制作 基于网络信号的政策决定:
const decision = await aj.protect(req);
if (decision.ip.isHosting()) {
// Requests from cloud/hosting providers are often automated.
// https://docs.arcjet.com/blueprints/vpn-proxy-detection
res.writeHead(403);
res.end(JSON.stringify({ error: "Forbidden" }));
}
if (decision.ip.isVpn() || decision.ip.isProxy() || decision.ip.isTor()) {
// Handle VPN/proxy traffic according to your policy
}
// Access geolocation and network details
console.log(decision.ip.country, decision.ip.city, decision.ip.asn);
自定义特性
跟踪和限制任何稳定的标识符的请求——用户ID,API密钥,会话, ——而不是仅IP地址.
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ["userId"], // Declare at the SDK level
rules: [
tokenBucket({
mode: "LIVE",
refillRate: 2_000,
interval: "1h",
capacity: 5_000,
}),
],
});
// Pass the characteristic value at request time
const decision = await aj.protect(req, {
userId: "user-123", // Replace with your actual user ID
requested: estimate,
});
最佳做法
见 Arcjet 最佳做法 详细指导。 密钥 建议:
创建单一客户端实例 并重新使用它与 withRule() 页:1
特定路线规则。 SDK 缓存决定和配置,因此创建
每一个请求的新实例 有效的废物.
// lib/arcjet.ts — create once, import everywhere
import arcjet, { shield } from "@arcjet/node";
export default arcjet({
key: process.env.ARCJET_KEY!,
rules: [
shield({ mode: "LIVE" }), // base rules applied to every request
],
});
// routes/chat.ts — extend per-route with withRule()
import aj from "./lib/arcjet.js";
import { detectBot, tokenBucket } from "@arcjet/node";
const routeAj = aj.withRule(detectBot({ mode: "LIVE", allow: [] })).withRule(
tokenBucket({
mode: "LIVE",
refillRate: 2_000,
interval: "1h",
capacity: 5_000,
}),
);
export async function handler(req, res) {
const decision = await routeAj.protect(req, { requested: 500 });
// ...
}
其他建议:
- 打电话
protect()每个请求一次 在处理器中 你需要它,不是 在全球中间软件层中. - 开始规则
DRY_RUN模式 在切换到前观察行为LIVE。这使得您可以调取阈值而不影响真实流量. - 配置代理 如果您的应用程序运行在负载平衡器或倒置代理服务器后
因此Arcjet解决了真正的客户端IP:
arcjet({ key: process.env.ARCJET_KEY!, rules: [], proxies: ["100.100.100.100"], }); - 明确处理错误 .
protect()永不扔出 — 在错误时返回 a 一个ERROR结果。 无法通过日志和允许请求打开 :if (decision.isErrored()) { console.error("Arcjet error", decision.reason.message); // allow the request to proceed }