hono-honeypot 1.2.1 → 1.3.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 +16 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/ph33nx/hono-honeypot">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/ph33nx/hono-honeypot/main/assets/hero.png" alt="hono-honeypot. Block bots before they reach your routes. Zero dependencies, MIT licensed." width="100%">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
1
7
|
# hono-honeypot
|
|
2
8
|
|
|
3
9
|
Production-grade security middleware for [Hono.js](https://hono.dev). Intercepts vulnerability scanners, bot crawlers, and brute-force probes before they reach your application logic.
|
|
@@ -49,6 +55,10 @@ app.use('*', honeypot({
|
|
|
49
55
|
|
|
50
56
|
### Pattern Matching (stateless, zero-config)
|
|
51
57
|
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="https://raw.githubusercontent.com/ph33nx/hono-honeypot/main/assets/patterns.png" alt="200+ attack patterns built in. wp-admin, .env, .git, /actuator, /@fs/. Smart anchoring, no false positives." width="100%">
|
|
60
|
+
</p>
|
|
61
|
+
|
|
52
62
|
Out of the box, the middleware matches request paths against 200+ regex patterns covering:
|
|
53
63
|
|
|
54
64
|
| Category | Examples |
|
|
@@ -56,6 +66,7 @@ Out of the box, the middleware matches request paths against 200+ regex patterns
|
|
|
56
66
|
| PHP/WordPress | `*.php`, `/wp-admin`, `/xmlrpc.php`, `/wp-content/` |
|
|
57
67
|
| Admin panels | `/admin`, `/phpmyadmin`, `/cpanel`, `/cgi-bin` |
|
|
58
68
|
| CMS frameworks | `/typo3`, `/joomla`, `/drupal`, `/magento` |
|
|
69
|
+
| Magento REST API | `/rest/V1/store/storeConfigs` and store-scope variants |
|
|
59
70
|
| JS framework fingerprinting | `/_next`, `/_rsc`, `/_vercel`, `next.config.js`, `nuxt.config.ts` |
|
|
60
71
|
| Deployment configs | `serverless.yml`, `vercel.json`, `netlify.toml`, `package.json` |
|
|
61
72
|
| Docker/container | `docker-compose.yml`, `Dockerfile`, `/docker/` |
|
|
@@ -65,6 +76,7 @@ Out of the box, the middleware matches request paths against 200+ regex patterns
|
|
|
65
76
|
| SSH/auth tokens | `/.ssh/`, `/id_rsa`, `/.npmrc`, `/.pypirc` |
|
|
66
77
|
| System path traversal | `/var/task/`, `/var/log/`, `/opt/` |
|
|
67
78
|
| Command injection | `$(pwd)`, backtick injection |
|
|
79
|
+
| URL normalisation probes | Zero-width Unicode (`U+200B`, `U+FEFF` BOM, U+200C–U+200F, U+202A–U+202E directional overrides) |
|
|
68
80
|
| Log files | `*.log`, `error_log` |
|
|
69
81
|
| Java/Spring Boot | `/WEB-INF`, `/manager/html`, `/solr`, `/actuator` |
|
|
70
82
|
| Dependency manifests | `composer.json`, `Gemfile`, `requirements.txt` |
|
|
@@ -136,6 +148,10 @@ Why `410 Gone` is the default:
|
|
|
136
148
|
|
|
137
149
|
## IP Strike/Ban System
|
|
138
150
|
|
|
151
|
+
<p align="center">
|
|
152
|
+
<img src="https://raw.githubusercontent.com/ph33nx/hono-honeypot/main/assets/strike-ban.png" alt="3 strikes, 24-hour ban. Memory, Redis, or Cloudflare KV. O(1) ban check before pattern matching." width="100%">
|
|
153
|
+
</p>
|
|
154
|
+
|
|
139
155
|
Without a store, the middleware is stateless: it blocks matching paths but imposes no penalty on repeat offenders. With a store, it tracks strikes per IP and bans IPs that exceed the threshold.
|
|
140
156
|
|
|
141
157
|
**Flow:**
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var factory=require('hono/factory');var $=class{strikes=new Map;bans=new Map;strikeTTL;banTTL;constructor(i){this.strikeTTL=(i?.strikeTTL??3600)*1e3,this.banTTL=(i?.banTTL??86400)*1e3;}isBanned(i){let n=this.bans.get(i);return n===void 0?false:Date.now()>n?(this.bans.delete(i),false):true}addStrike(i){let n=Date.now(),r=this.strikes.get(i);return r&&n<r.expires?(r.count++,r.count):(this.strikes.set(i,{count:1,expires:n+this.strikeTTL}),1)}ban(i){this.bans.set(i,Date.now()+this.banTTL);}resetStrikes(i){this.strikes.delete(i);}},b=[/\.php/i,/\/config\.php/i,/\/phpinfo/i,/\/eval-stdin\.php/i,/\/xmlrpc\.php/i,/\/ALFA_DATA/i,/\/c99\.php/i,/\/r57\.php/i,/\/shell\.php/i,/\/webshell/i,/^\/wp$/i,/^\/wp-/i,/^\/wordpress/i,/\/wp-includes\//i,/\/wp-content\//i,/\/wp-admin/i,/wlwmanifest\.xml$/i,/^\/uploads?$/i,/^\/images$/i,/^\/assets$/i,/^\/files$/i,/^\/media$/i,/^\/public$/i,/\/admin\/(uploads?|images|editor|fckeditor|controller)/i,/^\/modules$/i,/^\/plugins$/i,/^\/components$/i,/^\/system$/i,/^\/template$/i,/^\/includes?$/i,/^\/vendor$/i,/^\/local$/i,/^\/php$/i,/\/fckeditor\/editor\/filemanager/i,/\/sites\/default\/files/i,/\/images\/stories/i,/\/modules\/mod_simplefileupload/i,/\/controller\/extension/i,/\/ckeditor/i,/\/tinymce/i,/\/elfinder/i,/^\/admin(\.php)?$/i,/^\/administrator/i,/^\/phpmyadmin/i,/^\/cpanel/i,/^\/whm/i,/^\/cgi-bin/i,/^\/typo3/i,/^\/joomla/i,/^\/drupal/i,/^\/magento/i,/\/\.git/i,/\/\.svn/i,/\/\.hg/i,/\/\.env/i,/\/\.sql$/i
|
|
1
|
+
'use strict';var factory=require('hono/factory');var $=class{strikes=new Map;bans=new Map;strikeTTL;banTTL;constructor(i){this.strikeTTL=(i?.strikeTTL??3600)*1e3,this.banTTL=(i?.banTTL??86400)*1e3;}isBanned(i){let n=this.bans.get(i);return n===void 0?false:Date.now()>n?(this.bans.delete(i),false):true}addStrike(i){let n=Date.now(),r=this.strikes.get(i);return r&&n<r.expires?(r.count++,r.count):(this.strikes.set(i,{count:1,expires:n+this.strikeTTL}),1)}ban(i){this.bans.set(i,Date.now()+this.banTTL);}resetStrikes(i){this.strikes.delete(i);}},b=[/\.php/i,/\/config\.php/i,/\/phpinfo/i,/\/eval-stdin\.php/i,/\/xmlrpc\.php/i,/\/ALFA_DATA/i,/\/c99\.php/i,/\/r57\.php/i,/\/shell\.php/i,/\/webshell/i,/^\/wp$/i,/^\/wp-/i,/^\/wordpress/i,/\/wp-includes\//i,/\/wp-content\//i,/\/wp-admin/i,/wlwmanifest\.xml$/i,/^\/uploads?$/i,/^\/images$/i,/^\/assets$/i,/^\/files$/i,/^\/media$/i,/^\/public$/i,/\/admin\/(uploads?|images|editor|fckeditor|controller)/i,/^\/modules$/i,/^\/plugins$/i,/^\/components$/i,/^\/system$/i,/^\/template$/i,/^\/includes?$/i,/^\/vendor$/i,/^\/local$/i,/^\/php$/i,/\/fckeditor\/editor\/filemanager/i,/\/sites\/default\/files/i,/\/images\/stories/i,/\/modules\/mod_simplefileupload/i,/\/controller\/extension/i,/\/ckeditor/i,/\/tinymce/i,/\/elfinder/i,/^\/admin(\.php)?$/i,/^\/administrator/i,/^\/phpmyadmin/i,/^\/cpanel/i,/^\/whm/i,/^\/cgi-bin/i,/^\/typo3/i,/^\/joomla/i,/^\/drupal/i,/^\/magento/i,/^\/rest\/(?:[a-z0-9_-]+\/)?v\d+(?:\/|$)/i,/\/\.git/i,/\/\.svn/i,/\/\.hg/i,/\/\.env/i,/\/\.sql$/i,/\/(vendor|node_modules)\//i,/\/\.htaccess$/i,/\/\.htpasswd$/i,/\/\.DS_Store$/i,/\/Thumbs\.db$/i,/\/\.ssh/i,/\/id_rsa/i,/\/id_ed25519/i,/\/\.npmrc$/i,/\/\.pypirc$/i,/\/\.aws\//i,/\.(bak|old|backup|orig|save|swp)$/i,/\.(7z|tgz|tar\.gz|tar|bz2|war|jar)$/i,/^\/config\.(js|json|yml|yaml|xml|ini|conf)$/i,/^\/settings\.(js|json|yml|yaml|xml)$/i,/^\/credentials\.(js|json|yml|yaml)$/i,/^\/secrets\.(js|json|yml|yaml|env)$/i,/^\/appsettings\.(json|yml|yaml)$/i,/^\/application\.(yml|yaml|xml|properties)$/i,/sftp-config\.json$/i,/ftpsync\.settings$/i,/\.ftpconfig$/i,/\.ftppass$/i,/\.remote-sync\.json$/i,/ftp-deploy\.json$/i,/^\/env\.js$/i,/^\/main\.js$/i,/^\/index\.js$/i,/^\/app\.js$/i,/^\/server-(status|info)$/i,/^\/info$/i,/^\/swagger/i,/^\/api\/swagger\.(json|yml|yaml)$/i,/^\/api-docs/i,/^\/v\d+\/api-docs/i,/^\/_env/i,/^\/env$/i,/^\/config\//i,/^\/backup/i,/^\/bk$/i,/^\/bak$/i,/^\/bac$/i,/^\/dump/i,/^\/db_/i,/^\/sql/i,/^\/shell/i,/^\/old$/i,/^\/new$/i,/^\/test$/i,/^\/demo$/i,/^\/www$/i,/^\/main$/i,/^\/site$/i,/^\/shop$/i,/^\/bc$/i,/^\/sitio$/i,/^\/sito$/i,/^\/oldsite$/i,/^\/old-site$/i,/^\/script$/i,/^\/\d{4}$/i,/^\/getcmd$/i,/\$\(/,/`/,/"/,/\{(curl|wget|bash|sh|nc|ncat|python|perl|ruby|php),/i,/\.oast\.(site|fun|live|me|online|pro)/i,/(%00|\x00)/,/[\u2000-\u203F\uFEFF]/u,/^\/storfs-asup$/i,/^\/_next/i,/^\/_rsc/i,/^\/__rsc/i,/^\/_vercel/i,/next\.config\.(js|mjs|ts)$/i,/nuxt\.config\.(js|ts)$/i,/craco\.config\.js$/i,/serverless\.(yml|yaml|json)$/i,/vercel\.json$/i,/netlify\.toml$/i,/\/helm\//i,/\/package\.json$/i,/\/composer\.(json|lock)$/i,/\/Gemfile(\.lock)?$/i,/\/requirements\.txt$/i,/docker-compose\.(yml|yaml)$/i,/Dockerfile$/i,/\/docker\//i,/^\/aws/i,/\/aws[_-]s3/i,/\/aws[_-]ses/i,/\.\.\//,/\.\.%2f/i,/\.\.%5c/i,/^\/etc\//i,/^\/proc\//i,/^\/var\//i,/^\/opt\//i,/\/passwd$/i,/\.log$/i,/\/error_log$/i,/^\/@fs\//i,/^\/@vite\//i,/^\/@id\//i,/^\/_ignition/i,/^\/__debug__/i,/\/WEB-INF/i,/^\/manager\/html/i,/^\/solr/i,/^\/actuator/i,/\/elmah\.axd$/i,/^\/servlet\//i,/bsh\.servlet/i,/^\/struts\//i,/^\/invoker\//i,/\.action$/i,/\/mailcow/i,/^\/roundcube\//i,/^\/webmail\//i,/^\/adminer/i,/^\/pma\//i,/^\/myadmin\//i,/^\/mysqladmin/i,/^\/dbadmin/i,/^\/ip$/i,/^\/proxy\.pac$/i,/^\/proxy\//i,/169\.254\.169\.254/,/^\/latest\/meta-data/i,/^\/HNAP1\//i,/^\/boaform\//i,/^\/GponForm\//i,/\.cgi$/i,/\.htm$/i,/^\/sdk$/i,/^\/websso\//i,/^\/owa\//i,/^\/aspnet_client\//i,/^\/autodiscover\//i,/^\/ecp\//i,/^\/_layouts\//i,/^\/_vti_bin\//i,/^\/WebInterface\//i,/^\/owncloud\//i,/^\/nextcloud\//i,/^\/geoserver\//i,/^\/geowebcache\//i,/^\/confluence\//i,/^\/jira\//i,/^\/grafana\//i,/^\/kibana\//i,/^\/prometheus\//i,/^\/jenkins\//i,/\/j_acegi_security_check/i,/^\/portainer\//i,/^\/gitea\//i,/^\/gitlab\//i,/^\/metrics$/i,/^\/healthz$/i,/^\/readyz$/i,/^\/livez$/i,/^\/console\//i,/^\/debug\//i,/^\/\.dockerenv$/i];function k(e){return e.req.header("cf-connecting-ip")||e.req.header("x-forwarded-for")?.split(",")[0]?.trim()||e.req.header("x-real-ip")||"unknown"}var v=(e={})=>{let i=[...b,...e.patterns||[]];e.exclude?.length&&(i=i.filter(t=>!e.exclude.some(p=>t.source===p.source)));let n=e.log??true,r=e.status??410,a=e.store,u=e.strikeThreshold??3,g=e.getIP??k,l=e.onBlocked;return factory.createMiddleware(async(t,p)=>{let s=g(t),m=s&&s!=="unknown";if(a&&m&&await a.isBanned(s)){let o=t.req.path.replace(/\/+/g,"/");return l?l({ip:s,path:o,method:t.req.method,reason:"banned"}):n&&console.log(`\u{1F6AB} Banned [${s}] ${t.req.method} ${o}`),t.body(null,r)}let d=t.req.path.replace(/\/+/g,"/");if(i.some(o=>o.test(d))){let o,c=false;if(a&&m&&(o=await a.addStrike(s),o>=u&&(await a.ban(s),await a.resetStrikes(s),c=true)),l)l({ip:s,path:d,method:t.req.method,reason:"pattern",strikes:o,banned:c});else if(n){let h=c?" \u{1F6AB} BANNED":"";console.log(`\u{1F36F} Blocked [${s}] ${t.req.method} ${d}${h}`);}return t.body(null,r)}return p()})};/**
|
|
2
2
|
* hono-honeypot - Zero-dependency security middleware for Hono.js
|
|
3
3
|
* Blocks bot attacks, vulnerability scanners, and brute-force attempts.
|
|
4
4
|
* Optional store-backed IP banning (3 strikes = 24hr ban by default).
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {createMiddleware}from'hono/factory';var $=class{strikes=new Map;bans=new Map;strikeTTL;banTTL;constructor(i){this.strikeTTL=(i?.strikeTTL??3600)*1e3,this.banTTL=(i?.banTTL??86400)*1e3;}isBanned(i){let n=this.bans.get(i);return n===void 0?false:Date.now()>n?(this.bans.delete(i),false):true}addStrike(i){let n=Date.now(),r=this.strikes.get(i);return r&&n<r.expires?(r.count++,r.count):(this.strikes.set(i,{count:1,expires:n+this.strikeTTL}),1)}ban(i){this.bans.set(i,Date.now()+this.banTTL);}resetStrikes(i){this.strikes.delete(i);}},b=[/\.php/i,/\/config\.php/i,/\/phpinfo/i,/\/eval-stdin\.php/i,/\/xmlrpc\.php/i,/\/ALFA_DATA/i,/\/c99\.php/i,/\/r57\.php/i,/\/shell\.php/i,/\/webshell/i,/^\/wp$/i,/^\/wp-/i,/^\/wordpress/i,/\/wp-includes\//i,/\/wp-content\//i,/\/wp-admin/i,/wlwmanifest\.xml$/i,/^\/uploads?$/i,/^\/images$/i,/^\/assets$/i,/^\/files$/i,/^\/media$/i,/^\/public$/i,/\/admin\/(uploads?|images|editor|fckeditor|controller)/i,/^\/modules$/i,/^\/plugins$/i,/^\/components$/i,/^\/system$/i,/^\/template$/i,/^\/includes?$/i,/^\/vendor$/i,/^\/local$/i,/^\/php$/i,/\/fckeditor\/editor\/filemanager/i,/\/sites\/default\/files/i,/\/images\/stories/i,/\/modules\/mod_simplefileupload/i,/\/controller\/extension/i,/\/ckeditor/i,/\/tinymce/i,/\/elfinder/i,/^\/admin(\.php)?$/i,/^\/administrator/i,/^\/phpmyadmin/i,/^\/cpanel/i,/^\/whm/i,/^\/cgi-bin/i,/^\/typo3/i,/^\/joomla/i,/^\/drupal/i,/^\/magento/i,/\/\.git/i,/\/\.svn/i,/\/\.hg/i,/\/\.env/i,/\/\.sql$/i
|
|
1
|
+
import {createMiddleware}from'hono/factory';var $=class{strikes=new Map;bans=new Map;strikeTTL;banTTL;constructor(i){this.strikeTTL=(i?.strikeTTL??3600)*1e3,this.banTTL=(i?.banTTL??86400)*1e3;}isBanned(i){let n=this.bans.get(i);return n===void 0?false:Date.now()>n?(this.bans.delete(i),false):true}addStrike(i){let n=Date.now(),r=this.strikes.get(i);return r&&n<r.expires?(r.count++,r.count):(this.strikes.set(i,{count:1,expires:n+this.strikeTTL}),1)}ban(i){this.bans.set(i,Date.now()+this.banTTL);}resetStrikes(i){this.strikes.delete(i);}},b=[/\.php/i,/\/config\.php/i,/\/phpinfo/i,/\/eval-stdin\.php/i,/\/xmlrpc\.php/i,/\/ALFA_DATA/i,/\/c99\.php/i,/\/r57\.php/i,/\/shell\.php/i,/\/webshell/i,/^\/wp$/i,/^\/wp-/i,/^\/wordpress/i,/\/wp-includes\//i,/\/wp-content\//i,/\/wp-admin/i,/wlwmanifest\.xml$/i,/^\/uploads?$/i,/^\/images$/i,/^\/assets$/i,/^\/files$/i,/^\/media$/i,/^\/public$/i,/\/admin\/(uploads?|images|editor|fckeditor|controller)/i,/^\/modules$/i,/^\/plugins$/i,/^\/components$/i,/^\/system$/i,/^\/template$/i,/^\/includes?$/i,/^\/vendor$/i,/^\/local$/i,/^\/php$/i,/\/fckeditor\/editor\/filemanager/i,/\/sites\/default\/files/i,/\/images\/stories/i,/\/modules\/mod_simplefileupload/i,/\/controller\/extension/i,/\/ckeditor/i,/\/tinymce/i,/\/elfinder/i,/^\/admin(\.php)?$/i,/^\/administrator/i,/^\/phpmyadmin/i,/^\/cpanel/i,/^\/whm/i,/^\/cgi-bin/i,/^\/typo3/i,/^\/joomla/i,/^\/drupal/i,/^\/magento/i,/^\/rest\/(?:[a-z0-9_-]+\/)?v\d+(?:\/|$)/i,/\/\.git/i,/\/\.svn/i,/\/\.hg/i,/\/\.env/i,/\/\.sql$/i,/\/(vendor|node_modules)\//i,/\/\.htaccess$/i,/\/\.htpasswd$/i,/\/\.DS_Store$/i,/\/Thumbs\.db$/i,/\/\.ssh/i,/\/id_rsa/i,/\/id_ed25519/i,/\/\.npmrc$/i,/\/\.pypirc$/i,/\/\.aws\//i,/\.(bak|old|backup|orig|save|swp)$/i,/\.(7z|tgz|tar\.gz|tar|bz2|war|jar)$/i,/^\/config\.(js|json|yml|yaml|xml|ini|conf)$/i,/^\/settings\.(js|json|yml|yaml|xml)$/i,/^\/credentials\.(js|json|yml|yaml)$/i,/^\/secrets\.(js|json|yml|yaml|env)$/i,/^\/appsettings\.(json|yml|yaml)$/i,/^\/application\.(yml|yaml|xml|properties)$/i,/sftp-config\.json$/i,/ftpsync\.settings$/i,/\.ftpconfig$/i,/\.ftppass$/i,/\.remote-sync\.json$/i,/ftp-deploy\.json$/i,/^\/env\.js$/i,/^\/main\.js$/i,/^\/index\.js$/i,/^\/app\.js$/i,/^\/server-(status|info)$/i,/^\/info$/i,/^\/swagger/i,/^\/api\/swagger\.(json|yml|yaml)$/i,/^\/api-docs/i,/^\/v\d+\/api-docs/i,/^\/_env/i,/^\/env$/i,/^\/config\//i,/^\/backup/i,/^\/bk$/i,/^\/bak$/i,/^\/bac$/i,/^\/dump/i,/^\/db_/i,/^\/sql/i,/^\/shell/i,/^\/old$/i,/^\/new$/i,/^\/test$/i,/^\/demo$/i,/^\/www$/i,/^\/main$/i,/^\/site$/i,/^\/shop$/i,/^\/bc$/i,/^\/sitio$/i,/^\/sito$/i,/^\/oldsite$/i,/^\/old-site$/i,/^\/script$/i,/^\/\d{4}$/i,/^\/getcmd$/i,/\$\(/,/`/,/"/,/\{(curl|wget|bash|sh|nc|ncat|python|perl|ruby|php),/i,/\.oast\.(site|fun|live|me|online|pro)/i,/(%00|\x00)/,/[\u2000-\u203F\uFEFF]/u,/^\/storfs-asup$/i,/^\/_next/i,/^\/_rsc/i,/^\/__rsc/i,/^\/_vercel/i,/next\.config\.(js|mjs|ts)$/i,/nuxt\.config\.(js|ts)$/i,/craco\.config\.js$/i,/serverless\.(yml|yaml|json)$/i,/vercel\.json$/i,/netlify\.toml$/i,/\/helm\//i,/\/package\.json$/i,/\/composer\.(json|lock)$/i,/\/Gemfile(\.lock)?$/i,/\/requirements\.txt$/i,/docker-compose\.(yml|yaml)$/i,/Dockerfile$/i,/\/docker\//i,/^\/aws/i,/\/aws[_-]s3/i,/\/aws[_-]ses/i,/\.\.\//,/\.\.%2f/i,/\.\.%5c/i,/^\/etc\//i,/^\/proc\//i,/^\/var\//i,/^\/opt\//i,/\/passwd$/i,/\.log$/i,/\/error_log$/i,/^\/@fs\//i,/^\/@vite\//i,/^\/@id\//i,/^\/_ignition/i,/^\/__debug__/i,/\/WEB-INF/i,/^\/manager\/html/i,/^\/solr/i,/^\/actuator/i,/\/elmah\.axd$/i,/^\/servlet\//i,/bsh\.servlet/i,/^\/struts\//i,/^\/invoker\//i,/\.action$/i,/\/mailcow/i,/^\/roundcube\//i,/^\/webmail\//i,/^\/adminer/i,/^\/pma\//i,/^\/myadmin\//i,/^\/mysqladmin/i,/^\/dbadmin/i,/^\/ip$/i,/^\/proxy\.pac$/i,/^\/proxy\//i,/169\.254\.169\.254/,/^\/latest\/meta-data/i,/^\/HNAP1\//i,/^\/boaform\//i,/^\/GponForm\//i,/\.cgi$/i,/\.htm$/i,/^\/sdk$/i,/^\/websso\//i,/^\/owa\//i,/^\/aspnet_client\//i,/^\/autodiscover\//i,/^\/ecp\//i,/^\/_layouts\//i,/^\/_vti_bin\//i,/^\/WebInterface\//i,/^\/owncloud\//i,/^\/nextcloud\//i,/^\/geoserver\//i,/^\/geowebcache\//i,/^\/confluence\//i,/^\/jira\//i,/^\/grafana\//i,/^\/kibana\//i,/^\/prometheus\//i,/^\/jenkins\//i,/\/j_acegi_security_check/i,/^\/portainer\//i,/^\/gitea\//i,/^\/gitlab\//i,/^\/metrics$/i,/^\/healthz$/i,/^\/readyz$/i,/^\/livez$/i,/^\/console\//i,/^\/debug\//i,/^\/\.dockerenv$/i];function k(e){return e.req.header("cf-connecting-ip")||e.req.header("x-forwarded-for")?.split(",")[0]?.trim()||e.req.header("x-real-ip")||"unknown"}var v=(e={})=>{let i=[...b,...e.patterns||[]];e.exclude?.length&&(i=i.filter(t=>!e.exclude.some(p=>t.source===p.source)));let n=e.log??true,r=e.status??410,a=e.store,u=e.strikeThreshold??3,g=e.getIP??k,l=e.onBlocked;return createMiddleware(async(t,p)=>{let s=g(t),m=s&&s!=="unknown";if(a&&m&&await a.isBanned(s)){let o=t.req.path.replace(/\/+/g,"/");return l?l({ip:s,path:o,method:t.req.method,reason:"banned"}):n&&console.log(`\u{1F6AB} Banned [${s}] ${t.req.method} ${o}`),t.body(null,r)}let d=t.req.path.replace(/\/+/g,"/");if(i.some(o=>o.test(d))){let o,c=false;if(a&&m&&(o=await a.addStrike(s),o>=u&&(await a.ban(s),await a.resetStrikes(s),c=true)),l)l({ip:s,path:d,method:t.req.method,reason:"pattern",strikes:o,banned:c});else if(n){let h=c?" \u{1F6AB} BANNED":"";console.log(`\u{1F36F} Blocked [${s}] ${t.req.method} ${d}${h}`);}return t.body(null,r)}return p()})};/**
|
|
2
2
|
* hono-honeypot - Zero-dependency security middleware for Hono.js
|
|
3
3
|
* Blocks bot attacks, vulnerability scanners, and brute-force attempts.
|
|
4
4
|
* Optional store-backed IP banning (3 strikes = 24hr ban by default).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono-honeypot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Zero-dependency honeypot middleware for Hono.js that blocks bot attacks and vulnerability scanners",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsup",
|
|
29
|
-
"test": "
|
|
29
|
+
"test": "bun test",
|
|
30
30
|
"prepublishOnly": "bun run build && bun test"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
|
@@ -55,11 +55,10 @@
|
|
|
55
55
|
"hono": "^4.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@types/bun": "^1.3.
|
|
59
|
-
"hono": "^4.
|
|
58
|
+
"@types/bun": "^1.3.13",
|
|
59
|
+
"hono": "^4.12.15",
|
|
60
60
|
"tsup": "^8.5.1",
|
|
61
|
-
"typescript": "^
|
|
62
|
-
"vitest": "^4.0.16"
|
|
61
|
+
"typescript": "^6.0.3"
|
|
63
62
|
},
|
|
64
63
|
"engines": {
|
|
65
64
|
"node": ">=18"
|