mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 10:59:32 +01:00
fix: apply the review items for #684 at merge
Multi-user: add a (username, IP) failure bucket checked before verifyPassword, capped at AUTH_FAILURE_MAX, with the same decay as the other buckets; the per-IP pre-gate stays at AUTH_IP_FAILURE_MAX and the per-username bucket stays after the verify A correct password now also clears that account's (username, IP) bucket, beside the IP and per-username buckets The new bucket is disposed on server stop like the others; the comments above the gate and the constants' JSDoc describe the three buckets Tests: 10 wrong then the correct password from one IP is a 429, the same account logs in from another IP, another account behind that IP is unaffected, and a correct password clears the pair bucket test/multiuser-auth.test.ts: the spray test loops to AUTH_IP_FAILURE_MAX instead of a literal 50 Reworded the rate-limit lines in auth-config.ts, security-architecture.md, README.md, README.zh-CN.md, wiki/Security.md, endpoints.md (plus the plugin mirror), CLAUDE.md and architecture-invariants.md docs/wiki/Remote-Access.md: add the multi-user note to the tunnel page Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
175e3b8320
commit
b7897b6d0e
13 files changed
+173
-49
No files matched your search
@@ -457,6 +457,7 @@ export class WebServer extends EventEmitter {
|
||||
private qrAuthFailures: StaleExpirationMap<string, number> | null = null;
|
||||
private hookSecretFailures: StaleExpirationMap<string, number> | null = null;
|
||||
private userFailures: StaleExpirationMap<string, number> | null = null;
|
||||
private userIpFailures: StaleExpirationMap<string, number> | null = null;
|
||||
private pushStore: PushSubscriptionStore = new PushSubscriptionStore();
|
||||
/** ntfy / Slack / Discord / generic webhook for the push events; config in webhook.json (0600). */
|
||||
private webhookNotifier = new WebhookNotifier(() => readWebhookConfig(getDataDir()), webviewFetch);
|
||||
@@ -959,6 +960,7 @@ export class WebServer extends EventEmitter {
|
||||
this.qrAuthFailures = authState.qrAuthFailures;
|
||||
this.hookSecretFailures = authState.hookSecretFailures;
|
||||
this.userFailures = authState.userFailures;
|
||||
this.userIpFailures = authState.userIpFailures;
|
||||
}
|
||||
|
||||
// WebSocket support (terminal I/O — low-latency bidirectional channel)
|
||||
@@ -4324,6 +4326,10 @@ export class WebServer extends EventEmitter {
|
||||
this.userFailures.dispose();
|
||||
this.userFailures = null;
|
||||
}
|
||||
if (this.userIpFailures) {
|
||||
this.userIpFailures.dispose();
|
||||
this.userIpFailures = null;
|
||||
}
|
||||
this.activePlanOrchestrators.clear();
|
||||
this.cleaningUp.clear();
|
||||
this.killingSessions.clear();
|
||||
|
||||
Reference in new issue
Block a user