@kya-os/agentshield-nextjs 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -0
- package/dist/api-client.d.mts +6 -10
- package/dist/api-client.d.ts +6 -10
- package/dist/api-client.js.map +1 -1
- package/dist/api-client.mjs.map +1 -1
- package/dist/api-middleware.d.mts +1 -0
- package/dist/api-middleware.d.ts +1 -0
- package/dist/api-middleware.js.map +1 -1
- package/dist/api-middleware.mjs.map +1 -1
- package/dist/edge/index.js +1 -0
- package/dist/edge/index.js.map +1 -1
- package/dist/edge/index.mjs +1 -0
- package/dist/edge/index.mjs.map +1 -1
- package/dist/edge-runtime-loader.js +1 -0
- package/dist/edge-runtime-loader.js.map +1 -1
- package/dist/edge-runtime-loader.mjs +1 -0
- package/dist/edge-runtime-loader.mjs.map +1 -1
- package/dist/enhanced-middleware.js +1 -0
- package/dist/enhanced-middleware.js.map +1 -1
- package/dist/enhanced-middleware.mjs +1 -0
- package/dist/enhanced-middleware.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/edge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils.ts","../../src/edge/index.ts"],"names":["NextResponse","evaluateEnforcement","response"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Middleware with WASM Support\n *\n * This module provides Next.js middleware that uses the unified WASM runtime.\n * For Edge Runtime, consumers must provide a pre-compiled WASM module via static import:\n *\n * ```typescript\n * // In your middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * apiKey: process.env.AGENTSHIELD_API_KEY,\n * onAgentDetected: 'block',\n * });\n * ```\n *\n * When an API key is provided, the middleware will:\n * 1. Load customer policies (deny lists, allow lists, thresholds) from AgentShield API\n * 2. Automatically block agents that match deny list entries\n * 3. Cache policies for 5 minutes with background refresh\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport type { DetectionResult } from '@kya-os/agentshield-shared';\nimport { evaluateEnforcement } from '@kya-os/agentshield-shared';\nimport { getClientIp } from '../utils';\n\n/**\n * Edge middleware configuration\n */\nexport interface EdgeMiddlewareConfig {\n /**\n * Pre-compiled WebAssembly.Module for Edge Runtime\n * Use static import: `import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module'`\n */\n wasmModule?: WebAssembly.Module;\n\n /**\n * API key for loading customer policies from AgentShield dashboard\n * When provided, enables policy enforcement (deny lists, allow lists, thresholds)\n */\n apiKey?: string;\n\n /**\n * Custom URL for the policy API\n * @default 'https://api.agentshield.io'\n */\n policyApiUrl?: string;\n\n /**\n * Action to take when an agent is detected\n * @default 'log'\n */\n onAgentDetected?: 'block' | 'redirect' | 'rewrite' | 'log' | 'allow';\n\n /**\n * Custom handler called when an agent is detected\n * Return a NextResponse to override default behavior\n */\n onDetection?: (\n request: NextRequest,\n result: DetectionResult\n ) => Promise<NextResponse | void> | NextResponse | void;\n\n /**\n * Paths to skip detection (can be string prefixes or RegExp)\n */\n skipPaths?: (string | RegExp)[];\n\n /**\n * Minimum confidence threshold (0-100 scale) for considering a request as agent traffic\n * @default 70\n */\n confidenceThreshold?: number;\n\n /**\n * Response to send when blocking agents\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * URL to redirect to when redirecting agents\n */\n redirectUrl?: string;\n\n /**\n * URL to rewrite to when rewriting agent requests\n */\n rewriteUrl?: string;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n/**\n * Detection input extracted from request\n */\ninterface DetectionInput {\n userAgent?: string;\n ipAddress?: string;\n headers: Record<string, string>;\n url?: string;\n method?: string;\n}\n\n/**\n * Simple edge-safe detector that uses pattern matching\n * Falls back to this when WASM is not available\n */\nasync function patternDetect(input: DetectionInput): Promise<DetectionResult> {\n const userAgent = input.userAgent?.toLowerCase() || '';\n const reasons: string[] = [];\n let confidence = 0;\n let detectedAgent: { type: string; name: string } | undefined;\n\n // AI agent patterns with confidence scores (0-100 scale)\n const patterns = [\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-?bot/i, name: 'ClaudeBot', confidence: 95 },\n { pattern: /anthropic/i, name: 'Claude', confidence: 90 },\n { pattern: /gptbot/i, name: 'GPTBot', confidence: 90 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 90 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 85 },\n { pattern: /copilot/i, name: 'Copilot', confidence: 85 },\n { pattern: /gemini/i, name: 'Gemini', confidence: 85 },\n { pattern: /bard/i, name: 'Bard', confidence: 85 },\n // HTTP client libraries (often used by AI agents/scrapers)\n { pattern: /^axios\\//i, name: 'HTTP Client (axios)', confidence: 75 },\n { pattern: /^node-fetch\\//i, name: 'HTTP Client (node-fetch)', confidence: 75 },\n { pattern: /^got\\//i, name: 'HTTP Client (got)', confidence: 75 },\n { pattern: /^python-requests\\//i, name: 'HTTP Client (requests)', confidence: 75 },\n { pattern: /^python-urllib/i, name: 'HTTP Client (urllib)', confidence: 75 },\n { pattern: /^curl\\//i, name: 'HTTP Client (curl)', confidence: 60 },\n { pattern: /^wget\\//i, name: 'HTTP Client (wget)', confidence: 60 },\n { pattern: /^httpie\\//i, name: 'HTTP Client (httpie)', confidence: 70 },\n { pattern: /^undici\\//i, name: 'HTTP Client (undici)', confidence: 75 },\n ];\n\n for (const { pattern, name, confidence: patternConfidence } of patterns) {\n if (pattern.test(userAgent)) {\n confidence = patternConfidence;\n detectedAgent = { type: name.toLowerCase(), name };\n reasons.push(`known_pattern:${name.toLowerCase()}`);\n break;\n }\n }\n\n // Check for AI-specific headers\n const aiHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'signature-agent'];\n for (const [key] of Object.entries(input.headers)) {\n if (aiHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n confidence = Math.max(confidence, 45);\n reasons.push(`ai_headers:${key}`);\n break;\n }\n }\n\n return {\n isAgent: confidence > 30,\n confidence,\n detectionClass:\n confidence > 30 && detectedAgent\n ? { type: 'AiAgent' as const, agentType: detectedAgent.name }\n : confidence > 30\n ? { type: 'Unknown' as const }\n : { type: 'Human' as const },\n signals: [],\n ...(detectedAgent && { detectedAgent }),\n reasons,\n verificationMethod: 'pattern' as const,\n forgeabilityRisk: confidence > 80 ? 'medium' : 'high',\n timestamp: new Date(),\n };\n}\n\n/**\n * Extended detection result with policy enforcement\n */\ninterface PolicyEnforcedResult extends DetectionResult {\n shouldBlock?: boolean;\n blockReason?: 'deny_list' | 'not_in_allow_list' | 'threshold';\n}\n\n/**\n * Create detector using WASM runtime or fallback\n * When apiKey is provided, policy enforcement is enabled\n */\nasync function createDetector(config: EdgeMiddlewareConfig) {\n let detector: {\n detect: (input: DetectionInput) => Promise<PolicyEnforcedResult>;\n isReady: () => boolean;\n };\n\n // Try to use wasm-runtime if WASM module is provided\n if (config.wasmModule) {\n try {\n const { StaticWasmLoader, WasmDetector, PolicyLoader } = await import(\n '@kya-os/agentshield-wasm-runtime/edge'\n );\n const loader = new StaticWasmLoader(config.wasmModule);\n\n // Create policy loader if API key is provided\n const policyLoader = config.apiKey\n ? new PolicyLoader({\n apiUrl: config.policyApiUrl,\n })\n : undefined;\n\n // Create detector with policy support\n const wasmDetector = new WasmDetector(loader, policyLoader, {\n apiKey: config.apiKey,\n debug: config.debug,\n });\n\n await wasmDetector.ensureReady();\n\n if (config.debug) {\n console.debug('[AgentShield] WASM detector initialized in Edge Runtime', {\n policyEnabled: !!config.apiKey,\n });\n }\n\n detector = {\n detect: async (input: DetectionInput): Promise<PolicyEnforcedResult> => {\n const result = await wasmDetector.detect(input);\n // Convert IDetectionResult to DetectionResult by adding required fields\n // Type assertion needed due to different DetectionClass definitions\n return {\n isAgent: result.isAgent,\n isAiCrawler: (result as unknown as Record<string, unknown>).isAiCrawler as\n | boolean\n | undefined,\n confidence: result.confidence,\n detectionClass: result.detectionClass as DetectionResult['detectionClass'],\n detectedAgent: result.detectedAgent,\n verificationMethod: result.verificationMethod,\n forgeabilityRisk: result.forgeabilityRisk,\n reasons: result.reasons,\n timestamp: result.timestamp,\n signals: [], // Required by DetectionResult, empty for WASM results\n shouldBlock: result.shouldBlock,\n blockReason: result.blockReason as PolicyEnforcedResult['blockReason'],\n };\n },\n isReady: () => wasmDetector.isReady(),\n };\n } catch (error) {\n if (config.debug) {\n console.warn('[AgentShield] WASM runtime not available, using pattern detection:', error);\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n } else {\n // Use pattern-based detection\n if (config.debug) {\n console.debug('[AgentShield] No WASM module provided, using pattern detection');\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n\n return detector;\n}\n\n/**\n * Create Edge middleware with WASM support\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * onAgentDetected: 'block',\n * confidenceThreshold: 70,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function createEdgeMiddleware(config: EdgeMiddlewareConfig = {}) {\n let detectorPromise: Promise<Awaited<ReturnType<typeof createDetector>>> | null = null;\n\n const {\n onAgentDetected = 'log',\n onDetection,\n skipPaths = [],\n confidenceThreshold = 70,\n blockedResponse = {\n status: 403,\n message: 'Access denied: Automated agent detected',\n headers: { 'Content-Type': 'application/json' },\n },\n redirectUrl = '/blocked',\n rewriteUrl = '/blocked',\n debug = false,\n } = config;\n\n return async (request: NextRequest): Promise<NextResponse> => {\n try {\n // Initialize detector lazily\n if (!detectorPromise) {\n detectorPromise = createDetector({ ...config, debug });\n }\n const detector = await detectorPromise;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => {\n if (typeof pattern === 'string') {\n return request.nextUrl.pathname.startsWith(pattern);\n }\n return pattern.test(request.nextUrl.pathname);\n });\n\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n // Extract request context\n const url = new URL(request.url);\n const input: DetectionInput = {\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress: getClientIp(request),\n headers: Object.fromEntries(request.headers.entries()),\n url: url.pathname + url.search,\n method: request.method,\n };\n\n // Run detection\n const result = await detector.detect(input);\n\n // POLICY ENFORCEMENT: Check shouldBlock from policy rules (deny list, allow list, threshold)\n // This takes precedence over the general threshold check below\n if (result.shouldBlock) {\n if (debug) {\n console.debug('[AgentShield] Blocked by policy', {\n reason: result.blockReason,\n agent: result.detectedAgent?.name,\n confidence: result.confidence,\n pathname: request.nextUrl.pathname,\n });\n }\n\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return 403 with policy block reason\n return NextResponse.json(\n {\n error: 'Access denied by policy',\n reason: result.blockReason,\n detected: true,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n timestamp: result.timestamp,\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n // Check if agent detected above threshold (when policy doesn't block)\n // Skip if shouldBlock === false (agent explicitly allowed by policy)\n if (result.shouldBlock !== false) {\n const decision = evaluateEnforcement(result, {\n confidenceThreshold,\n defaultAction: onAgentDetected,\n });\n\n if (decision.shouldNotify) {\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Handle based on decision action\n switch (decision.action) {\n case 'block': {\n const response = NextResponse.json(\n {\n error: blockedResponse.message,\n detected: true,\n confidence: result.confidence,\n timestamp: result.timestamp,\n },\n { status: blockedResponse.status }\n );\n\n if (blockedResponse.headers) {\n Object.entries(blockedResponse.headers).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n }\n\n return response;\n }\n\n case 'redirect':\n return NextResponse.redirect(new URL(redirectUrl, request.url));\n\n case 'rewrite':\n return NextResponse.rewrite(new URL(rewriteUrl, request.url));\n\n case 'log':\n if (debug || process.env.NODE_ENV !== 'production') {\n console.debug('AgentShield: Agent detected', {\n ipAddress: input.ipAddress,\n userAgent: input.userAgent,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n pathname: request.nextUrl.pathname,\n });\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n // Continue with request\n const response = NextResponse.next();\n\n // Add detection headers\n response.headers.set('kya-detected', result.isAgent.toString());\n response.headers.set('kya-confidence', result.confidence.toString());\n if (result.detectedAgent?.name) {\n response.headers.set('kya-agent', result.detectedAgent.name);\n }\n\n return response;\n } catch (error) {\n console.error('AgentShield middleware error:', error);\n return NextResponse.next();\n }\n };\n}\n\n// Re-export types for convenience\nexport type { DetectionResult };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts","../../src/edge/index.ts"],"names":["NextResponse","evaluateEnforcement","response"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Middleware with WASM Support\n *\n * This module provides Next.js middleware that uses the unified WASM runtime.\n * For Edge Runtime, consumers must provide a pre-compiled WASM module via static import:\n *\n * ```typescript\n * // In your middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * apiKey: process.env.AGENTSHIELD_API_KEY,\n * onAgentDetected: 'block',\n * });\n * ```\n *\n * When an API key is provided, the middleware will:\n * 1. Load customer policies (deny lists, allow lists, thresholds) from AgentShield API\n * 2. Automatically block agents that match deny list entries\n * 3. Cache policies for 5 minutes with background refresh\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport type { DetectionResult } from '@kya-os/agentshield-shared';\nimport { evaluateEnforcement } from '@kya-os/agentshield-shared';\nimport { getClientIp } from '../utils';\n\n/**\n * Edge middleware configuration\n */\nexport interface EdgeMiddlewareConfig {\n /**\n * Pre-compiled WebAssembly.Module for Edge Runtime\n * Use static import: `import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module'`\n */\n wasmModule?: WebAssembly.Module;\n\n /**\n * API key for loading customer policies from AgentShield dashboard\n * When provided, enables policy enforcement (deny lists, allow lists, thresholds)\n */\n apiKey?: string;\n\n /**\n * Custom URL for the policy API\n * @default 'https://api.agentshield.io'\n */\n policyApiUrl?: string;\n\n /**\n * Action to take when an agent is detected\n * @default 'log'\n */\n onAgentDetected?: 'block' | 'redirect' | 'rewrite' | 'log' | 'allow';\n\n /**\n * Custom handler called when an agent is detected\n * Return a NextResponse to override default behavior\n */\n onDetection?: (\n request: NextRequest,\n result: DetectionResult\n ) => Promise<NextResponse | void> | NextResponse | void;\n\n /**\n * Paths to skip detection (can be string prefixes or RegExp)\n */\n skipPaths?: (string | RegExp)[];\n\n /**\n * Minimum confidence threshold (0-100 scale) for considering a request as agent traffic\n * @default 70\n */\n confidenceThreshold?: number;\n\n /**\n * Response to send when blocking agents\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * URL to redirect to when redirecting agents\n */\n redirectUrl?: string;\n\n /**\n * URL to rewrite to when rewriting agent requests\n */\n rewriteUrl?: string;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n/**\n * Detection input extracted from request\n */\ninterface DetectionInput {\n userAgent?: string;\n ipAddress?: string;\n headers: Record<string, string>;\n url?: string;\n method?: string;\n}\n\n/**\n * Simple edge-safe detector that uses pattern matching\n * Falls back to this when WASM is not available\n */\nasync function patternDetect(input: DetectionInput): Promise<DetectionResult> {\n const userAgent = input.userAgent?.toLowerCase() || '';\n const reasons: string[] = [];\n let confidence = 0;\n let detectedAgent: { type: string; name: string } | undefined;\n\n // AI agent patterns with confidence scores (0-100 scale)\n const patterns = [\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-user/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-?bot/i, name: 'ClaudeBot', confidence: 95 },\n { pattern: /anthropic/i, name: 'Claude', confidence: 90 },\n { pattern: /gptbot/i, name: 'GPTBot', confidence: 90 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 90 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 85 },\n { pattern: /copilot/i, name: 'Copilot', confidence: 85 },\n { pattern: /gemini/i, name: 'Gemini', confidence: 85 },\n { pattern: /bard/i, name: 'Bard', confidence: 85 },\n // HTTP client libraries (often used by AI agents/scrapers)\n { pattern: /^axios\\//i, name: 'HTTP Client (axios)', confidence: 75 },\n { pattern: /^node-fetch\\//i, name: 'HTTP Client (node-fetch)', confidence: 75 },\n { pattern: /^got\\//i, name: 'HTTP Client (got)', confidence: 75 },\n { pattern: /^python-requests\\//i, name: 'HTTP Client (requests)', confidence: 75 },\n { pattern: /^python-urllib/i, name: 'HTTP Client (urllib)', confidence: 75 },\n { pattern: /^curl\\//i, name: 'HTTP Client (curl)', confidence: 60 },\n { pattern: /^wget\\//i, name: 'HTTP Client (wget)', confidence: 60 },\n { pattern: /^httpie\\//i, name: 'HTTP Client (httpie)', confidence: 70 },\n { pattern: /^undici\\//i, name: 'HTTP Client (undici)', confidence: 75 },\n ];\n\n for (const { pattern, name, confidence: patternConfidence } of patterns) {\n if (pattern.test(userAgent)) {\n confidence = patternConfidence;\n detectedAgent = { type: name.toLowerCase(), name };\n reasons.push(`known_pattern:${name.toLowerCase()}`);\n break;\n }\n }\n\n // Check for AI-specific headers\n const aiHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'signature-agent'];\n for (const [key] of Object.entries(input.headers)) {\n if (aiHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n confidence = Math.max(confidence, 45);\n reasons.push(`ai_headers:${key}`);\n break;\n }\n }\n\n return {\n isAgent: confidence > 30,\n confidence,\n detectionClass:\n confidence > 30 && detectedAgent\n ? { type: 'AiAgent' as const, agentType: detectedAgent.name }\n : confidence > 30\n ? { type: 'Unknown' as const }\n : { type: 'Human' as const },\n signals: [],\n ...(detectedAgent && { detectedAgent }),\n reasons,\n verificationMethod: 'pattern' as const,\n forgeabilityRisk: confidence > 80 ? 'medium' : 'high',\n timestamp: new Date(),\n };\n}\n\n/**\n * Extended detection result with policy enforcement\n */\ninterface PolicyEnforcedResult extends DetectionResult {\n shouldBlock?: boolean;\n blockReason?: 'deny_list' | 'not_in_allow_list' | 'threshold';\n}\n\n/**\n * Create detector using WASM runtime or fallback\n * When apiKey is provided, policy enforcement is enabled\n */\nasync function createDetector(config: EdgeMiddlewareConfig) {\n let detector: {\n detect: (input: DetectionInput) => Promise<PolicyEnforcedResult>;\n isReady: () => boolean;\n };\n\n // Try to use wasm-runtime if WASM module is provided\n if (config.wasmModule) {\n try {\n const { StaticWasmLoader, WasmDetector, PolicyLoader } = await import(\n '@kya-os/agentshield-wasm-runtime/edge'\n );\n const loader = new StaticWasmLoader(config.wasmModule);\n\n // Create policy loader if API key is provided\n const policyLoader = config.apiKey\n ? new PolicyLoader({\n apiUrl: config.policyApiUrl,\n })\n : undefined;\n\n // Create detector with policy support\n const wasmDetector = new WasmDetector(loader, policyLoader, {\n apiKey: config.apiKey,\n debug: config.debug,\n });\n\n await wasmDetector.ensureReady();\n\n if (config.debug) {\n console.debug('[AgentShield] WASM detector initialized in Edge Runtime', {\n policyEnabled: !!config.apiKey,\n });\n }\n\n detector = {\n detect: async (input: DetectionInput): Promise<PolicyEnforcedResult> => {\n const result = await wasmDetector.detect(input);\n // Convert IDetectionResult to DetectionResult by adding required fields\n // Type assertion needed due to different DetectionClass definitions\n return {\n isAgent: result.isAgent,\n isAiCrawler: (result as unknown as Record<string, unknown>).isAiCrawler as\n | boolean\n | undefined,\n confidence: result.confidence,\n detectionClass: result.detectionClass as DetectionResult['detectionClass'],\n detectedAgent: result.detectedAgent,\n verificationMethod: result.verificationMethod,\n forgeabilityRisk: result.forgeabilityRisk,\n reasons: result.reasons,\n timestamp: result.timestamp,\n signals: [], // Required by DetectionResult, empty for WASM results\n shouldBlock: result.shouldBlock,\n blockReason: result.blockReason as PolicyEnforcedResult['blockReason'],\n };\n },\n isReady: () => wasmDetector.isReady(),\n };\n } catch (error) {\n if (config.debug) {\n console.warn('[AgentShield] WASM runtime not available, using pattern detection:', error);\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n } else {\n // Use pattern-based detection\n if (config.debug) {\n console.debug('[AgentShield] No WASM module provided, using pattern detection');\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n\n return detector;\n}\n\n/**\n * Create Edge middleware with WASM support\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * onAgentDetected: 'block',\n * confidenceThreshold: 70,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function createEdgeMiddleware(config: EdgeMiddlewareConfig = {}) {\n let detectorPromise: Promise<Awaited<ReturnType<typeof createDetector>>> | null = null;\n\n const {\n onAgentDetected = 'log',\n onDetection,\n skipPaths = [],\n confidenceThreshold = 70,\n blockedResponse = {\n status: 403,\n message: 'Access denied: Automated agent detected',\n headers: { 'Content-Type': 'application/json' },\n },\n redirectUrl = '/blocked',\n rewriteUrl = '/blocked',\n debug = false,\n } = config;\n\n return async (request: NextRequest): Promise<NextResponse> => {\n try {\n // Initialize detector lazily\n if (!detectorPromise) {\n detectorPromise = createDetector({ ...config, debug });\n }\n const detector = await detectorPromise;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => {\n if (typeof pattern === 'string') {\n return request.nextUrl.pathname.startsWith(pattern);\n }\n return pattern.test(request.nextUrl.pathname);\n });\n\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n // Extract request context\n const url = new URL(request.url);\n const input: DetectionInput = {\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress: getClientIp(request),\n headers: Object.fromEntries(request.headers.entries()),\n url: url.pathname + url.search,\n method: request.method,\n };\n\n // Run detection\n const result = await detector.detect(input);\n\n // POLICY ENFORCEMENT: Check shouldBlock from policy rules (deny list, allow list, threshold)\n // This takes precedence over the general threshold check below\n if (result.shouldBlock) {\n if (debug) {\n console.debug('[AgentShield] Blocked by policy', {\n reason: result.blockReason,\n agent: result.detectedAgent?.name,\n confidence: result.confidence,\n pathname: request.nextUrl.pathname,\n });\n }\n\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return 403 with policy block reason\n return NextResponse.json(\n {\n error: 'Access denied by policy',\n reason: result.blockReason,\n detected: true,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n timestamp: result.timestamp,\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n // Check if agent detected above threshold (when policy doesn't block)\n // Skip if shouldBlock === false (agent explicitly allowed by policy)\n if (result.shouldBlock !== false) {\n const decision = evaluateEnforcement(result, {\n confidenceThreshold,\n defaultAction: onAgentDetected,\n });\n\n if (decision.shouldNotify) {\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Handle based on decision action\n switch (decision.action) {\n case 'block': {\n const response = NextResponse.json(\n {\n error: blockedResponse.message,\n detected: true,\n confidence: result.confidence,\n timestamp: result.timestamp,\n },\n { status: blockedResponse.status }\n );\n\n if (blockedResponse.headers) {\n Object.entries(blockedResponse.headers).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n }\n\n return response;\n }\n\n case 'redirect':\n return NextResponse.redirect(new URL(redirectUrl, request.url));\n\n case 'rewrite':\n return NextResponse.rewrite(new URL(rewriteUrl, request.url));\n\n case 'log':\n if (debug || process.env.NODE_ENV !== 'production') {\n console.debug('AgentShield: Agent detected', {\n ipAddress: input.ipAddress,\n userAgent: input.userAgent,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n pathname: request.nextUrl.pathname,\n });\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n // Continue with request\n const response = NextResponse.next();\n\n // Add detection headers\n response.headers.set('kya-detected', result.isAgent.toString());\n response.headers.set('kya-confidence', result.confidence.toString());\n if (result.detectedAgent?.name) {\n response.headers.set('kya-agent', result.detectedAgent.name);\n }\n\n return response;\n } catch (error) {\n console.error('AgentShield middleware error:', error);\n return NextResponse.next();\n }\n };\n}\n\n// Re-export types for convenience\nexport type { DetectionResult };\n"]}
|
package/dist/edge/index.mjs
CHANGED
|
@@ -28,6 +28,7 @@ async function patternDetect(input) {
|
|
|
28
28
|
const patterns = [
|
|
29
29
|
{ pattern: /chatgpt-user/i, name: "ChatGPT", confidence: 95 },
|
|
30
30
|
{ pattern: /claude-web/i, name: "Claude", confidence: 95 },
|
|
31
|
+
{ pattern: /claude-user/i, name: "Claude", confidence: 95 },
|
|
31
32
|
{ pattern: /claude-?bot/i, name: "ClaudeBot", confidence: 95 },
|
|
32
33
|
{ pattern: /anthropic/i, name: "Claude", confidence: 90 },
|
|
33
34
|
{ pattern: /gptbot/i, name: "GPTBot", confidence: 90 },
|
package/dist/edge/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils.ts","../../src/edge/index.ts"],"names":["response"],"mappings":";;;;;;AAcO,SAAS,YAAY,OAAA,EAA0C;AAEpE,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AAC1D,EAAA,IAAI,YAAA,EAAc;AAEhB,IAAA,MAAM,KAAK,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,GAAG,IAAA,EAAK;AAC5C,IAAA,IAAI,IAAI,OAAO,EAAA;AAAA,EACjB;AAGA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA;AAC9C,EAAA,IAAI,QAAQ,OAAO,MAAA;AAGnB,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA;AACnD,EAAA,IAAI,MAAM,OAAO,IAAA;AAGjB,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AAClD,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,OAAO,MAAA;AACT;;;ACiFA,eAAe,cAAc,KAAA,EAAiD;AAC5E,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,SAAA,EAAW,WAAA,EAAY,IAAK,EAAA;AACpD,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,aAAA;AAGJ,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,EAAE,OAAA,EAAS,eAAA,EAAiB,IAAA,EAAM,SAAA,EAAW,YAAY,EAAA,EAAG;AAAA,IAC5D,EAAE,OAAA,EAAS,aAAA,EAAe,IAAA,EAAM,QAAA,EAAU,YAAY,EAAA,EAAG;AAAA,IACzD,EAAE,OAAA,EAAS,cAAA,EAAgB,IAAA,EAAM,WAAA,EAAa,YAAY,EAAA,EAAG;AAAA,IAC7D,EAAE,OAAA,EAAS,YAAA,EAAc,IAAA,EAAM,QAAA,EAAU,YAAY,EAAA,EAAG;AAAA,IACxD,EAAE,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,QAAA,EAAU,YAAY,EAAA,EAAG;AAAA,IACrD,EAAE,OAAA,EAAS,aAAA,EAAe,IAAA,EAAM,YAAA,EAAc,YAAY,EAAA,EAAG;AAAA,IAC7D,EAAE,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,QAAA,EAAU,YAAY,EAAA,EAAG;AAAA,IACrD,EAAE,OAAA,EAAS,UAAA,EAAY,IAAA,EAAM,SAAA,EAAW,YAAY,EAAA,EAAG;AAAA,IACvD,EAAE,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,QAAA,EAAU,YAAY,EAAA,EAAG;AAAA,IACrD,EAAE,OAAA,EAAS,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,YAAY,EAAA,EAAG;AAAA;AAAA,IAEjD,EAAE,OAAA,EAAS,WAAA,EAAa,IAAA,EAAM,qBAAA,EAAuB,YAAY,EAAA,EAAG;AAAA,IACpE,EAAE,OAAA,EAAS,gBAAA,EAAkB,IAAA,EAAM,0BAAA,EAA4B,YAAY,EAAA,EAAG;AAAA,IAC9E,EAAE,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,mBAAA,EAAqB,YAAY,EAAA,EAAG;AAAA,IAChE,EAAE,OAAA,EAAS,qBAAA,EAAuB,IAAA,EAAM,wBAAA,EAA0B,YAAY,EAAA,EAAG;AAAA,IACjF,EAAE,OAAA,EAAS,iBAAA,EAAmB,IAAA,EAAM,sBAAA,EAAwB,YAAY,EAAA,EAAG;AAAA,IAC3E,EAAE,OAAA,EAAS,UAAA,EAAY,IAAA,EAAM,oBAAA,EAAsB,YAAY,EAAA,EAAG;AAAA,IAClE,EAAE,OAAA,EAAS,UAAA,EAAY,IAAA,EAAM,oBAAA,EAAsB,YAAY,EAAA,EAAG;AAAA,IAClE,EAAE,OAAA,EAAS,YAAA,EAAc,IAAA,EAAM,sBAAA,EAAwB,YAAY,EAAA,EAAG;AAAA,IACtE,EAAE,OAAA,EAAS,YAAA,EAAc,IAAA,EAAM,sBAAA,EAAwB,YAAY,EAAA;AAAG,GACxE;AAEA,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,IAAA,EAAM,UAAA,EAAY,iBAAA,MAAuB,QAAA,EAAU;AACvE,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA,EAAG;AAC3B,MAAA,UAAA,GAAa,iBAAA;AACb,MAAA,aAAA,GAAgB,EAAE,IAAA,EAAM,IAAA,CAAK,WAAA,IAAe,IAAA,EAAK;AACjD,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,cAAA,EAAiB,IAAA,CAAK,WAAA,EAAa,CAAA,CAAE,CAAA;AAClD,MAAA;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,SAAA,GAAY,CAAC,WAAA,EAAa,cAAA,EAAgB,SAAS,iBAAiB,CAAA;AAC1E,EAAA,KAAA,MAAW,CAAC,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA,EAAG;AACjD,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,CAAC,MAAA,KAAW,GAAA,CAAI,aAAY,CAAE,UAAA,CAAW,MAAM,CAAC,CAAA,EAAG;AACpE,MAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,EAAE,CAAA;AACpC,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,WAAA,EAAc,GAAG,CAAA,CAAE,CAAA;AAChC,MAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,SAAS,UAAA,GAAa,EAAA;AAAA,IACtB,UAAA;AAAA,IACA,gBACE,UAAA,GAAa,EAAA,IAAM,gBACf,EAAE,IAAA,EAAM,WAAoB,SAAA,EAAW,aAAA,CAAc,MAAK,GAC1D,UAAA,GAAa,KACX,EAAE,IAAA,EAAM,WAAmB,GAC3B,EAAE,MAAM,OAAA,EAAiB;AAAA,IACjC,SAAS,EAAC;AAAA,IACV,GAAI,aAAA,IAAiB,EAAE,aAAA,EAAc;AAAA,IACrC,OAAA;AAAA,IACA,kBAAA,EAAoB,SAAA;AAAA,IACpB,gBAAA,EAAkB,UAAA,GAAa,EAAA,GAAK,QAAA,GAAW,MAAA;AAAA,IAC/C,SAAA,sBAAe,IAAA;AAAK,GACtB;AACF;AAcA,eAAe,eAAe,MAAA,EAA8B;AAC1D,EAAA,IAAI,QAAA;AAMJ,EAAA,IAAI,OAAO,UAAA,EAAY;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,gBAAA,EAAkB,YAAA,EAAc,cAAa,GAAI,MAAM,OAC7D,uCACF,CAAA;AACA,MAAA,MAAM,MAAA,GAAS,IAAI,gBAAA,CAAiB,MAAA,CAAO,UAAU,CAAA;AAGrD,MAAA,MAAM,YAAA,GAAe,MAAA,CAAO,MAAA,GACxB,IAAI,YAAA,CAAa;AAAA,QACf,QAAQ,MAAA,CAAO;AAAA,OAChB,CAAA,GACD,KAAA,CAAA;AAGJ,MAAA,MAAM,YAAA,GAAe,IAAI,YAAA,CAAa,MAAA,EAAQ,YAAA,EAAc;AAAA,QAC1D,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,OAAO,MAAA,CAAO;AAAA,OACf,CAAA;AAED,MAAA,MAAM,aAAa,WAAA,EAAY;AAE/B,MAAA,IAAI,OAAO,KAAA,EAAO;AAChB,QAAA,OAAA,CAAQ,MAAM,yDAAA,EAA2D;AAAA,UACvE,aAAA,EAAe,CAAC,CAAC,MAAA,CAAO;AAAA,SACzB,CAAA;AAAA,MACH;AAEA,MAAA,QAAA,GAAW;AAAA,QACT,MAAA,EAAQ,OAAO,KAAA,KAAyD;AACtE,UAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA;AAG9C,UAAA,OAAO;AAAA,YACL,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,aAAc,MAAA,CAA8C,WAAA;AAAA,YAG5D,YAAY,MAAA,CAAO,UAAA;AAAA,YACnB,gBAAgB,MAAA,CAAO,cAAA;AAAA,YACvB,eAAe,MAAA,CAAO,aAAA;AAAA,YACtB,oBAAoB,MAAA,CAAO,kBAAA;AAAA,YAC3B,kBAAkB,MAAA,CAAO,gBAAA;AAAA,YACzB,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,WAAW,MAAA,CAAO,SAAA;AAAA,YAClB,SAAS,EAAC;AAAA;AAAA,YACV,aAAa,MAAA,CAAO,WAAA;AAAA,YACpB,aAAa,MAAA,CAAO;AAAA,WACtB;AAAA,QACF,CAAA;AAAA,QACA,OAAA,EAAS,MAAM,YAAA,CAAa,OAAA;AAAQ,OACtC;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,OAAO,KAAA,EAAO;AAChB,QAAA,OAAA,CAAQ,IAAA,CAAK,sEAAsE,KAAK,CAAA;AAAA,MAC1F;AACA,MAAA,QAAA,GAAW;AAAA,QACT,MAAA,EAAQ,aAAA;AAAA,QACR,SAAS,MAAM;AAAA,OACjB;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AAEL,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,OAAA,CAAQ,MAAM,gEAAgE,CAAA;AAAA,IAChF;AACA,IAAA,QAAA,GAAW;AAAA,MACT,MAAA,EAAQ,aAAA;AAAA,MACR,SAAS,MAAM;AAAA,KACjB;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAsBO,SAAS,oBAAA,CAAqB,MAAA,GAA+B,EAAC,EAAG;AACtE,EAAA,IAAI,eAAA,GAA8E,IAAA;AAElF,EAAA,MAAM;AAAA,IACJ,eAAA,GAAkB,KAAA;AAAA,IAClB,WAAA;AAAA,IACA,YAAY,EAAC;AAAA,IACb,mBAAA,GAAsB,EAAA;AAAA,IACtB,eAAA,GAAkB;AAAA,MAChB,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,yCAAA;AAAA,MACT,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,KAChD;AAAA,IACA,WAAA,GAAc,UAAA;AAAA,IACd,UAAA,GAAa,UAAA;AAAA,IACb,KAAA,GAAQ;AAAA,GACV,GAAI,MAAA;AAEJ,EAAA,OAAO,OAAO,OAAA,KAAgD;AAC5D,IAAA,IAAI;AAEF,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,eAAA,GAAkB,cAAA,CAAe,EAAE,GAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,MACvD;AACA,MAAA,MAAM,WAAW,MAAM,eAAA;AAGvB,MAAA,MAAM,UAAA,GAAa,SAAA,CAAU,IAAA,CAAK,CAAC,OAAA,KAAY;AAC7C,QAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,UAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA;AAAA,QACpD;AACA,QAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAC9C,CAAC,CAAA;AAED,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,OAAO,aAAa,IAAA,EAAK;AAAA,MAC3B;AAGA,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,MAAA,MAAM,KAAA,GAAwB;AAAA,QAC5B,SAAA,EAAW,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,IAAK,KAAA,CAAA;AAAA,QAChD,SAAA,EAAW,YAAY,OAAO,CAAA;AAAA,QAC9B,SAAS,MAAA,CAAO,WAAA,CAAY,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA;AAAA,QACrD,GAAA,EAAK,GAAA,CAAI,QAAA,GAAW,GAAA,CAAI,MAAA;AAAA,QACxB,QAAQ,OAAA,CAAQ;AAAA,OAClB;AAGA,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA;AAI1C,MAAA,IAAI,OAAO,WAAA,EAAa;AACtB,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,OAAA,CAAQ,MAAM,iCAAA,EAAmC;AAAA,YAC/C,QAAQ,MAAA,CAAO,WAAA;AAAA,YACf,KAAA,EAAO,OAAO,aAAA,EAAe,IAAA;AAAA,YAC7B,YAAY,MAAA,CAAO,UAAA;AAAA,YACnB,QAAA,EAAU,QAAQ,OAAA,CAAQ;AAAA,WAC3B,CAAA;AAAA,QACH;AAGA,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAM,cAAA,GAAiB,MAAM,WAAA,CAAY,OAAA,EAAS,MAAM,CAAA;AACxD,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,OAAO,cAAA;AAAA,UACT;AAAA,QACF;AAGA,QAAA,OAAO,YAAA,CAAa,IAAA;AAAA,UAClB;AAAA,YACE,KAAA,EAAO,yBAAA;AAAA,YACP,QAAQ,MAAA,CAAO,WAAA;AAAA,YACf,QAAA,EAAU,IAAA;AAAA,YACV,YAAY,MAAA,CAAO,UAAA;AAAA,YACnB,KAAA,EAAO,OAAO,aAAA,EAAe,IAAA;AAAA,YAC7B,WAAW,MAAA,CAAO;AAAA,WACpB;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,GAAA;AAAA,YACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB;AAChD,SACF;AAAA,MACF;AAIA,MAAA,IAAI,MAAA,CAAO,gBAAgB,KAAA,EAAO;AAChC,QAAA,MAAM,QAAA,GAAW,oBAAoB,MAAA,EAAQ;AAAA,UAC3C,mBAAA;AAAA,UACA,aAAA,EAAe;AAAA,SAChB,CAAA;AAED,QAAA,IAAI,SAAS,YAAA,EAAc;AAEzB,UAAA,IAAI,WAAA,EAAa;AACf,YAAA,MAAM,cAAA,GAAiB,MAAM,WAAA,CAAY,OAAA,EAAS,MAAM,CAAA;AACxD,YAAA,IAAI,cAAA,EAAgB;AAClB,cAAA,OAAO,cAAA;AAAA,YACT;AAAA,UACF;AAGA,UAAA,QAAQ,SAAS,MAAA;AAAQ,YACvB,KAAK,OAAA,EAAS;AACZ,cAAA,MAAMA,YAAW,YAAA,CAAa,IAAA;AAAA,gBAC5B;AAAA,kBACE,OAAO,eAAA,CAAgB,OAAA;AAAA,kBACvB,QAAA,EAAU,IAAA;AAAA,kBACV,YAAY,MAAA,CAAO,UAAA;AAAA,kBACnB,WAAW,MAAA,CAAO;AAAA,iBACpB;AAAA,gBACA,EAAE,MAAA,EAAQ,eAAA,CAAgB,MAAA;AAAO,eACnC;AAEA,cAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,gBAAA,MAAA,CAAO,OAAA,CAAQ,gBAAgB,OAAO,CAAA,CAAE,QAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAChE,kBAAAA,SAAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,gBACjC,CAAC,CAAA;AAAA,cACH;AAEA,cAAA,OAAOA,SAAAA;AAAA,YACT;AAAA,YAEA,KAAK,UAAA;AACH,cAAA,OAAO,aAAa,QAAA,CAAS,IAAI,IAAI,WAAA,EAAa,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,YAEhE,KAAK,SAAA;AACH,cAAA,OAAO,aAAa,OAAA,CAAQ,IAAI,IAAI,UAAA,EAAY,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,YAE9D,KAAK,KAAA;AACH,cAAA,IAAI,KAAA,IAAS,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc;AAClD,gBAAA,OAAA,CAAQ,MAAM,6BAAA,EAA+B;AAAA,kBAC3C,WAAW,KAAA,CAAM,SAAA;AAAA,kBACjB,WAAW,KAAA,CAAM,SAAA;AAAA,kBACjB,YAAY,MAAA,CAAO,UAAA;AAAA,kBACnB,KAAA,EAAO,OAAO,aAAA,EAAe,IAAA;AAAA,kBAC7B,QAAA,EAAU,QAAQ,OAAA,CAAQ;AAAA,iBAC3B,CAAA;AAAA,cACH;AACA,cAAA;AAAA,YAEF;AACE,cAAA;AAAA;AACJ,QACF;AAAA,MACF;AAGA,MAAA,MAAM,QAAA,GAAW,aAAa,IAAA,EAAK;AAGnC,MAAA,QAAA,CAAS,QAAQ,GAAA,CAAI,cAAA,EAAgB,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAC9D,MAAA,QAAA,CAAS,QAAQ,GAAA,CAAI,gBAAA,EAAkB,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA;AACnE,MAAA,IAAI,MAAA,CAAO,eAAe,IAAA,EAAM;AAC9B,QAAA,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAa,MAAA,CAAO,cAAc,IAAI,CAAA;AAAA,MAC7D;AAEA,MAAA,OAAO,QAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,iCAAiC,KAAK,CAAA;AACpD,MAAA,OAAO,aAAa,IAAA,EAAK;AAAA,IAC3B;AAAA,EACF,CAAA;AACF","file":"index.mjs","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Middleware with WASM Support\n *\n * This module provides Next.js middleware that uses the unified WASM runtime.\n * For Edge Runtime, consumers must provide a pre-compiled WASM module via static import:\n *\n * ```typescript\n * // In your middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * apiKey: process.env.AGENTSHIELD_API_KEY,\n * onAgentDetected: 'block',\n * });\n * ```\n *\n * When an API key is provided, the middleware will:\n * 1. Load customer policies (deny lists, allow lists, thresholds) from AgentShield API\n * 2. Automatically block agents that match deny list entries\n * 3. Cache policies for 5 minutes with background refresh\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport type { DetectionResult } from '@kya-os/agentshield-shared';\nimport { evaluateEnforcement } from '@kya-os/agentshield-shared';\nimport { getClientIp } from '../utils';\n\n/**\n * Edge middleware configuration\n */\nexport interface EdgeMiddlewareConfig {\n /**\n * Pre-compiled WebAssembly.Module for Edge Runtime\n * Use static import: `import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module'`\n */\n wasmModule?: WebAssembly.Module;\n\n /**\n * API key for loading customer policies from AgentShield dashboard\n * When provided, enables policy enforcement (deny lists, allow lists, thresholds)\n */\n apiKey?: string;\n\n /**\n * Custom URL for the policy API\n * @default 'https://api.agentshield.io'\n */\n policyApiUrl?: string;\n\n /**\n * Action to take when an agent is detected\n * @default 'log'\n */\n onAgentDetected?: 'block' | 'redirect' | 'rewrite' | 'log' | 'allow';\n\n /**\n * Custom handler called when an agent is detected\n * Return a NextResponse to override default behavior\n */\n onDetection?: (\n request: NextRequest,\n result: DetectionResult\n ) => Promise<NextResponse | void> | NextResponse | void;\n\n /**\n * Paths to skip detection (can be string prefixes or RegExp)\n */\n skipPaths?: (string | RegExp)[];\n\n /**\n * Minimum confidence threshold (0-100 scale) for considering a request as agent traffic\n * @default 70\n */\n confidenceThreshold?: number;\n\n /**\n * Response to send when blocking agents\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * URL to redirect to when redirecting agents\n */\n redirectUrl?: string;\n\n /**\n * URL to rewrite to when rewriting agent requests\n */\n rewriteUrl?: string;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n/**\n * Detection input extracted from request\n */\ninterface DetectionInput {\n userAgent?: string;\n ipAddress?: string;\n headers: Record<string, string>;\n url?: string;\n method?: string;\n}\n\n/**\n * Simple edge-safe detector that uses pattern matching\n * Falls back to this when WASM is not available\n */\nasync function patternDetect(input: DetectionInput): Promise<DetectionResult> {\n const userAgent = input.userAgent?.toLowerCase() || '';\n const reasons: string[] = [];\n let confidence = 0;\n let detectedAgent: { type: string; name: string } | undefined;\n\n // AI agent patterns with confidence scores (0-100 scale)\n const patterns = [\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-?bot/i, name: 'ClaudeBot', confidence: 95 },\n { pattern: /anthropic/i, name: 'Claude', confidence: 90 },\n { pattern: /gptbot/i, name: 'GPTBot', confidence: 90 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 90 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 85 },\n { pattern: /copilot/i, name: 'Copilot', confidence: 85 },\n { pattern: /gemini/i, name: 'Gemini', confidence: 85 },\n { pattern: /bard/i, name: 'Bard', confidence: 85 },\n // HTTP client libraries (often used by AI agents/scrapers)\n { pattern: /^axios\\//i, name: 'HTTP Client (axios)', confidence: 75 },\n { pattern: /^node-fetch\\//i, name: 'HTTP Client (node-fetch)', confidence: 75 },\n { pattern: /^got\\//i, name: 'HTTP Client (got)', confidence: 75 },\n { pattern: /^python-requests\\//i, name: 'HTTP Client (requests)', confidence: 75 },\n { pattern: /^python-urllib/i, name: 'HTTP Client (urllib)', confidence: 75 },\n { pattern: /^curl\\//i, name: 'HTTP Client (curl)', confidence: 60 },\n { pattern: /^wget\\//i, name: 'HTTP Client (wget)', confidence: 60 },\n { pattern: /^httpie\\//i, name: 'HTTP Client (httpie)', confidence: 70 },\n { pattern: /^undici\\//i, name: 'HTTP Client (undici)', confidence: 75 },\n ];\n\n for (const { pattern, name, confidence: patternConfidence } of patterns) {\n if (pattern.test(userAgent)) {\n confidence = patternConfidence;\n detectedAgent = { type: name.toLowerCase(), name };\n reasons.push(`known_pattern:${name.toLowerCase()}`);\n break;\n }\n }\n\n // Check for AI-specific headers\n const aiHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'signature-agent'];\n for (const [key] of Object.entries(input.headers)) {\n if (aiHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n confidence = Math.max(confidence, 45);\n reasons.push(`ai_headers:${key}`);\n break;\n }\n }\n\n return {\n isAgent: confidence > 30,\n confidence,\n detectionClass:\n confidence > 30 && detectedAgent\n ? { type: 'AiAgent' as const, agentType: detectedAgent.name }\n : confidence > 30\n ? { type: 'Unknown' as const }\n : { type: 'Human' as const },\n signals: [],\n ...(detectedAgent && { detectedAgent }),\n reasons,\n verificationMethod: 'pattern' as const,\n forgeabilityRisk: confidence > 80 ? 'medium' : 'high',\n timestamp: new Date(),\n };\n}\n\n/**\n * Extended detection result with policy enforcement\n */\ninterface PolicyEnforcedResult extends DetectionResult {\n shouldBlock?: boolean;\n blockReason?: 'deny_list' | 'not_in_allow_list' | 'threshold';\n}\n\n/**\n * Create detector using WASM runtime or fallback\n * When apiKey is provided, policy enforcement is enabled\n */\nasync function createDetector(config: EdgeMiddlewareConfig) {\n let detector: {\n detect: (input: DetectionInput) => Promise<PolicyEnforcedResult>;\n isReady: () => boolean;\n };\n\n // Try to use wasm-runtime if WASM module is provided\n if (config.wasmModule) {\n try {\n const { StaticWasmLoader, WasmDetector, PolicyLoader } = await import(\n '@kya-os/agentshield-wasm-runtime/edge'\n );\n const loader = new StaticWasmLoader(config.wasmModule);\n\n // Create policy loader if API key is provided\n const policyLoader = config.apiKey\n ? new PolicyLoader({\n apiUrl: config.policyApiUrl,\n })\n : undefined;\n\n // Create detector with policy support\n const wasmDetector = new WasmDetector(loader, policyLoader, {\n apiKey: config.apiKey,\n debug: config.debug,\n });\n\n await wasmDetector.ensureReady();\n\n if (config.debug) {\n console.debug('[AgentShield] WASM detector initialized in Edge Runtime', {\n policyEnabled: !!config.apiKey,\n });\n }\n\n detector = {\n detect: async (input: DetectionInput): Promise<PolicyEnforcedResult> => {\n const result = await wasmDetector.detect(input);\n // Convert IDetectionResult to DetectionResult by adding required fields\n // Type assertion needed due to different DetectionClass definitions\n return {\n isAgent: result.isAgent,\n isAiCrawler: (result as unknown as Record<string, unknown>).isAiCrawler as\n | boolean\n | undefined,\n confidence: result.confidence,\n detectionClass: result.detectionClass as DetectionResult['detectionClass'],\n detectedAgent: result.detectedAgent,\n verificationMethod: result.verificationMethod,\n forgeabilityRisk: result.forgeabilityRisk,\n reasons: result.reasons,\n timestamp: result.timestamp,\n signals: [], // Required by DetectionResult, empty for WASM results\n shouldBlock: result.shouldBlock,\n blockReason: result.blockReason as PolicyEnforcedResult['blockReason'],\n };\n },\n isReady: () => wasmDetector.isReady(),\n };\n } catch (error) {\n if (config.debug) {\n console.warn('[AgentShield] WASM runtime not available, using pattern detection:', error);\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n } else {\n // Use pattern-based detection\n if (config.debug) {\n console.debug('[AgentShield] No WASM module provided, using pattern detection');\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n\n return detector;\n}\n\n/**\n * Create Edge middleware with WASM support\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * onAgentDetected: 'block',\n * confidenceThreshold: 70,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function createEdgeMiddleware(config: EdgeMiddlewareConfig = {}) {\n let detectorPromise: Promise<Awaited<ReturnType<typeof createDetector>>> | null = null;\n\n const {\n onAgentDetected = 'log',\n onDetection,\n skipPaths = [],\n confidenceThreshold = 70,\n blockedResponse = {\n status: 403,\n message: 'Access denied: Automated agent detected',\n headers: { 'Content-Type': 'application/json' },\n },\n redirectUrl = '/blocked',\n rewriteUrl = '/blocked',\n debug = false,\n } = config;\n\n return async (request: NextRequest): Promise<NextResponse> => {\n try {\n // Initialize detector lazily\n if (!detectorPromise) {\n detectorPromise = createDetector({ ...config, debug });\n }\n const detector = await detectorPromise;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => {\n if (typeof pattern === 'string') {\n return request.nextUrl.pathname.startsWith(pattern);\n }\n return pattern.test(request.nextUrl.pathname);\n });\n\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n // Extract request context\n const url = new URL(request.url);\n const input: DetectionInput = {\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress: getClientIp(request),\n headers: Object.fromEntries(request.headers.entries()),\n url: url.pathname + url.search,\n method: request.method,\n };\n\n // Run detection\n const result = await detector.detect(input);\n\n // POLICY ENFORCEMENT: Check shouldBlock from policy rules (deny list, allow list, threshold)\n // This takes precedence over the general threshold check below\n if (result.shouldBlock) {\n if (debug) {\n console.debug('[AgentShield] Blocked by policy', {\n reason: result.blockReason,\n agent: result.detectedAgent?.name,\n confidence: result.confidence,\n pathname: request.nextUrl.pathname,\n });\n }\n\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return 403 with policy block reason\n return NextResponse.json(\n {\n error: 'Access denied by policy',\n reason: result.blockReason,\n detected: true,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n timestamp: result.timestamp,\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n // Check if agent detected above threshold (when policy doesn't block)\n // Skip if shouldBlock === false (agent explicitly allowed by policy)\n if (result.shouldBlock !== false) {\n const decision = evaluateEnforcement(result, {\n confidenceThreshold,\n defaultAction: onAgentDetected,\n });\n\n if (decision.shouldNotify) {\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Handle based on decision action\n switch (decision.action) {\n case 'block': {\n const response = NextResponse.json(\n {\n error: blockedResponse.message,\n detected: true,\n confidence: result.confidence,\n timestamp: result.timestamp,\n },\n { status: blockedResponse.status }\n );\n\n if (blockedResponse.headers) {\n Object.entries(blockedResponse.headers).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n }\n\n return response;\n }\n\n case 'redirect':\n return NextResponse.redirect(new URL(redirectUrl, request.url));\n\n case 'rewrite':\n return NextResponse.rewrite(new URL(rewriteUrl, request.url));\n\n case 'log':\n if (debug || process.env.NODE_ENV !== 'production') {\n console.debug('AgentShield: Agent detected', {\n ipAddress: input.ipAddress,\n userAgent: input.userAgent,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n pathname: request.nextUrl.pathname,\n });\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n // Continue with request\n const response = NextResponse.next();\n\n // Add detection headers\n response.headers.set('kya-detected', result.isAgent.toString());\n response.headers.set('kya-confidence', result.confidence.toString());\n if (result.detectedAgent?.name) {\n response.headers.set('kya-agent', result.detectedAgent.name);\n }\n\n return response;\n } catch (error) {\n console.error('AgentShield middleware error:', error);\n return NextResponse.next();\n }\n };\n}\n\n// Re-export types for convenience\nexport type { DetectionResult };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts","../../src/edge/index.ts"],"names":["response"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Middleware with WASM Support\n *\n * This module provides Next.js middleware that uses the unified WASM runtime.\n * For Edge Runtime, consumers must provide a pre-compiled WASM module via static import:\n *\n * ```typescript\n * // In your middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * apiKey: process.env.AGENTSHIELD_API_KEY,\n * onAgentDetected: 'block',\n * });\n * ```\n *\n * When an API key is provided, the middleware will:\n * 1. Load customer policies (deny lists, allow lists, thresholds) from AgentShield API\n * 2. Automatically block agents that match deny list entries\n * 3. Cache policies for 5 minutes with background refresh\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport type { DetectionResult } from '@kya-os/agentshield-shared';\nimport { evaluateEnforcement } from '@kya-os/agentshield-shared';\nimport { getClientIp } from '../utils';\n\n/**\n * Edge middleware configuration\n */\nexport interface EdgeMiddlewareConfig {\n /**\n * Pre-compiled WebAssembly.Module for Edge Runtime\n * Use static import: `import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module'`\n */\n wasmModule?: WebAssembly.Module;\n\n /**\n * API key for loading customer policies from AgentShield dashboard\n * When provided, enables policy enforcement (deny lists, allow lists, thresholds)\n */\n apiKey?: string;\n\n /**\n * Custom URL for the policy API\n * @default 'https://api.agentshield.io'\n */\n policyApiUrl?: string;\n\n /**\n * Action to take when an agent is detected\n * @default 'log'\n */\n onAgentDetected?: 'block' | 'redirect' | 'rewrite' | 'log' | 'allow';\n\n /**\n * Custom handler called when an agent is detected\n * Return a NextResponse to override default behavior\n */\n onDetection?: (\n request: NextRequest,\n result: DetectionResult\n ) => Promise<NextResponse | void> | NextResponse | void;\n\n /**\n * Paths to skip detection (can be string prefixes or RegExp)\n */\n skipPaths?: (string | RegExp)[];\n\n /**\n * Minimum confidence threshold (0-100 scale) for considering a request as agent traffic\n * @default 70\n */\n confidenceThreshold?: number;\n\n /**\n * Response to send when blocking agents\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * URL to redirect to when redirecting agents\n */\n redirectUrl?: string;\n\n /**\n * URL to rewrite to when rewriting agent requests\n */\n rewriteUrl?: string;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n/**\n * Detection input extracted from request\n */\ninterface DetectionInput {\n userAgent?: string;\n ipAddress?: string;\n headers: Record<string, string>;\n url?: string;\n method?: string;\n}\n\n/**\n * Simple edge-safe detector that uses pattern matching\n * Falls back to this when WASM is not available\n */\nasync function patternDetect(input: DetectionInput): Promise<DetectionResult> {\n const userAgent = input.userAgent?.toLowerCase() || '';\n const reasons: string[] = [];\n let confidence = 0;\n let detectedAgent: { type: string; name: string } | undefined;\n\n // AI agent patterns with confidence scores (0-100 scale)\n const patterns = [\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-user/i, name: 'Claude', confidence: 95 },\n { pattern: /claude-?bot/i, name: 'ClaudeBot', confidence: 95 },\n { pattern: /anthropic/i, name: 'Claude', confidence: 90 },\n { pattern: /gptbot/i, name: 'GPTBot', confidence: 90 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 90 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 85 },\n { pattern: /copilot/i, name: 'Copilot', confidence: 85 },\n { pattern: /gemini/i, name: 'Gemini', confidence: 85 },\n { pattern: /bard/i, name: 'Bard', confidence: 85 },\n // HTTP client libraries (often used by AI agents/scrapers)\n { pattern: /^axios\\//i, name: 'HTTP Client (axios)', confidence: 75 },\n { pattern: /^node-fetch\\//i, name: 'HTTP Client (node-fetch)', confidence: 75 },\n { pattern: /^got\\//i, name: 'HTTP Client (got)', confidence: 75 },\n { pattern: /^python-requests\\//i, name: 'HTTP Client (requests)', confidence: 75 },\n { pattern: /^python-urllib/i, name: 'HTTP Client (urllib)', confidence: 75 },\n { pattern: /^curl\\//i, name: 'HTTP Client (curl)', confidence: 60 },\n { pattern: /^wget\\//i, name: 'HTTP Client (wget)', confidence: 60 },\n { pattern: /^httpie\\//i, name: 'HTTP Client (httpie)', confidence: 70 },\n { pattern: /^undici\\//i, name: 'HTTP Client (undici)', confidence: 75 },\n ];\n\n for (const { pattern, name, confidence: patternConfidence } of patterns) {\n if (pattern.test(userAgent)) {\n confidence = patternConfidence;\n detectedAgent = { type: name.toLowerCase(), name };\n reasons.push(`known_pattern:${name.toLowerCase()}`);\n break;\n }\n }\n\n // Check for AI-specific headers\n const aiHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'signature-agent'];\n for (const [key] of Object.entries(input.headers)) {\n if (aiHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n confidence = Math.max(confidence, 45);\n reasons.push(`ai_headers:${key}`);\n break;\n }\n }\n\n return {\n isAgent: confidence > 30,\n confidence,\n detectionClass:\n confidence > 30 && detectedAgent\n ? { type: 'AiAgent' as const, agentType: detectedAgent.name }\n : confidence > 30\n ? { type: 'Unknown' as const }\n : { type: 'Human' as const },\n signals: [],\n ...(detectedAgent && { detectedAgent }),\n reasons,\n verificationMethod: 'pattern' as const,\n forgeabilityRisk: confidence > 80 ? 'medium' : 'high',\n timestamp: new Date(),\n };\n}\n\n/**\n * Extended detection result with policy enforcement\n */\ninterface PolicyEnforcedResult extends DetectionResult {\n shouldBlock?: boolean;\n blockReason?: 'deny_list' | 'not_in_allow_list' | 'threshold';\n}\n\n/**\n * Create detector using WASM runtime or fallback\n * When apiKey is provided, policy enforcement is enabled\n */\nasync function createDetector(config: EdgeMiddlewareConfig) {\n let detector: {\n detect: (input: DetectionInput) => Promise<PolicyEnforcedResult>;\n isReady: () => boolean;\n };\n\n // Try to use wasm-runtime if WASM module is provided\n if (config.wasmModule) {\n try {\n const { StaticWasmLoader, WasmDetector, PolicyLoader } = await import(\n '@kya-os/agentshield-wasm-runtime/edge'\n );\n const loader = new StaticWasmLoader(config.wasmModule);\n\n // Create policy loader if API key is provided\n const policyLoader = config.apiKey\n ? new PolicyLoader({\n apiUrl: config.policyApiUrl,\n })\n : undefined;\n\n // Create detector with policy support\n const wasmDetector = new WasmDetector(loader, policyLoader, {\n apiKey: config.apiKey,\n debug: config.debug,\n });\n\n await wasmDetector.ensureReady();\n\n if (config.debug) {\n console.debug('[AgentShield] WASM detector initialized in Edge Runtime', {\n policyEnabled: !!config.apiKey,\n });\n }\n\n detector = {\n detect: async (input: DetectionInput): Promise<PolicyEnforcedResult> => {\n const result = await wasmDetector.detect(input);\n // Convert IDetectionResult to DetectionResult by adding required fields\n // Type assertion needed due to different DetectionClass definitions\n return {\n isAgent: result.isAgent,\n isAiCrawler: (result as unknown as Record<string, unknown>).isAiCrawler as\n | boolean\n | undefined,\n confidence: result.confidence,\n detectionClass: result.detectionClass as DetectionResult['detectionClass'],\n detectedAgent: result.detectedAgent,\n verificationMethod: result.verificationMethod,\n forgeabilityRisk: result.forgeabilityRisk,\n reasons: result.reasons,\n timestamp: result.timestamp,\n signals: [], // Required by DetectionResult, empty for WASM results\n shouldBlock: result.shouldBlock,\n blockReason: result.blockReason as PolicyEnforcedResult['blockReason'],\n };\n },\n isReady: () => wasmDetector.isReady(),\n };\n } catch (error) {\n if (config.debug) {\n console.warn('[AgentShield] WASM runtime not available, using pattern detection:', error);\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n } else {\n // Use pattern-based detection\n if (config.debug) {\n console.debug('[AgentShield] No WASM module provided, using pattern detection');\n }\n detector = {\n detect: patternDetect,\n isReady: () => true,\n };\n }\n\n return detector;\n}\n\n/**\n * Create Edge middleware with WASM support\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import wasmModule from '@kya-os/agentshield-wasm-runtime/wasm?module';\n * import { createEdgeMiddleware } from '@kya-os/agentshield-nextjs/edge';\n *\n * export const middleware = createEdgeMiddleware({\n * wasmModule,\n * onAgentDetected: 'block',\n * confidenceThreshold: 70,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function createEdgeMiddleware(config: EdgeMiddlewareConfig = {}) {\n let detectorPromise: Promise<Awaited<ReturnType<typeof createDetector>>> | null = null;\n\n const {\n onAgentDetected = 'log',\n onDetection,\n skipPaths = [],\n confidenceThreshold = 70,\n blockedResponse = {\n status: 403,\n message: 'Access denied: Automated agent detected',\n headers: { 'Content-Type': 'application/json' },\n },\n redirectUrl = '/blocked',\n rewriteUrl = '/blocked',\n debug = false,\n } = config;\n\n return async (request: NextRequest): Promise<NextResponse> => {\n try {\n // Initialize detector lazily\n if (!detectorPromise) {\n detectorPromise = createDetector({ ...config, debug });\n }\n const detector = await detectorPromise;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => {\n if (typeof pattern === 'string') {\n return request.nextUrl.pathname.startsWith(pattern);\n }\n return pattern.test(request.nextUrl.pathname);\n });\n\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n // Extract request context\n const url = new URL(request.url);\n const input: DetectionInput = {\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress: getClientIp(request),\n headers: Object.fromEntries(request.headers.entries()),\n url: url.pathname + url.search,\n method: request.method,\n };\n\n // Run detection\n const result = await detector.detect(input);\n\n // POLICY ENFORCEMENT: Check shouldBlock from policy rules (deny list, allow list, threshold)\n // This takes precedence over the general threshold check below\n if (result.shouldBlock) {\n if (debug) {\n console.debug('[AgentShield] Blocked by policy', {\n reason: result.blockReason,\n agent: result.detectedAgent?.name,\n confidence: result.confidence,\n pathname: request.nextUrl.pathname,\n });\n }\n\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Return 403 with policy block reason\n return NextResponse.json(\n {\n error: 'Access denied by policy',\n reason: result.blockReason,\n detected: true,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n timestamp: result.timestamp,\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n // Check if agent detected above threshold (when policy doesn't block)\n // Skip if shouldBlock === false (agent explicitly allowed by policy)\n if (result.shouldBlock !== false) {\n const decision = evaluateEnforcement(result, {\n confidenceThreshold,\n defaultAction: onAgentDetected,\n });\n\n if (decision.shouldNotify) {\n // Call custom detection handler if provided\n if (onDetection) {\n const customResponse = await onDetection(request, result);\n if (customResponse) {\n return customResponse;\n }\n }\n\n // Handle based on decision action\n switch (decision.action) {\n case 'block': {\n const response = NextResponse.json(\n {\n error: blockedResponse.message,\n detected: true,\n confidence: result.confidence,\n timestamp: result.timestamp,\n },\n { status: blockedResponse.status }\n );\n\n if (blockedResponse.headers) {\n Object.entries(blockedResponse.headers).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n }\n\n return response;\n }\n\n case 'redirect':\n return NextResponse.redirect(new URL(redirectUrl, request.url));\n\n case 'rewrite':\n return NextResponse.rewrite(new URL(rewriteUrl, request.url));\n\n case 'log':\n if (debug || process.env.NODE_ENV !== 'production') {\n console.debug('AgentShield: Agent detected', {\n ipAddress: input.ipAddress,\n userAgent: input.userAgent,\n confidence: result.confidence,\n agent: result.detectedAgent?.name,\n pathname: request.nextUrl.pathname,\n });\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n // Continue with request\n const response = NextResponse.next();\n\n // Add detection headers\n response.headers.set('kya-detected', result.isAgent.toString());\n response.headers.set('kya-confidence', result.confidence.toString());\n if (result.detectedAgent?.name) {\n response.headers.set('kya-agent', result.detectedAgent.name);\n }\n\n return response;\n } catch (error) {\n console.error('AgentShield middleware error:', error);\n return NextResponse.next();\n }\n };\n}\n\n// Re-export types for convenience\nexport type { DetectionResult };\n"]}
|
|
@@ -131,6 +131,7 @@ var EdgeRuntimeAgentShield = class {
|
|
|
131
131
|
// High confidence - explicit AI identifiers
|
|
132
132
|
{ pattern: /chatgpt-user/i, name: "ChatGPT", confidence: 0.95 },
|
|
133
133
|
{ pattern: /claude-web/i, name: "Claude", confidence: 0.95 },
|
|
134
|
+
{ pattern: /claude-user/i, name: "Claude", confidence: 0.95 },
|
|
134
135
|
{ pattern: /gpt-crawler/i, name: "GPT Crawler", confidence: 0.95 },
|
|
135
136
|
{ pattern: /perplexitybot/i, name: "Perplexity", confidence: 0.95 },
|
|
136
137
|
{ pattern: /perplexity-user/i, name: "Perplexity", confidence: 0.95 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/edge-runtime-loader.ts"],"names":["exports"],"mappings":"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","file":"edge-runtime-loader.js","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Compatible WASM Loader for AgentShield\n *\n * This module provides a pre-built solution for loading WASM in Edge Runtime.\n * It requires the WASM file to be manually placed in the project.\n */\n\nimport type { NextRequest } from 'next/server';\nimport { getClientIp } from './utils';\n\n// User must provide the WASM module via import\n// This is intentionally not imported here to allow user control\nexport interface WasmModule {\n default: WebAssembly.Module;\n}\n\nexport interface DetectionResult {\n isAgent: boolean;\n isAiCrawler?: boolean;\n confidence: number;\n agent?: string;\n verificationMethod: 'cryptographic' | 'pattern';\n riskLevel?: 'low' | 'medium' | 'high' | 'critical';\n timestamp: string;\n}\n\nexport interface AgentShieldConfig {\n wasmModule?: WebAssembly.Module;\n enableWasm?: boolean;\n onAgentDetected?: (result: DetectionResult) => void;\n blockAgents?: boolean;\n allowedAgents?: string[];\n debug?: boolean;\n}\n\ninterface WasmExports {\n detect_agent(metadataPtr: number, metadataLen: number): number;\n get_version(): number;\n __wbindgen_malloc(size: number): number;\n __wbindgen_free(ptr: number, size: number): void;\n __wbindgen_realloc(ptr: number, oldSize: number, newSize: number): number;\n memory: WebAssembly.Memory;\n}\n\nclass EdgeRuntimeAgentShield {\n private wasmInstance: WebAssembly.Instance | null = null;\n private wasmMemory: WebAssembly.Memory | null = null;\n private config: AgentShieldConfig;\n private initialized = false;\n\n constructor(config: AgentShieldConfig = {}) {\n this.config = config;\n }\n\n async init(wasmModule?: WebAssembly.Module): Promise<void> {\n if (this.initialized) return;\n\n const module = wasmModule || this.config.wasmModule;\n\n if (module && this.config.enableWasm !== false) {\n try {\n this.wasmMemory = new WebAssembly.Memory({ initial: 17, maximum: 256 });\n\n const imports = {\n wbg: {\n __wbindgen_throw: (ptr: number, len: number) => {\n throw new Error(this.readString(ptr, len));\n },\n __wbg_log_: (ptr: number, len: number) => {\n if (this.config.debug) {\n console.log(this.readString(ptr, len));\n }\n },\n },\n env: {\n memory: this.wasmMemory,\n },\n };\n\n this.wasmInstance = await WebAssembly.instantiate(module, imports);\n this.initialized = true;\n\n if (this.config.debug) {\n console.log('✅ AgentShield WASM initialized in Edge Runtime');\n }\n } catch (error) {\n console.warn('⚠️ WASM initialization failed, using pattern detection:', error);\n this.initialized = true;\n }\n } else {\n this.initialized = true;\n }\n }\n\n private readString(ptr: number, len: number): string {\n if (!this.wasmInstance || !this.wasmMemory) {\n throw new Error('WASM not initialized');\n }\n const memory = new Uint8Array(this.wasmMemory.buffer);\n const bytes = memory.slice(ptr, ptr + len);\n return new TextDecoder().decode(bytes);\n }\n\n private writeString(str: string): [number, number] {\n if (!this.wasmInstance) {\n throw new Error('WASM not initialized');\n }\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n\n const encoded = new TextEncoder().encode(str);\n const ptr = exports.__wbindgen_malloc(encoded.length);\n\n const memory = new Uint8Array(exports.memory.buffer);\n memory.set(encoded, ptr);\n\n return [ptr, encoded.length];\n }\n\n async detect(request: NextRequest): Promise<DetectionResult> {\n if (!this.initialized) {\n await this.init();\n }\n\n const metadata = {\n userAgent: request.headers.get('user-agent') || '',\n ipAddress: getClientIp(request) || '',\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // Try WASM detection first\n if (this.wasmInstance && this.config.enableWasm !== false) {\n try {\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n const [ptr, len] = this.writeString(JSON.stringify(metadata));\n\n const resultPtr = exports.detect_agent(ptr, len);\n // Read result with dynamic size\n let resultStr = '';\n let offset = 0;\n const memory = new Uint8Array((exports.memory as WebAssembly.Memory).buffer);\n\n // Read until we find the end of the JSON string\n while (offset < 4096) {\n // Max 4KB result\n const byte = memory[resultPtr + offset];\n if (byte === 0 || byte === undefined) break;\n offset++;\n }\n\n if (offset > 0) {\n resultStr = this.readString(resultPtr, offset);\n }\n\n exports.__wbindgen_free(ptr, len);\n if (offset > 0) {\n exports.__wbindgen_free(resultPtr, offset);\n }\n\n const result = JSON.parse(resultStr);\n\n const detection: DetectionResult = {\n ...result,\n verificationMethod: 'cryptographic',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected && detection.isAgent) {\n this.config.onAgentDetected(detection);\n }\n\n return detection;\n } catch (error) {\n if (this.config.debug) {\n console.error('WASM detection failed:', error);\n }\n // Fall through to pattern detection\n }\n }\n\n // Fallback: Pattern-based detection\n return this.patternDetection(metadata);\n }\n\n private patternDetection(metadata: {\n userAgent: string;\n ipAddress: string;\n headers: Record<string, string>;\n }): DetectionResult {\n const userAgent = metadata.userAgent.toLowerCase();\n\n // Enhanced AI agent patterns with confidence scores\n const patterns = [\n // High confidence - explicit AI identifiers\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 0.95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 0.95 },\n { pattern: /gpt-crawler/i, name: 'GPT Crawler', confidence: 0.95 },\n { pattern: /perplexitybot/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-user/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-ai/i, name: 'Perplexity', confidence: 0.95 },\n\n // Medium-high confidence - company identifiers\n { pattern: /anthropic/i, name: 'Anthropic', confidence: 0.9 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 0.9 },\n\n // Medium confidence - product names\n { pattern: /copilot/i, name: 'GitHub Copilot', confidence: 0.85 },\n { pattern: /bard/i, name: 'Google Bard', confidence: 0.85 },\n { pattern: /gemini/i, name: 'Google Gemini', confidence: 0.85 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 0.85 }, // Fallback\n { pattern: /\\byou\\.com\\b/i, name: 'You.com', confidence: 0.8 },\n { pattern: /\\bphind\\b/i, name: 'Phind', confidence: 0.8 },\n ];\n\n // Check for suspicious headers\n const suspiciousHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'x-llm-', 'x-gpt-'];\n\n let headerBoost = 0;\n for (const [key] of Object.entries(metadata.headers)) {\n if (suspiciousHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n headerBoost = 0.1;\n break;\n }\n }\n\n // Check patterns - patterns are ordered by confidence (highest first: 0.95, 0.90, 0.85...)\n // so breaking on first match returns the highest-confidence match\n for (const { pattern, name, confidence } of patterns) {\n if (pattern.test(userAgent)) {\n const finalConfidence = Math.min(confidence + headerBoost, 1.0);\n\n const result: DetectionResult = {\n isAgent: true,\n confidence: finalConfidence,\n agent: name,\n verificationMethod: 'pattern',\n riskLevel: finalConfidence > 0.9 ? 'high' : 'medium',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected) {\n this.config.onAgentDetected(result);\n }\n\n return result;\n }\n }\n\n // Not detected\n return {\n isAgent: false,\n confidence: 0.85,\n verificationMethod: 'pattern',\n timestamp: new Date().toISOString(),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n getVerificationMethod(): 'cryptographic' | 'pattern' {\n return this.wasmInstance ? 'cryptographic' : 'pattern';\n }\n}\n\n/**\n * Factory function to create an AgentShield instance for Edge Runtime\n */\nexport function createEdgeAgentShield(config?: AgentShieldConfig) {\n return new EdgeRuntimeAgentShield(config);\n}\n\n/**\n * Singleton instance for simple usage\n */\nlet defaultInstance: EdgeRuntimeAgentShield | null = null;\n\nexport function getDefaultAgentShield(config?: AgentShieldConfig): EdgeRuntimeAgentShield {\n if (!defaultInstance) {\n defaultInstance = new EdgeRuntimeAgentShield(config);\n }\n return defaultInstance;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/edge-runtime-loader.ts"],"names":["exports"],"mappings":"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","file":"edge-runtime-loader.js","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Compatible WASM Loader for AgentShield\n *\n * This module provides a pre-built solution for loading WASM in Edge Runtime.\n * It requires the WASM file to be manually placed in the project.\n */\n\nimport type { NextRequest } from 'next/server';\nimport { getClientIp } from './utils';\n\n// User must provide the WASM module via import\n// This is intentionally not imported here to allow user control\nexport interface WasmModule {\n default: WebAssembly.Module;\n}\n\nexport interface DetectionResult {\n isAgent: boolean;\n isAiCrawler?: boolean;\n confidence: number;\n agent?: string;\n verificationMethod: 'cryptographic' | 'pattern';\n riskLevel?: 'low' | 'medium' | 'high' | 'critical';\n timestamp: string;\n}\n\nexport interface AgentShieldConfig {\n wasmModule?: WebAssembly.Module;\n enableWasm?: boolean;\n onAgentDetected?: (result: DetectionResult) => void;\n blockAgents?: boolean;\n allowedAgents?: string[];\n debug?: boolean;\n}\n\ninterface WasmExports {\n detect_agent(metadataPtr: number, metadataLen: number): number;\n get_version(): number;\n __wbindgen_malloc(size: number): number;\n __wbindgen_free(ptr: number, size: number): void;\n __wbindgen_realloc(ptr: number, oldSize: number, newSize: number): number;\n memory: WebAssembly.Memory;\n}\n\nclass EdgeRuntimeAgentShield {\n private wasmInstance: WebAssembly.Instance | null = null;\n private wasmMemory: WebAssembly.Memory | null = null;\n private config: AgentShieldConfig;\n private initialized = false;\n\n constructor(config: AgentShieldConfig = {}) {\n this.config = config;\n }\n\n async init(wasmModule?: WebAssembly.Module): Promise<void> {\n if (this.initialized) return;\n\n const module = wasmModule || this.config.wasmModule;\n\n if (module && this.config.enableWasm !== false) {\n try {\n this.wasmMemory = new WebAssembly.Memory({ initial: 17, maximum: 256 });\n\n const imports = {\n wbg: {\n __wbindgen_throw: (ptr: number, len: number) => {\n throw new Error(this.readString(ptr, len));\n },\n __wbg_log_: (ptr: number, len: number) => {\n if (this.config.debug) {\n console.log(this.readString(ptr, len));\n }\n },\n },\n env: {\n memory: this.wasmMemory,\n },\n };\n\n this.wasmInstance = await WebAssembly.instantiate(module, imports);\n this.initialized = true;\n\n if (this.config.debug) {\n console.log('✅ AgentShield WASM initialized in Edge Runtime');\n }\n } catch (error) {\n console.warn('⚠️ WASM initialization failed, using pattern detection:', error);\n this.initialized = true;\n }\n } else {\n this.initialized = true;\n }\n }\n\n private readString(ptr: number, len: number): string {\n if (!this.wasmInstance || !this.wasmMemory) {\n throw new Error('WASM not initialized');\n }\n const memory = new Uint8Array(this.wasmMemory.buffer);\n const bytes = memory.slice(ptr, ptr + len);\n return new TextDecoder().decode(bytes);\n }\n\n private writeString(str: string): [number, number] {\n if (!this.wasmInstance) {\n throw new Error('WASM not initialized');\n }\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n\n const encoded = new TextEncoder().encode(str);\n const ptr = exports.__wbindgen_malloc(encoded.length);\n\n const memory = new Uint8Array(exports.memory.buffer);\n memory.set(encoded, ptr);\n\n return [ptr, encoded.length];\n }\n\n async detect(request: NextRequest): Promise<DetectionResult> {\n if (!this.initialized) {\n await this.init();\n }\n\n const metadata = {\n userAgent: request.headers.get('user-agent') || '',\n ipAddress: getClientIp(request) || '',\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // Try WASM detection first\n if (this.wasmInstance && this.config.enableWasm !== false) {\n try {\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n const [ptr, len] = this.writeString(JSON.stringify(metadata));\n\n const resultPtr = exports.detect_agent(ptr, len);\n // Read result with dynamic size\n let resultStr = '';\n let offset = 0;\n const memory = new Uint8Array((exports.memory as WebAssembly.Memory).buffer);\n\n // Read until we find the end of the JSON string\n while (offset < 4096) {\n // Max 4KB result\n const byte = memory[resultPtr + offset];\n if (byte === 0 || byte === undefined) break;\n offset++;\n }\n\n if (offset > 0) {\n resultStr = this.readString(resultPtr, offset);\n }\n\n exports.__wbindgen_free(ptr, len);\n if (offset > 0) {\n exports.__wbindgen_free(resultPtr, offset);\n }\n\n const result = JSON.parse(resultStr);\n\n const detection: DetectionResult = {\n ...result,\n verificationMethod: 'cryptographic',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected && detection.isAgent) {\n this.config.onAgentDetected(detection);\n }\n\n return detection;\n } catch (error) {\n if (this.config.debug) {\n console.error('WASM detection failed:', error);\n }\n // Fall through to pattern detection\n }\n }\n\n // Fallback: Pattern-based detection\n return this.patternDetection(metadata);\n }\n\n private patternDetection(metadata: {\n userAgent: string;\n ipAddress: string;\n headers: Record<string, string>;\n }): DetectionResult {\n const userAgent = metadata.userAgent.toLowerCase();\n\n // Enhanced AI agent patterns with confidence scores\n const patterns = [\n // High confidence - explicit AI identifiers\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 0.95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 0.95 },\n { pattern: /claude-user/i, name: 'Claude', confidence: 0.95 },\n { pattern: /gpt-crawler/i, name: 'GPT Crawler', confidence: 0.95 },\n { pattern: /perplexitybot/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-user/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-ai/i, name: 'Perplexity', confidence: 0.95 },\n\n // Medium-high confidence - company identifiers\n { pattern: /anthropic/i, name: 'Anthropic', confidence: 0.9 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 0.9 },\n\n // Medium confidence - product names\n { pattern: /copilot/i, name: 'GitHub Copilot', confidence: 0.85 },\n { pattern: /bard/i, name: 'Google Bard', confidence: 0.85 },\n { pattern: /gemini/i, name: 'Google Gemini', confidence: 0.85 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 0.85 }, // Fallback\n { pattern: /\\byou\\.com\\b/i, name: 'You.com', confidence: 0.8 },\n { pattern: /\\bphind\\b/i, name: 'Phind', confidence: 0.8 },\n ];\n\n // Check for suspicious headers\n const suspiciousHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'x-llm-', 'x-gpt-'];\n\n let headerBoost = 0;\n for (const [key] of Object.entries(metadata.headers)) {\n if (suspiciousHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n headerBoost = 0.1;\n break;\n }\n }\n\n // Check patterns - patterns are ordered by confidence (highest first: 0.95, 0.90, 0.85...)\n // so breaking on first match returns the highest-confidence match\n for (const { pattern, name, confidence } of patterns) {\n if (pattern.test(userAgent)) {\n const finalConfidence = Math.min(confidence + headerBoost, 1.0);\n\n const result: DetectionResult = {\n isAgent: true,\n confidence: finalConfidence,\n agent: name,\n verificationMethod: 'pattern',\n riskLevel: finalConfidence > 0.9 ? 'high' : 'medium',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected) {\n this.config.onAgentDetected(result);\n }\n\n return result;\n }\n }\n\n // Not detected\n return {\n isAgent: false,\n confidence: 0.85,\n verificationMethod: 'pattern',\n timestamp: new Date().toISOString(),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n getVerificationMethod(): 'cryptographic' | 'pattern' {\n return this.wasmInstance ? 'cryptographic' : 'pattern';\n }\n}\n\n/**\n * Factory function to create an AgentShield instance for Edge Runtime\n */\nexport function createEdgeAgentShield(config?: AgentShieldConfig) {\n return new EdgeRuntimeAgentShield(config);\n}\n\n/**\n * Singleton instance for simple usage\n */\nlet defaultInstance: EdgeRuntimeAgentShield | null = null;\n\nexport function getDefaultAgentShield(config?: AgentShieldConfig): EdgeRuntimeAgentShield {\n if (!defaultInstance) {\n defaultInstance = new EdgeRuntimeAgentShield(config);\n }\n return defaultInstance;\n}\n"]}
|
|
@@ -129,6 +129,7 @@ var EdgeRuntimeAgentShield = class {
|
|
|
129
129
|
// High confidence - explicit AI identifiers
|
|
130
130
|
{ pattern: /chatgpt-user/i, name: "ChatGPT", confidence: 0.95 },
|
|
131
131
|
{ pattern: /claude-web/i, name: "Claude", confidence: 0.95 },
|
|
132
|
+
{ pattern: /claude-user/i, name: "Claude", confidence: 0.95 },
|
|
132
133
|
{ pattern: /gpt-crawler/i, name: "GPT Crawler", confidence: 0.95 },
|
|
133
134
|
{ pattern: /perplexitybot/i, name: "Perplexity", confidence: 0.95 },
|
|
134
135
|
{ pattern: /perplexity-user/i, name: "Perplexity", confidence: 0.95 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/edge-runtime-loader.ts"],"names":["exports"],"mappings":"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","file":"edge-runtime-loader.mjs","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Compatible WASM Loader for AgentShield\n *\n * This module provides a pre-built solution for loading WASM in Edge Runtime.\n * It requires the WASM file to be manually placed in the project.\n */\n\nimport type { NextRequest } from 'next/server';\nimport { getClientIp } from './utils';\n\n// User must provide the WASM module via import\n// This is intentionally not imported here to allow user control\nexport interface WasmModule {\n default: WebAssembly.Module;\n}\n\nexport interface DetectionResult {\n isAgent: boolean;\n isAiCrawler?: boolean;\n confidence: number;\n agent?: string;\n verificationMethod: 'cryptographic' | 'pattern';\n riskLevel?: 'low' | 'medium' | 'high' | 'critical';\n timestamp: string;\n}\n\nexport interface AgentShieldConfig {\n wasmModule?: WebAssembly.Module;\n enableWasm?: boolean;\n onAgentDetected?: (result: DetectionResult) => void;\n blockAgents?: boolean;\n allowedAgents?: string[];\n debug?: boolean;\n}\n\ninterface WasmExports {\n detect_agent(metadataPtr: number, metadataLen: number): number;\n get_version(): number;\n __wbindgen_malloc(size: number): number;\n __wbindgen_free(ptr: number, size: number): void;\n __wbindgen_realloc(ptr: number, oldSize: number, newSize: number): number;\n memory: WebAssembly.Memory;\n}\n\nclass EdgeRuntimeAgentShield {\n private wasmInstance: WebAssembly.Instance | null = null;\n private wasmMemory: WebAssembly.Memory | null = null;\n private config: AgentShieldConfig;\n private initialized = false;\n\n constructor(config: AgentShieldConfig = {}) {\n this.config = config;\n }\n\n async init(wasmModule?: WebAssembly.Module): Promise<void> {\n if (this.initialized) return;\n\n const module = wasmModule || this.config.wasmModule;\n\n if (module && this.config.enableWasm !== false) {\n try {\n this.wasmMemory = new WebAssembly.Memory({ initial: 17, maximum: 256 });\n\n const imports = {\n wbg: {\n __wbindgen_throw: (ptr: number, len: number) => {\n throw new Error(this.readString(ptr, len));\n },\n __wbg_log_: (ptr: number, len: number) => {\n if (this.config.debug) {\n console.log(this.readString(ptr, len));\n }\n },\n },\n env: {\n memory: this.wasmMemory,\n },\n };\n\n this.wasmInstance = await WebAssembly.instantiate(module, imports);\n this.initialized = true;\n\n if (this.config.debug) {\n console.log('✅ AgentShield WASM initialized in Edge Runtime');\n }\n } catch (error) {\n console.warn('⚠️ WASM initialization failed, using pattern detection:', error);\n this.initialized = true;\n }\n } else {\n this.initialized = true;\n }\n }\n\n private readString(ptr: number, len: number): string {\n if (!this.wasmInstance || !this.wasmMemory) {\n throw new Error('WASM not initialized');\n }\n const memory = new Uint8Array(this.wasmMemory.buffer);\n const bytes = memory.slice(ptr, ptr + len);\n return new TextDecoder().decode(bytes);\n }\n\n private writeString(str: string): [number, number] {\n if (!this.wasmInstance) {\n throw new Error('WASM not initialized');\n }\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n\n const encoded = new TextEncoder().encode(str);\n const ptr = exports.__wbindgen_malloc(encoded.length);\n\n const memory = new Uint8Array(exports.memory.buffer);\n memory.set(encoded, ptr);\n\n return [ptr, encoded.length];\n }\n\n async detect(request: NextRequest): Promise<DetectionResult> {\n if (!this.initialized) {\n await this.init();\n }\n\n const metadata = {\n userAgent: request.headers.get('user-agent') || '',\n ipAddress: getClientIp(request) || '',\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // Try WASM detection first\n if (this.wasmInstance && this.config.enableWasm !== false) {\n try {\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n const [ptr, len] = this.writeString(JSON.stringify(metadata));\n\n const resultPtr = exports.detect_agent(ptr, len);\n // Read result with dynamic size\n let resultStr = '';\n let offset = 0;\n const memory = new Uint8Array((exports.memory as WebAssembly.Memory).buffer);\n\n // Read until we find the end of the JSON string\n while (offset < 4096) {\n // Max 4KB result\n const byte = memory[resultPtr + offset];\n if (byte === 0 || byte === undefined) break;\n offset++;\n }\n\n if (offset > 0) {\n resultStr = this.readString(resultPtr, offset);\n }\n\n exports.__wbindgen_free(ptr, len);\n if (offset > 0) {\n exports.__wbindgen_free(resultPtr, offset);\n }\n\n const result = JSON.parse(resultStr);\n\n const detection: DetectionResult = {\n ...result,\n verificationMethod: 'cryptographic',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected && detection.isAgent) {\n this.config.onAgentDetected(detection);\n }\n\n return detection;\n } catch (error) {\n if (this.config.debug) {\n console.error('WASM detection failed:', error);\n }\n // Fall through to pattern detection\n }\n }\n\n // Fallback: Pattern-based detection\n return this.patternDetection(metadata);\n }\n\n private patternDetection(metadata: {\n userAgent: string;\n ipAddress: string;\n headers: Record<string, string>;\n }): DetectionResult {\n const userAgent = metadata.userAgent.toLowerCase();\n\n // Enhanced AI agent patterns with confidence scores\n const patterns = [\n // High confidence - explicit AI identifiers\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 0.95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 0.95 },\n { pattern: /gpt-crawler/i, name: 'GPT Crawler', confidence: 0.95 },\n { pattern: /perplexitybot/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-user/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-ai/i, name: 'Perplexity', confidence: 0.95 },\n\n // Medium-high confidence - company identifiers\n { pattern: /anthropic/i, name: 'Anthropic', confidence: 0.9 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 0.9 },\n\n // Medium confidence - product names\n { pattern: /copilot/i, name: 'GitHub Copilot', confidence: 0.85 },\n { pattern: /bard/i, name: 'Google Bard', confidence: 0.85 },\n { pattern: /gemini/i, name: 'Google Gemini', confidence: 0.85 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 0.85 }, // Fallback\n { pattern: /\\byou\\.com\\b/i, name: 'You.com', confidence: 0.8 },\n { pattern: /\\bphind\\b/i, name: 'Phind', confidence: 0.8 },\n ];\n\n // Check for suspicious headers\n const suspiciousHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'x-llm-', 'x-gpt-'];\n\n let headerBoost = 0;\n for (const [key] of Object.entries(metadata.headers)) {\n if (suspiciousHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n headerBoost = 0.1;\n break;\n }\n }\n\n // Check patterns - patterns are ordered by confidence (highest first: 0.95, 0.90, 0.85...)\n // so breaking on first match returns the highest-confidence match\n for (const { pattern, name, confidence } of patterns) {\n if (pattern.test(userAgent)) {\n const finalConfidence = Math.min(confidence + headerBoost, 1.0);\n\n const result: DetectionResult = {\n isAgent: true,\n confidence: finalConfidence,\n agent: name,\n verificationMethod: 'pattern',\n riskLevel: finalConfidence > 0.9 ? 'high' : 'medium',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected) {\n this.config.onAgentDetected(result);\n }\n\n return result;\n }\n }\n\n // Not detected\n return {\n isAgent: false,\n confidence: 0.85,\n verificationMethod: 'pattern',\n timestamp: new Date().toISOString(),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n getVerificationMethod(): 'cryptographic' | 'pattern' {\n return this.wasmInstance ? 'cryptographic' : 'pattern';\n }\n}\n\n/**\n * Factory function to create an AgentShield instance for Edge Runtime\n */\nexport function createEdgeAgentShield(config?: AgentShieldConfig) {\n return new EdgeRuntimeAgentShield(config);\n}\n\n/**\n * Singleton instance for simple usage\n */\nlet defaultInstance: EdgeRuntimeAgentShield | null = null;\n\nexport function getDefaultAgentShield(config?: AgentShieldConfig): EdgeRuntimeAgentShield {\n if (!defaultInstance) {\n defaultInstance = new EdgeRuntimeAgentShield(config);\n }\n return defaultInstance;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/edge-runtime-loader.ts"],"names":["exports"],"mappings":"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","file":"edge-runtime-loader.mjs","sourcesContent":["/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Edge Runtime Compatible WASM Loader for AgentShield\n *\n * This module provides a pre-built solution for loading WASM in Edge Runtime.\n * It requires the WASM file to be manually placed in the project.\n */\n\nimport type { NextRequest } from 'next/server';\nimport { getClientIp } from './utils';\n\n// User must provide the WASM module via import\n// This is intentionally not imported here to allow user control\nexport interface WasmModule {\n default: WebAssembly.Module;\n}\n\nexport interface DetectionResult {\n isAgent: boolean;\n isAiCrawler?: boolean;\n confidence: number;\n agent?: string;\n verificationMethod: 'cryptographic' | 'pattern';\n riskLevel?: 'low' | 'medium' | 'high' | 'critical';\n timestamp: string;\n}\n\nexport interface AgentShieldConfig {\n wasmModule?: WebAssembly.Module;\n enableWasm?: boolean;\n onAgentDetected?: (result: DetectionResult) => void;\n blockAgents?: boolean;\n allowedAgents?: string[];\n debug?: boolean;\n}\n\ninterface WasmExports {\n detect_agent(metadataPtr: number, metadataLen: number): number;\n get_version(): number;\n __wbindgen_malloc(size: number): number;\n __wbindgen_free(ptr: number, size: number): void;\n __wbindgen_realloc(ptr: number, oldSize: number, newSize: number): number;\n memory: WebAssembly.Memory;\n}\n\nclass EdgeRuntimeAgentShield {\n private wasmInstance: WebAssembly.Instance | null = null;\n private wasmMemory: WebAssembly.Memory | null = null;\n private config: AgentShieldConfig;\n private initialized = false;\n\n constructor(config: AgentShieldConfig = {}) {\n this.config = config;\n }\n\n async init(wasmModule?: WebAssembly.Module): Promise<void> {\n if (this.initialized) return;\n\n const module = wasmModule || this.config.wasmModule;\n\n if (module && this.config.enableWasm !== false) {\n try {\n this.wasmMemory = new WebAssembly.Memory({ initial: 17, maximum: 256 });\n\n const imports = {\n wbg: {\n __wbindgen_throw: (ptr: number, len: number) => {\n throw new Error(this.readString(ptr, len));\n },\n __wbg_log_: (ptr: number, len: number) => {\n if (this.config.debug) {\n console.log(this.readString(ptr, len));\n }\n },\n },\n env: {\n memory: this.wasmMemory,\n },\n };\n\n this.wasmInstance = await WebAssembly.instantiate(module, imports);\n this.initialized = true;\n\n if (this.config.debug) {\n console.log('✅ AgentShield WASM initialized in Edge Runtime');\n }\n } catch (error) {\n console.warn('⚠️ WASM initialization failed, using pattern detection:', error);\n this.initialized = true;\n }\n } else {\n this.initialized = true;\n }\n }\n\n private readString(ptr: number, len: number): string {\n if (!this.wasmInstance || !this.wasmMemory) {\n throw new Error('WASM not initialized');\n }\n const memory = new Uint8Array(this.wasmMemory.buffer);\n const bytes = memory.slice(ptr, ptr + len);\n return new TextDecoder().decode(bytes);\n }\n\n private writeString(str: string): [number, number] {\n if (!this.wasmInstance) {\n throw new Error('WASM not initialized');\n }\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n\n const encoded = new TextEncoder().encode(str);\n const ptr = exports.__wbindgen_malloc(encoded.length);\n\n const memory = new Uint8Array(exports.memory.buffer);\n memory.set(encoded, ptr);\n\n return [ptr, encoded.length];\n }\n\n async detect(request: NextRequest): Promise<DetectionResult> {\n if (!this.initialized) {\n await this.init();\n }\n\n const metadata = {\n userAgent: request.headers.get('user-agent') || '',\n ipAddress: getClientIp(request) || '',\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // Try WASM detection first\n if (this.wasmInstance && this.config.enableWasm !== false) {\n try {\n const exports = this.wasmInstance.exports as unknown as WasmExports;\n const [ptr, len] = this.writeString(JSON.stringify(metadata));\n\n const resultPtr = exports.detect_agent(ptr, len);\n // Read result with dynamic size\n let resultStr = '';\n let offset = 0;\n const memory = new Uint8Array((exports.memory as WebAssembly.Memory).buffer);\n\n // Read until we find the end of the JSON string\n while (offset < 4096) {\n // Max 4KB result\n const byte = memory[resultPtr + offset];\n if (byte === 0 || byte === undefined) break;\n offset++;\n }\n\n if (offset > 0) {\n resultStr = this.readString(resultPtr, offset);\n }\n\n exports.__wbindgen_free(ptr, len);\n if (offset > 0) {\n exports.__wbindgen_free(resultPtr, offset);\n }\n\n const result = JSON.parse(resultStr);\n\n const detection: DetectionResult = {\n ...result,\n verificationMethod: 'cryptographic',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected && detection.isAgent) {\n this.config.onAgentDetected(detection);\n }\n\n return detection;\n } catch (error) {\n if (this.config.debug) {\n console.error('WASM detection failed:', error);\n }\n // Fall through to pattern detection\n }\n }\n\n // Fallback: Pattern-based detection\n return this.patternDetection(metadata);\n }\n\n private patternDetection(metadata: {\n userAgent: string;\n ipAddress: string;\n headers: Record<string, string>;\n }): DetectionResult {\n const userAgent = metadata.userAgent.toLowerCase();\n\n // Enhanced AI agent patterns with confidence scores\n const patterns = [\n // High confidence - explicit AI identifiers\n { pattern: /chatgpt-user/i, name: 'ChatGPT', confidence: 0.95 },\n { pattern: /claude-web/i, name: 'Claude', confidence: 0.95 },\n { pattern: /claude-user/i, name: 'Claude', confidence: 0.95 },\n { pattern: /gpt-crawler/i, name: 'GPT Crawler', confidence: 0.95 },\n { pattern: /perplexitybot/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-user/i, name: 'Perplexity', confidence: 0.95 },\n { pattern: /perplexity-ai/i, name: 'Perplexity', confidence: 0.95 },\n\n // Medium-high confidence - company identifiers\n { pattern: /anthropic/i, name: 'Anthropic', confidence: 0.9 },\n { pattern: /openai/i, name: 'OpenAI', confidence: 0.9 },\n\n // Medium confidence - product names\n { pattern: /copilot/i, name: 'GitHub Copilot', confidence: 0.85 },\n { pattern: /bard/i, name: 'Google Bard', confidence: 0.85 },\n { pattern: /gemini/i, name: 'Google Gemini', confidence: 0.85 },\n { pattern: /perplexity/i, name: 'Perplexity', confidence: 0.85 }, // Fallback\n { pattern: /\\byou\\.com\\b/i, name: 'You.com', confidence: 0.8 },\n { pattern: /\\bphind\\b/i, name: 'Phind', confidence: 0.8 },\n ];\n\n // Check for suspicious headers\n const suspiciousHeaders = ['x-openai-', 'x-anthropic-', 'x-ai-', 'x-llm-', 'x-gpt-'];\n\n let headerBoost = 0;\n for (const [key] of Object.entries(metadata.headers)) {\n if (suspiciousHeaders.some((prefix) => key.toLowerCase().startsWith(prefix))) {\n headerBoost = 0.1;\n break;\n }\n }\n\n // Check patterns - patterns are ordered by confidence (highest first: 0.95, 0.90, 0.85...)\n // so breaking on first match returns the highest-confidence match\n for (const { pattern, name, confidence } of patterns) {\n if (pattern.test(userAgent)) {\n const finalConfidence = Math.min(confidence + headerBoost, 1.0);\n\n const result: DetectionResult = {\n isAgent: true,\n confidence: finalConfidence,\n agent: name,\n verificationMethod: 'pattern',\n riskLevel: finalConfidence > 0.9 ? 'high' : 'medium',\n timestamp: new Date().toISOString(),\n };\n\n if (this.config.onAgentDetected) {\n this.config.onAgentDetected(result);\n }\n\n return result;\n }\n }\n\n // Not detected\n return {\n isAgent: false,\n confidence: 0.85,\n verificationMethod: 'pattern',\n timestamp: new Date().toISOString(),\n };\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n getVerificationMethod(): 'cryptographic' | 'pattern' {\n return this.wasmInstance ? 'cryptographic' : 'pattern';\n }\n}\n\n/**\n * Factory function to create an AgentShield instance for Edge Runtime\n */\nexport function createEdgeAgentShield(config?: AgentShieldConfig) {\n return new EdgeRuntimeAgentShield(config);\n}\n\n/**\n * Singleton instance for simple usage\n */\nlet defaultInstance: EdgeRuntimeAgentShield | null = null;\n\nexport function getDefaultAgentShield(config?: AgentShieldConfig): EdgeRuntimeAgentShield {\n if (!defaultInstance) {\n defaultInstance = new EdgeRuntimeAgentShield(config);\n }\n return defaultInstance;\n}\n"]}
|
|
@@ -511,6 +511,7 @@ var init_edge_detector_with_wasm = __esm({
|
|
|
511
511
|
var AI_AGENT_PATTERNS = [
|
|
512
512
|
{ pattern: /chatgpt-user/i, type: "chatgpt", name: "ChatGPT" },
|
|
513
513
|
{ pattern: /claude-web/i, type: "claude", name: "Claude" },
|
|
514
|
+
{ pattern: /claude-user/i, type: "claude", name: "Claude" },
|
|
514
515
|
{ pattern: /perplexitybot/i, type: "perplexity", name: "Perplexity" },
|
|
515
516
|
{ pattern: /perplexity-user/i, type: "perplexity", name: "Perplexity" },
|
|
516
517
|
{ pattern: /perplexity/i, type: "perplexity", name: "Perplexity" },
|