Skip to content

feat: add IP-based login brute-force protection - #531

Merged
EKKOLearnAI merged 4 commits into
EKKOLearnAI:mainfrom
cccsaber:fix/login-brute-force-protection
May 8, 2026
Merged

feat: add IP-based login brute-force protection#531
EKKOLearnAI merged 4 commits into
EKKOLearnAI:mainfrom
cccsaber:fix/login-brute-force-protection

Conversation

@cccsaber

@cccsaber cccsaber commented May 7, 2026

Copy link
Copy Markdown
Contributor
  • Per-IP rate limiting: 3 failed login attempts locks the IP for 1 hour
  • Separate counters for password login and token auth
  • Global safety net: 20 req/min, hard lock after 50 total failures
  • Persistent lock state to ~/.hermes-web-ui/.login-lock.json (survives restarts)
  • Manual unlock: edit or delete the lock file
  • Frontend handles 429/503 responses with localized error messages
  • i18n support for 8 languages

- Per-IP rate limiting: 3 failed login attempts locks the IP for 1 hour
- Separate counters for password login and token auth
- Global safety net: 20 req/min, hard lock after 50 total failures
- Persistent lock state to ~/.hermes-web-ui/.login-lock.json (survives restarts)
- Manual unlock: edit or delete the lock file
- Frontend handles 429/503 responses with localized error messages
- i18n support for 8 languages
@EKKOLearnAI

Copy link
Copy Markdown
Owner

Review 了 login-limiter.ts,有个问题:

当前没有提供手动解除锁定的 API 或管理接口。reset() 函数存在但未被任何路由调用。如果用户因误操作被锁定(比如忘记密码试了 3 次),只能:

  1. 等待锁定期自动过期(单 IP 锁 1 小时,全局锁 30 分钟)
  2. 手动删除 ~/.hermes-web-ui/.login-lock.json 并重启服务

建议增加一个管理端点来查看和移除锁定,避免用户被误锁后无法恢复。

@cccsaber

cccsaber commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

ok @EKKOLearnAI

cccsaber added 2 commits May 8, 2026 13:56
- GET /api/auth/locked-ips: list all currently locked IPs (protected)
- DELETE /api/auth/locked-ips/:ip: unlock a specific IP (protected)
- DELETE /api/auth/locked-ips: unlock all IPs (protected)
- AccountSettings: shows locked IPs with remaining time, unlock buttons
- i18n support for 8 languages
- Clean up stale .js artifacts, add .gitignore rule
- Password and token login now share IP lock state: if an IP is locked
  by either method, ALL auth methods are blocked for that IP
- Changed unlock endpoint from path param to query param (?ip=xxx) to
  support IPv6 addresses containing colons
- Merged unlockIp and unlockAll into a single handler
@cccsaber
cccsaber force-pushed the fix/login-brute-force-protection branch from c51c59d to 05509a7 Compare May 8, 2026 07:01
…inute

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@EKKOLearnAI
EKKOLearnAI merged commit 4859c32 into EKKOLearnAI:main May 8, 2026
1 check passed
mysoul12138 pushed a commit to mysoul12138/hermes-web-ui that referenced this pull request May 8, 2026
* feat: add IP-based login brute-force protection

- Per-IP rate limiting: 3 failed login attempts locks the IP for 1 hour
- Separate counters for password login and token auth
- Global safety net: 20 req/min, hard lock after 50 total failures
- Persistent lock state to ~/.hermes-web-ui/.login-lock.json (survives restarts)
- Manual unlock: edit or delete the lock file
- Frontend handles 429/503 responses with localized error messages
- i18n support for 8 languages

* feat: add locked IP management endpoint and UI

- GET /api/auth/locked-ips: list all currently locked IPs (protected)
- DELETE /api/auth/locked-ips/:ip: unlock a specific IP (protected)
- DELETE /api/auth/locked-ips: unlock all IPs (protected)
- AccountSettings: shows locked IPs with remaining time, unlock buttons
- i18n support for 8 languages
- Clean up stale .js artifacts, add .gitignore rule

* fix: cross-type IP lock and IPv6-compatible unlock route

- Password and token login now share IP lock state: if an IP is locked
  by either method, ALL auth methods are blocked for that IP
- Changed unlock endpoint from path param to query param (?ip=xxx) to
  support IPv6 addresses containing colons
- Merged unlockIp and unlockAll into a single handler

* chore: increase global login rate limit from 20 to 100 requests per minute

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: ekko <fqsy1416@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
salvia-ai-bot pushed a commit to salvia-ai-bot/hermes-web-ui that referenced this pull request May 14, 2026
* feat: add IP-based login brute-force protection

- Per-IP rate limiting: 3 failed login attempts locks the IP for 1 hour
- Separate counters for password login and token auth
- Global safety net: 20 req/min, hard lock after 50 total failures
- Persistent lock state to ~/.hermes-web-ui/.login-lock.json (survives restarts)
- Manual unlock: edit or delete the lock file
- Frontend handles 429/503 responses with localized error messages
- i18n support for 8 languages

* feat: add locked IP management endpoint and UI

- GET /api/auth/locked-ips: list all currently locked IPs (protected)
- DELETE /api/auth/locked-ips/:ip: unlock a specific IP (protected)
- DELETE /api/auth/locked-ips: unlock all IPs (protected)
- AccountSettings: shows locked IPs with remaining time, unlock buttons
- i18n support for 8 languages
- Clean up stale .js artifacts, add .gitignore rule

* fix: cross-type IP lock and IPv6-compatible unlock route

- Password and token login now share IP lock state: if an IP is locked
  by either method, ALL auth methods are blocked for that IP
- Changed unlock endpoint from path param to query param (?ip=xxx) to
  support IPv6 addresses containing colons
- Merged unlockIp and unlockAll into a single handler

* chore: increase global login rate limit from 20 to 100 requests per minute

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: ekko <fqsy1416@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
ifsherlock pushed a commit to ifsherlock/hermes-web-ui that referenced this pull request Jun 10, 2026
* feat: add IP-based login brute-force protection

- Per-IP rate limiting: 3 failed login attempts locks the IP for 1 hour
- Separate counters for password login and token auth
- Global safety net: 20 req/min, hard lock after 50 total failures
- Persistent lock state to ~/.hermes-web-ui/.login-lock.json (survives restarts)
- Manual unlock: edit or delete the lock file
- Frontend handles 429/503 responses with localized error messages
- i18n support for 8 languages

* feat: add locked IP management endpoint and UI

- GET /api/auth/locked-ips: list all currently locked IPs (protected)
- DELETE /api/auth/locked-ips/:ip: unlock a specific IP (protected)
- DELETE /api/auth/locked-ips: unlock all IPs (protected)
- AccountSettings: shows locked IPs with remaining time, unlock buttons
- i18n support for 8 languages
- Clean up stale .js artifacts, add .gitignore rule

* fix: cross-type IP lock and IPv6-compatible unlock route

- Password and token login now share IP lock state: if an IP is locked
  by either method, ALL auth methods are blocked for that IP
- Changed unlock endpoint from path param to query param (?ip=xxx) to
  support IPv6 addresses containing colons
- Merged unlockIp and unlockAll into a single handler

* chore: increase global login rate limit from 20 to 100 requests per minute

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: ekko <fqsy1416@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants