nextjs-secure 0.6.0 → 0.7.0

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
6
  [![Next.js](https://img.shields.io/badge/Next.js-13+-black.svg)](https://nextjs.org/)
7
- [![Tests](https://img.shields.io/badge/tests-467%20passing-brightgreen.svg)]()
7
+ [![Tests](https://img.shields.io/badge/tests-568%20passing-brightgreen.svg)]()
8
8
 
9
9
  Production-ready security middleware for Next.js 13+ App Router. Zero config, maximum protection.
10
10
 
@@ -52,6 +52,7 @@ pnpm add nextjs-secure
52
52
  - [Authentication](#authentication)
53
53
  - [Input Validation](#input-validation)
54
54
  - [Audit Logging](#audit-logging)
55
+ - [Bot Detection](#bot-detection)
55
56
  - [Utilities](#utilities)
56
57
  - [API Reference](#api-reference)
57
58
  - [Examples](#examples)
@@ -800,6 +801,170 @@ const structuredFormatter = new StructuredFormatter({
800
801
 
801
802
  ---
802
803
 
804
+ ## Bot Detection
805
+
806
+ Protect your endpoints from automated bots, scrapers, and spam.
807
+
808
+ ### Basic Usage
809
+
810
+ ```typescript
811
+ import { withBotProtection } from 'nextjs-secure/bot'
812
+
813
+ export const POST = withBotProtection(handler, {
814
+ userAgent: {
815
+ blockAllBots: false,
816
+ allowList: ['Googlebot', 'Bingbot'],
817
+ },
818
+ honeypot: true,
819
+ behavior: {
820
+ maxRequestsPerSecond: 10,
821
+ },
822
+ })
823
+ ```
824
+
825
+ ### Presets
826
+
827
+ ```typescript
828
+ import { withBotProtectionPreset } from 'nextjs-secure/bot'
829
+
830
+ // Relaxed: Only blocks obvious bots
831
+ export const GET = withBotProtectionPreset(handler, 'relaxed')
832
+
833
+ // Standard: Good balance (default)
834
+ export const GET = withBotProtectionPreset(handler, 'standard')
835
+
836
+ // Strict: Maximum protection
837
+ export const GET = withBotProtectionPreset(handler, 'strict')
838
+
839
+ // API: Optimized for API endpoints
840
+ export const GET = withBotProtectionPreset(handler, 'api')
841
+ ```
842
+
843
+ ### User-Agent Detection
844
+
845
+ ```typescript
846
+ import { withUserAgentProtection, analyzeUserAgent, KNOWN_BOT_PATTERNS } from 'nextjs-secure/bot'
847
+
848
+ // Middleware
849
+ export const GET = withUserAgentProtection(handler, {
850
+ blockAllBots: true,
851
+ allowCategories: ['search_engine', 'social_media'],
852
+ allowList: ['Googlebot', 'Twitterbot'],
853
+ blockList: ['BadBot'],
854
+ })
855
+
856
+ // Manual detection
857
+ const result = analyzeUserAgent('Googlebot/2.1')
858
+ // { isBot: true, category: 'search_engine', name: 'Googlebot', confidence: 0.95 }
859
+ ```
860
+
861
+ ### Honeypot Protection
862
+
863
+ ```typescript
864
+ import { withHoneypotProtection, generateHoneypotHTML, generateHoneypotCSS } from 'nextjs-secure/bot'
865
+
866
+ // Middleware
867
+ export const POST = withHoneypotProtection(handler, {
868
+ fieldName: '_hp_email',
869
+ additionalFields: ['_hp_name', '_hp_phone'],
870
+ })
871
+
872
+ // Generate HTML for forms
873
+ const honeypotHTML = generateHoneypotHTML({ fieldName: '_hp_email' })
874
+ // Returns hidden input fields
875
+
876
+ // Generate CSS
877
+ const honeypotCSS = generateHoneypotCSS({ fieldName: '_hp_email' })
878
+ // Returns CSS to hide fields
879
+ ```
880
+
881
+ ### Behavior Analysis
882
+
883
+ ```typescript
884
+ import { withBehaviorProtection, MemoryBehaviorStore } from 'nextjs-secure/bot'
885
+
886
+ const store = new MemoryBehaviorStore()
887
+
888
+ export const GET = withBehaviorProtection(handler, {
889
+ store,
890
+ minRequestInterval: 100, // Min ms between requests
891
+ maxRequestsPerSecond: 10, // Max requests per second
892
+ patterns: {
893
+ sequentialAccess: true, // Detect sequential URL patterns
894
+ regularTiming: true, // Detect bot-like timing
895
+ missingHeaders: true, // Detect missing browser headers
896
+ },
897
+ })
898
+ ```
899
+
900
+ ### CAPTCHA Integration
901
+
902
+ ```typescript
903
+ import { withCaptchaProtection, verifyCaptcha } from 'nextjs-secure/bot'
904
+
905
+ // reCAPTCHA v3
906
+ export const POST = withCaptchaProtection(handler, {
907
+ provider: 'recaptcha-v3',
908
+ siteKey: process.env.RECAPTCHA_SITE_KEY,
909
+ secretKey: process.env.RECAPTCHA_SECRET_KEY,
910
+ threshold: 0.5,
911
+ })
912
+
913
+ // hCaptcha
914
+ export const POST = withCaptchaProtection(handler, {
915
+ provider: 'hcaptcha',
916
+ siteKey: process.env.HCAPTCHA_SITE_KEY,
917
+ secretKey: process.env.HCAPTCHA_SECRET_KEY,
918
+ })
919
+
920
+ // Cloudflare Turnstile
921
+ export const POST = withCaptchaProtection(handler, {
922
+ provider: 'turnstile',
923
+ siteKey: process.env.TURNSTILE_SITE_KEY,
924
+ secretKey: process.env.TURNSTILE_SECRET_KEY,
925
+ })
926
+
927
+ // Manual verification
928
+ const result = await verifyCaptcha(token, {
929
+ provider: 'recaptcha-v3',
930
+ secretKey: process.env.RECAPTCHA_SECRET_KEY,
931
+ })
932
+ ```
933
+
934
+ ### Manual Bot Detection
935
+
936
+ ```typescript
937
+ import { detectBot } from 'nextjs-secure/bot'
938
+
939
+ const result = await detectBot(request, {
940
+ userAgent: { blockAllBots: true },
941
+ honeypot: true,
942
+ behavior: { maxRequestsPerSecond: 10 },
943
+ })
944
+
945
+ if (result.isBot) {
946
+ console.log(`Bot detected: ${result.reason}`)
947
+ console.log(`Category: ${result.category}`)
948
+ console.log(`Confidence: ${result.confidence}`)
949
+ }
950
+ ```
951
+
952
+ ### Bot Categories
953
+
954
+ | Category | Examples |
955
+ |----------|----------|
956
+ | `search_engine` | Googlebot, Bingbot, Yandex |
957
+ | `social_media` | Twitterbot, FacebookBot, LinkedInBot |
958
+ | `ai_crawler` | GPTBot, Claude-Web, Anthropic |
959
+ | `monitoring` | UptimeRobot, Pingdom |
960
+ | `feed_reader` | Feedly, Feedbin |
961
+ | `preview` | Slackbot, Discord |
962
+ | `scraper` | Scrapy, DataMiner |
963
+ | `spam` | Spam bots, malicious crawlers |
964
+ | `unknown` | Unidentified automated traffic |
965
+
966
+ ---
967
+
803
968
  ## Utilities
804
969
 
805
970
  ### Duration Parsing
@@ -904,6 +1069,24 @@ isLocalhost('127.0.0.1') // true
904
1069
  | `trackSecurityEvent(store, event)` | Track single event |
905
1070
  | `redactObject(obj, config)` | Redact PII from object |
906
1071
 
1072
+ ### Bot Detection
1073
+
1074
+ | Function | Description |
1075
+ |----------|-------------|
1076
+ | `withBotProtection(handler, config)` | Combined bot protection |
1077
+ | `withUserAgentProtection(handler, config)` | User-agent only protection |
1078
+ | `withHoneypotProtection(handler, config)` | Honeypot only protection |
1079
+ | `withBehaviorProtection(handler, config)` | Behavior analysis only |
1080
+ | `withCaptchaProtection(handler, config)` | CAPTCHA verification |
1081
+ | `withBotProtectionPreset(handler, preset)` | Use preset configuration |
1082
+ | `detectBot(request, config)` | Manual bot detection |
1083
+ | `analyzeUserAgent(userAgent, config)` | Analyze user-agent string |
1084
+ | `checkHoneypot(request, config)` | Check honeypot fields |
1085
+ | `checkBehavior(request, config)` | Check request behavior |
1086
+ | `verifyCaptcha(token, config)` | Verify CAPTCHA token |
1087
+ | `generateHoneypotHTML(config)` | Generate honeypot HTML |
1088
+ | `generateHoneypotCSS(config)` | Generate honeypot CSS |
1089
+
907
1090
  ---
908
1091
 
909
1092
  ## Examples
@@ -1008,6 +1191,7 @@ export async function GET(req) {
1008
1191
  - [x] **v0.4.0** - Authentication
1009
1192
  - [x] **v0.5.0** - Input Validation
1010
1193
  - [x] **v0.6.0** - Audit Logging
1194
+ - [x] **v0.7.0** - Bot Detection
1011
1195
 
1012
1196
  See [ROADMAP.md](ROADMAP.md) for detailed progress and future plans.
1013
1197