@arcjet/nest
弧喷 是您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/nest- 设定
ARCJET_KEY=ajkey_yourkey在你的环境中 - 将 Arcjet 添加到您的应用程序中 快速开始 下级
npm 软件包 | GitHub 来源 | 完整文档 | 其他 SDKs 软件
特征
以下所有特征均可使用 @arcjet/nest 请求保护.
警卫保护(工具呼叫、MCP服务器、队列)见
@arcjet/guard。 。 。 .
| 特性 | @arcjet/nest | @arcjet/guard |
|---|---|---|
| 限制费率 | ✅ | ✅ |
| 快速注射检测 | ✅ | ✅ |
| 敏感信息检测 | ✅ | ✅ |
| 瓶装保护 | ✅ | —— 说 |
| 盾牌 WAF | ✅ | —— 说 |
| 电子邮件验证 | ✅ | —— 说 |
| 注册表保护 | ✅ | —— 说 |
| 请求过滤器 | ✅ | —— 说 |
| IP 分析 | ✅ | —— 说 |
| 自定义规则 | —— 说 | ✅ |
- 🔒 快速注射检测 - 探测和阻断 在到达你的LLM前立即注射.
- 🤖 瓶装保护 - 停止刮刮机, 证明性材料, 和AI爬行者滥用你的终点.
- 🛑 限制费率 - 标志桶、固定窗口和滑动 窗口算法; 每个用户的模型 AI 符号预算.
- 🕵️ 敏感信息检测 - 块 PII,信用卡和定制模式 从进入你的AI管道.
- 🛡️ 盾牌 WAF • 防止SQL注射、XSS和其他 常见的网络攻击.
- 📧 电子邮件验证 一次性、无效和 注册时无法提供地址 .
- 📝 注册表保护 结合机器人保护, 电子邮件验证, 以及限制您注册表格的速率 .
- 🎯 请求过滤器 ——IP,路径上以表达为主的规则, 标题和自定义字段.
- 🌐 IP 分析 地理定位、ASN、VPN、代理、Tor和托管 检测包括每个请求.
快开始
此示例保护 NestJS 应用程序, 并使用 bot 全局守护 探测器,盾牌WAF, 和象征性桶率限制.
首先,登记 ArcjetModule 在您的应用模块中 :
// app.module.ts
import { ArcjetModule, detectBot, shield, tokenBucket } from "@arcjet/nest";
import { Module } from "@nestjs/common";
@Module({
imports: [
ArcjetModule.forRoot({
isGlobal: true,
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",
refillRate: 5, // Refill 5 tokens per interval
interval: 10, // Refill every 10 seconds
capacity: 10, // Bucket capacity of 10 tokens
}),
],
}),
],
})
export class AppModule {}
然后使用 @InjectArcjet()数字 :
// app.controller.ts
import { ArcjetNest, InjectArcjet } from "@arcjet/nest";
import { isSpoofedBot } from "@arcjet/inspect";
import {
Controller,
Get,
HttpException,
HttpStatus,
Req,
} from "@nestjs/common";
import type { Request } from "express";
@Controller()
export class AppController {
constructor(@InjectArcjet() private readonly arcjet: ArcjetNest) {}
@Get("/")
async index(@Req() req: Request) {
const decision = await this.arcjet.protect(req, { requested: 5 });
console.log("Arcjet decision", decision);
if (decision.isDenied()) {
if (decision.reason.isRateLimit()) {
throw new HttpException(
"Too many requests",
HttpStatus.TOO_MANY_REQUESTS,
);
} else if (decision.reason.isBot()) {
throw new HttpException("No bots allowed", HttpStatus.FORBIDDEN);
} else {
throw new HttpException("Forbidden", HttpStatus.FORBIDDEN);
}
}
// Requests from hosting IPs are likely from bots.
// https://docs.arcjet.com/blueprints/vpn-proxy-detection
if (decision.ip.isHosting()) {
throw new HttpException("Forbidden", HttpStatus.FORBIDDEN);
}
// 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
if (decision.results.some(isSpoofedBot)) {
throw new HttpException("Forbidden", HttpStatus.FORBIDDEN);
}
return { message: "Hello world" };
}
}
全文见 Arcjet NestJS SDK 文档。 。 。 .
快速注射检测
检测和阻止快速注射攻击——试图推翻你的AI
模型的指示——在他们到达你的模型之前. 传递用户消息
通过 detectPromptInjectionMessage 每个 protect() 电话.
// app.module.ts
import { ArcjetModule, detectPromptInjection } from "@arcjet/nest";
import { Module } from "@nestjs/common";
@Module({
imports: [
ArcjetModule.forRoot({
isGlobal: true,
key: process.env.ARCJET_KEY!,
rules: [
detectPromptInjection({
mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only
}),
],
}),
],
})
export class AppModule {}
// chat.controller.ts
import { ArcjetNest, InjectArcjet } from "@arcjet/nest";
import {
Body,
Controller,
HttpException,
HttpStatus,
Post,
Req,
} from "@nestjs/common";
import type { Request } from "express";
@Controller("chat")
export class ChatController {
constructor(@InjectArcjet() private readonly arcjet: ArcjetNest) {}
@Post("/")
async chat(@Req() req: Request, @Body() body: { message: string }) {
const decision = await this.arcjet.protect(req, {
detectPromptInjectionMessage: body.message,
});
if (decision.isDenied() && decision.reason.isPromptInjection()) {
throw new HttpException(
"Prompt injection detected — please rephrase your message",
HttpStatus.BAD_REQUEST,
);
}
// 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 { ArcjetModule, detectBot } from "@arcjet/nest";
ArcjetModule.forRoot({
isGlobal: true,
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 controller:
import { isSpoofedBot } from "@arcjet/inspect";
const decision = await this.arcjet.protect(req);
if (decision.isDenied() && decision.reason.isBot()) {
throw new HttpException("No bots allowed", HttpStatus.FORBIDDEN);
}
// Verifies the authenticity of common bots using IP data.
if (decision.results.some(isSpoofedBot)) {
throw new HttpException("Forbidden", HttpStatus.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)) {
throw new HttpException("Forbidden", HttpStatus.FORBIDDEN);
}
限制费率
Arcjet支持符号桶,固定窗口和滑动窗口算法.
Token桶是控制AI符号预算的理想工具——设置 capacity 改为
用户可以花费的最大代币, refillRate 以还原多少个令牌
百分比 interval,并通过 requested 内 protect()。 。 。 .
这个 interval 接受字符串( r)"1s", (中文(简体) ), "1m", (中文(简体) ), "1h", (中文(简体) ), "1d")或秒为
一个数字。 使用 characteristics 以跟踪每个用户的限制,而不是每个IP.
import {
ArcjetModule,
tokenBucket,
slidingWindow,
fixedWindow,
} from "@arcjet/nest";
ArcjetModule.forRoot({
isGlobal: true,
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
}),
],
});
// In your controller:
const decision = await this.arcjet.protect(req, {
userId: "user-123",
requested: estimate, // Number of tokens to deduct
});
if (decision.isDenied() && decision.reason.isRateLimit()) {
throw new HttpException("Rate limit exceeded", HttpStatus.TOO_MANY_REQUESTS);
}
敏感信息检测
检测和封存请求中的 PII 内容
@arcjet/sensitive-info-rampart, (中文(简体) ),
在本地运行着Rampart命名实体识别模型,所以没有数据
离开你的环境。 通过扫描传送内容 sensitiveInfoValue 打开
每个 protect() 电话 Rampart侦测到姓名、地址、政府和
财务识别符、电子邮件地址、电话号码、IP地址和卡片
数字。 添加识别器以检测自定义模式 .
npm install @arcjet/sensitive-info-rampart
import { ArcjetModule, sensitiveInfo } from "@arcjet/nest";
import { rampart } from "@arcjet/sensitive-info-rampart";
ArcjetModule.forRoot({
isGlobal: true,
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(),
}),
],
});
// In your controller:
const decision = await this.arcjet.protect(req, {
sensitiveInfoValue: userMessage, // The text content to scan
});
if (decision.isDenied() && decision.reason.isSensitiveInfo()) {
throw new HttpException(
"Sensitive information detected",
HttpStatus.BAD_REQUEST,
);
}
Rampart在Node.js、Bun和Deno上运行,并装入它的型号
node_modules 在运行时间,所以不要在您的服务器捆绑。 见
Bundlers和框架。 。 。 .
盾牌 WAF
保护您的应用程序免受常见的网络攻击, 包括 OWASP 排行前10名.
import { ArcjetModule, shield } from "@arcjet/nest";
ArcjetModule.forRoot({
isGlobal: true,
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 { ArcjetModule, validateEmail } from "@arcjet/nest";
ArcjetModule.forRoot({
isGlobal: true,
key: process.env.ARCJET_KEY!,
rules: [
validateEmail({
mode: "LIVE",
deny: ["DISPOSABLE", "INVALID", "NO_MX_RECORDS"],
}),
],
});
// In your controller:
const decision = await this.arcjet.protect(req, {
email: "[email protected]",
});
if (decision.isDenied() && decision.reason.isEmail()) {
throw new HttpException("Invalid email address", HttpStatus.BAD_REQUEST);
}
请求过滤器
使用基于表达式的规则对请求属性过滤请求(IP, 页: 1.
import { ArcjetModule, filter } from "@arcjet/nest";
ArcjetModule.forRoot({
isGlobal: true,
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 this.arcjet.protect(req);
if (decision.ip.isVpn() || decision.ip.isTor()) {
throw new HttpException("VPN traffic not allowed", HttpStatus.FORBIDDEN);
}
见 请求过滤文件, (中文(简体) ), IP 地理定位蓝图,以及 VPN/Proxy检测蓝图 更多细节.
知识产权分析
Arcjet用IP元数据丰富了每个请求. 使用这些助手来制作 基于网络信号的政策决定:
const decision = await this.arcjet.protect(req);
if (decision.ip.isHosting()) {
// Requests from cloud/hosting providers are often automated.
// https://docs.arcjet.com/blueprints/vpn-proxy-detection
throw new HttpException("Forbidden", HttpStatus.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地址.
ArcjetModule.forRoot({
isGlobal: true,
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 this.arcjet.protect(req, {
userId: "user-123", // Replace with your actual user ID
requested: estimate,
});
最佳做法
见 Arcjet 最佳做法 详细指导。 密钥 建议:
使用 withRule() 用于控制器特定规则 在全球基础上
规则。 SDK 缓存决定和配置, 这样效率更高
而不是创建每个请求的新实例.
// chat.controller.ts — extend per-route with withRule()
import { ArcjetNest, InjectArcjet, detectBot, tokenBucket } from "@arcjet/nest";
import { Controller, Post, Req } from "@nestjs/common";
import type { Request } from "express";
@Controller("chat")
export class ChatController {
constructor(@InjectArcjet() private readonly arcjet: ArcjetNest) {}
@Post("/")
async chat(@Req() req: Request, @Body() body: { requested: number }) {
const routeAj = this.arcjet
.withRule(detectBot({ mode: "LIVE", allow: [] }))
.withRule(
tokenBucket({
mode: "LIVE",
refillRate: 2_000,
interval: "1h",
capacity: 5_000,
}),
);
const decision = await routeAj.protect(req, { requested: body.requested });
// ...
}
}
其他建议:
- 开始规则
DRY_RUN模式 在切换到前观察行为LIVE。这使得您可以调取阈值而不影响真实流量. - 配置代理 如果您的应用程序运行在负载平衡器或倒置代理服务器后
因此Arcjet解决了真正的客户端IP:
ArcjetModule.forRoot({ 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 }