LibreChat/api/server/middleware/limiters
Danny Avila 09da878a47
🚰 fix: Throttle Shared Link Reads and Aggregate Audit Findings (#15605)
* 🪵 fix: Aggregate Audit Findings and Rate Limit Shared Link Reads

Audit-mode content filter rules wrote one `logger.info` per matching
fragment, and inspection deliberately continues past every finding. A
shared conversation full of distinct matching strings therefore produced
one log write per fragment, regenerated on every retrieval of
`GET /api/share/:shareId` — a public, unauthenticated route with no
limiter. The 4,096-entry inspection dedupe set is a memory bound, not an
event budget: once full, further values are inspected and logged again.

Audit metadata carries no inspected text — only rule, source, field and
provenance — so thousands of those writes were byte-identical lines.
Findings are now counted inside an aggregation scope and reported once
per distinct key with an `occurrences` count when the scope ends:

- `assertModelBoundContent` opens a scope when audit rules are configured,
  bounding one inspection pass (a single message's fragments).
- `assertConversationImportContentAllowed` opens the outer scope for
  import and shared-link snapshots, so per-message inspections nest into
  one report instead of one per message.
- `createShareContentPreflight` spans the shared-file metadata pass too.

Nested scopes reuse the outermost aggregation, and outside any scope the
previous immediate write is kept.

`GET /api/share/:shareId` re-inspects the whole snapshot on every request,
so it now carries IP and user limiters like the neighbouring fork route
(`SHARE_IP_MAX`/`SHARE_IP_WINDOW`, `SHARE_USER_MAX`/`SHARE_USER_WINDOW`,
`SHARE_VIOLATION_SCORE`); the user limiter skips anonymous viewers.

* 🔒 fix: Address Codex Findings on Share Audit Aggregation

- The aggregation key joined rule fields with a space, but the filter
  schema allows spaces in custom pattern ids and labels, so
  `{id: 'a', label: 'b c'}` and `{id: 'a b', label: 'c'}` collided on the
  same source/field/provenance and merged two rules' counts under one
  identity. Serialize the tuple instead.
- `SHARE_VIOLATION_SCORE` left unset reached `logViolation` as
  `undefined`, which selects that function's default score of 1 rather
  than the documented zero. With default ban settings a viewer refreshing
  a rate-limited shared link would be banned after 20 rejections. Default
  the score to 0 in code, not only in `.env.example`.
- `removePorts` returns a full IPv6 address, so an attacker holding a
  prefix could rotate the host portion for a fresh bucket on every
  request — and for anonymous viewers the IP limiter is the only bound.
  Derive the key through `ipKeyGenerator` so IPv6 clients group by /56.
2026-09-04 12:38:34 -04:00
..
code.js 🛫 feat: Enable Self-Service Code Worker Pairing (#15367) 2026-09-01 18:46:33 -04:00
code.spec.js 🛫 feat: Enable Self-Service Code Worker Pairing (#15367) 2026-09-01 18:46:33 -04:00
forkLimiters.js
importLimiters.js
index.js 🚰 fix: Throttle Shared Link Reads and Aggregate Audit Findings (#15605) 2026-09-04 12:38:34 -04:00
loginLimiter.js 🔐 fix: Redirect OAuth Browser Navigations Instead of Rendering JSON (#15440) 2026-08-31 21:13:47 -04:00
loginLimiter.spec.js 🔐 fix: Redirect OAuth Browser Navigations Instead of Rendering JSON (#15440) 2026-08-31 21:13:47 -04:00
messageLimiters.js 🛑 fix: Separate Agent Event Backpressure From User Bans (#15200) 2026-08-25 09:27:35 -04:00
messageLimiters.spec.js 🛑 fix: Separate Agent Event Backpressure From User Bans (#15200) 2026-08-25 09:27:35 -04:00
promptUsageLimiter.js
registerLimiter.js
resetPasswordLimiter.js
resetPasswordSubmissionLimiter.js
shareLimiters.js 🚰 fix: Throttle Shared Link Reads and Aggregate Audit Findings (#15605) 2026-09-04 12:38:34 -04:00
shareLimiters.spec.js 🚰 fix: Throttle Shared Link Reads and Aggregate Audit Findings (#15605) 2026-09-04 12:38:34 -04:00
sttLimiters.js
toolCallLimiter.js
ttsLimiters.js
twoFactorTempLimiter.js
twoFactorTempLimiter.test.js
uploadLimiters.js 🔒 fix: Bound /files/usage TTL Hold Instead of Clearing It (#14470) 2026-07-28 07:37:26 -04:00
verifyEmailLimiter.js
verifyEmailSubmissionLimiter.js