-
Notifications
You must be signed in to change notification settings - Fork 51
Security hardening and code quality fixes #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||
| import type { Context, Next } from 'hono'; | ||||||||||||||||
| import type { Context, Next } from "hono"; | ||||||||||||||||
|
|
||||||||||||||||
| interface RateLimitEntry { | ||||||||||||||||
| count: number; | ||||||||||||||||
|
|
@@ -18,8 +18,12 @@ export function rateLimiter(maxRequests = 60, windowMs = 60_000) { | |||||||||||||||
| }, windowMs).unref(); | ||||||||||||||||
|
|
||||||||||||||||
| return async (c: Context, next: Next): Promise<Response | void> => { | ||||||||||||||||
| const forwardedFor = c.req.header('x-forwarded-for'); | ||||||||||||||||
| const ip = (forwardedFor?.split(',')[0]?.trim()) || c.req.header('x-real-ip') || 'unknown'; | ||||||||||||||||
| const xRealIp = c.req.header("x-real-ip"); | ||||||||||||||||
| const forwarded = c.req.header("x-forwarded-for"); | ||||||||||||||||
| const forwardedIp = forwarded | ||||||||||||||||
| ? forwarded.split(",").at(-1)?.trim() | ||||||||||||||||
| : undefined; | ||||||||||||||||
|
Comment on lines
+23
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Rate limiter extracts proxy IP instead of client IP from X-Forwarded-For The rate limiter uses Root Cause and ImpactThe This means:
The old code: const ip = (forwardedFor?.split(',')[0]?.trim()) || c.req.header('x-real-ip') || 'unknown';The new code: const forwardedIp = forwarded ? forwarded.split(",").at(-1)?.trim() : undefined;
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||
| const ip = xRealIp || forwardedIp || "unknown"; | ||||||||||||||||
| const now = Date.now(); | ||||||||||||||||
|
|
||||||||||||||||
| let entry = windows.get(ip); | ||||||||||||||||
|
|
@@ -30,12 +34,21 @@ export function rateLimiter(maxRequests = 60, windowMs = 60_000) { | |||||||||||||||
|
|
||||||||||||||||
| entry.count++; | ||||||||||||||||
|
|
||||||||||||||||
| c.header('X-RateLimit-Limit', String(maxRequests)); | ||||||||||||||||
| c.header('X-RateLimit-Remaining', String(Math.max(0, maxRequests - entry.count))); | ||||||||||||||||
| c.header('X-RateLimit-Reset', String(Math.ceil(entry.resetAt / 1000))); | ||||||||||||||||
| c.header("X-RateLimit-Limit", String(maxRequests)); | ||||||||||||||||
| c.header( | ||||||||||||||||
| "X-RateLimit-Remaining", | ||||||||||||||||
| String(Math.max(0, maxRequests - entry.count)), | ||||||||||||||||
| ); | ||||||||||||||||
| c.header("X-RateLimit-Reset", String(Math.ceil(entry.resetAt / 1000))); | ||||||||||||||||
|
|
||||||||||||||||
| if (entry.count > maxRequests) { | ||||||||||||||||
| return c.json({ error: 'Too many requests', retryAfter: Math.ceil((entry.resetAt - now) / 1000) }, 429); | ||||||||||||||||
| return c.json( | ||||||||||||||||
| { | ||||||||||||||||
| error: "Too many requests", | ||||||||||||||||
| retryAfter: Math.ceil((entry.resetAt - now) / 1000), | ||||||||||||||||
| }, | ||||||||||||||||
| 429, | ||||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| await next(); | ||||||||||||||||
|
|
||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.