Skip to content

fix: harden rate limiting behind proxies - #93

Merged
llbbl merged 1 commit into
mainfrom
fix/76-rate-limit-proxy-trust
Aug 24, 2026
Merged

fix: harden rate limiting behind proxies#93
llbbl merged 1 commit into
mainfrom
fix/76-rate-limit-proxy-trust

Conversation

@llbbl

@llbbl llbbl commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • add explicit trusted-proxy configuration for client IP resolution before applying search rate limits
  • bound in-memory limiter state derived from request traffic and cover the behavior with env, middleware, and API tests
  • document the security model and trusted deployment configuration for proxy-aware rate limiting

Changes

Bug Fixes

  • src/lib/env.ts: validate and expose trusted proxy hop configuration from environment
  • src/middleware/rateLimit.ts: resolve client IPs only through configured trusted proxies and cap request-driven bucket growth
  • src/pages/api/search.json.ts: apply the updated limiter behavior to the search endpoint

Tests

  • src/lib/env.test.ts: cover trusted proxy env parsing and validation
  • src/middleware/rateLimit.test.ts: verify proxy trust handling and bounded limiter state
  • src/pages/api/search.json.test.ts: exercise search API behavior with the hardened limiter

Documentation

  • .env.example: document the trusted proxy configuration knob
  • docs/SECURITY.md: explain proxy trust assumptions and rate-limit protections
  • src/env.d.ts: type the new environment setting

Test plan

  • Formatted 47 files in 8ms. No fixes applied.
  • Checked 48 files in 15ms. No fixes applied.
  • [x]
  • [x]
    RUN v4.1.11 /Users/loganlindquist/Web/semantic-docs
    Coverage enabled with v8

Test Files 11 passed (11)
Tests 178 passed (178)
Start at 22:31:45
Duration 3.23s (transform 607ms, setup 0ms, import 1.32s, tests 2.49s, environment 3.93s)

% Coverage report from v8
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 96.38 | 89.63 | 98.73 | 96.54 |
components | 95.5 | 90.19 | 95.45 | 95.45 |
Search.tsx | 95.18 | 89.36 | 94.73 | 95.12 | 119,124,247-248
lib | 98.03 | 90 | 100 | 98.93 |
env.ts | 96.42 | 90.62 | 100 | 96.29 | 31
markdown.ts | 96.77 | 77.27 | 100 | 100 | 13,48,57-58
middleware | 100 | 94.23 | 100 | 100 |
rateLimit.ts | 100 | 94.23 | 100 | 100 | 83,125,142
pages/api | 89.28 | 82.05 | 100 | 89.09 |
search.json.ts | 89.28 | 82.05 | 100 | 89.09 | 111,200,213-216
-------------------|---------|----------|---------|---------|-------------------

=============================== Coverage summary ===============================
Statements : 96.38% ( 320/332 )
Branches : 89.63% ( 199/222 )
Functions : 98.73% ( 78/79 )
Lines : 96.54% ( 307/318 )
================================================================================ (178 passed; 96.54% lines; limiter 100% lines)

  • [2026-08-24T03:31:50.264Z] INFO: Using local libSQL database (file:local.db)
    [2026-08-24T03:31:50.266Z] INFO: Initializing database schema...
    [2026-08-24T03:31:50.266Z] INFO: Created articles_local_384 with 384-dimension embeddings
    [2026-08-24T03:31:50.266Z] INFO: Database schema initialized successfully!
  • [2026-08-24T03:31:51.385Z] INFO: Using local libSQL database (file:local.db)
    [2026-08-24T03:31:51.387Z] INFO: Starting content indexing...
    [2026-08-24T03:31:51.394Z] INFO: [1/3] Indexing: features/semantic-search.md
    Loading local embedding model (Xenova/all-MiniLM-L6-v2)...
    Local model loaded successfully
    [2026-08-24T03:31:51.775Z] INFO: [2/3] Indexing: getting-started/welcome.md
    [2026-08-24T03:31:51.800Z] INFO: [3/3] Indexing: theme/overview.md
    [2026-08-24T03:31:51.834Z] INFO: Indexing complete!
    [2026-08-24T03:31:51.834Z] INFO: Successfully indexed 3/3 documents
  • local-env 22:31:53 [@astrojs/node] Enabling sessions with filesystem storage
    22:31:53 [types] Generated 29ms
    22:31:53 [build] output: "server"
    22:31:53 [build] mode: "server"
    22:31:53 [build] directory: /Users/loganlindquist/Web/semantic-docs/dist/
    22:31:53 [build] adapter: @astrojs/node
    22:31:53 [build] Collecting build info...
    22:31:53 [build] ✓ Completed in 70ms.
    22:31:53 [build] Building server entrypoints...
    22:31:53 [vite] ✓ built in 176ms
    22:31:53 [vite] ✓ built in 108ms
    22:31:54 [vite] ✓ built in 164ms

prerendering static routes
[ELIFECYCLE] Command failed with exit code 1.

  • Independent JS/TS review PASS

Closes #76

Only trust proxy forwarding data when the deployment explicitly
configures how many hops are safe. This keeps client IP handling
predictable and prevents request headers from widening the limiter
scope by accident.

• Bound request-derived limiter state so untrusted traffic cannot grow
  in-memory buckets without limit
• Document the trusted-proxy setting and cover the behavior with env,
  middleware, and API tests
@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.16129% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.21%. Comparing base (7696229) to head (8945ca0).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/middleware/rateLimit.ts 94.33% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #93      +/-   ##
==========================================
+ Coverage   89.33%   91.21%   +1.87%     
==========================================
  Files          12       12              
  Lines         300      330      +30     
  Branches       71       86      +15     
==========================================
+ Hits          268      301      +33     
+ Misses         16       11       -5     
- Partials       16       18       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@llbbl
llbbl merged commit dcd7abb into main Aug 24, 2026
6 checks passed
@llbbl
llbbl deleted the fix/76-rate-limit-proxy-trust branch August 24, 2026 11:25
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.

fix(security): harden search rate limiting behind proxies

1 participant