Skip to content

(feat): secure Gemini API architecture and harden AI prompt pipeline#51

Open
vraj826 wants to merge 4 commits into
nirvik34:mainfrom
vraj826:feat/secure-server-side-gemini-router
Open

(feat): secure Gemini API architecture and harden AI prompt pipeline#51
vraj826 wants to merge 4 commits into
nirvik34:mainfrom
vraj826:feat/secure-server-side-gemini-router

Conversation

@vraj826
Copy link
Copy Markdown

@vraj826 vraj826 commented May 25, 2026

Description

Fixes #49

Implements a secure server-side AI architecture for Gitbun by migrating Gemini inference behind a protected Next.js API route and hardening the AI prompt pipeline against injection and abuse vectors.

Changes Made

  • Added secure /api/generate server route
  • Removed client-side Gemini API exposure
  • Replaced NEXT_PUBLIC_GEMINI_API_KEY with server-only GEMINI_API_KEY
  • Added prompt sanitization and validation layers
  • Added in-memory IP rate limiting
  • Improved AI failure fallback handling
  • Added Vitest coverage for validation, sanitization, API routes, and rate limiting

Screenshots

Secure server-side Gemini routing

Frontend requests are routed through /api/generate, ensuring Gemini API credentials remain server-side and are never exposed to the browser bundle.

Screenshot 2026-05-25 222634

Request validation using Zod schemas

Malformed and empty payloads are rejected before reaching the AI pipeline.

Screenshot 2026-05-25 221859

Prompt injection safeguards

Unsafe instruction override attempts are intercepted and safely handled through the secured AI pipeline.

Screenshot 2026-05-25 221824

Oversized payload protection

Large payloads are blocked through validation and sanitization safeguards to reduce abuse risks.

Screenshot 2026-05-25 221925

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Documentation update
  • Frontend styling/component update

GSSoC '26 Contribution Details

Please select only one difficulty level that was assigned to you in the issue:

  • level:beginner

  • level:intermediate

  • level:advanced

  • level:critical

  • I have been assigned to this issue by a maintainer. (PRs without prior assignment will not count toward GSSoC).

How Has This Been Tested?

  • npm test passes locally
  • npm run lint passes without errors
  • I ran the CLI locally using npm run dev and verified the output

Verification

npm.cmd test
npm.cmd exec tsc -- --noEmit
npm.cmd run build

Result:

  • 5 test files
  • 18 tests passed

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas

Summary by CodeRabbit

  • New Features

    • Gemini access now goes through a server-side API; API key must remain server-side
    • Request rate limiting to reduce abuse
    • Prompt sanitization to mitigate injection attempts
    • Automatic fallback to rule-based commit generation when AI is unavailable
    • Stronger request/response validation with clearer error responses
  • Tests

    • Expanded test coverage and added Vitest configuration
  • Chores

    • Added zod and vitest, added a test script, and updated README configuration notes

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 25, 2026

@vraj826 is attempting to deploy a commit to the nirvik34's projects Team on Vercel.

A member of the Team first needs to authorize it.

@vraj826
Copy link
Copy Markdown
Author

vraj826 commented May 25, 2026

@nirvik34 The PR is ready to be reviewed.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Warning

Review limit reached

@vraj826, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 58 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 50e06f34-2909-4395-9fae-6709f2c475fe

📥 Commits

Reviewing files that changed from the base of the PR and between 0edbd5a and 97b627c.

📒 Files selected for processing (1)
  • frontend/src/lib/rateLimit.ts

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid option: expected one of "chill"|"assertive" at "reviews.profile"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

Moves Gemini inference to a server-side Next.js POST route (/api/generate), adds Zod validation, prompt sanitization, an in-memory rate limiter, client adapter changes with fallback logic, and tests plus Vitest configuration.

Changes

Secure Server-Side Gemini Architecture

Layer / File(s) Summary
Validation schemas and tests
frontend/src/lib/validation.ts, frontend/src/lib/validation.test.ts
Zod schemas define generate request shape, commit-result constraints, success/error responses, and inferred TS types; tests exercise valid/invalid cases and safe-default normalization.
Prompt sanitization and tests
frontend/src/lib/sanitizePrompt.ts, frontend/src/lib/sanitizePrompt.test.ts
Regex-based sanitization removes control characters, normalizes whitespace/blank lines, replaces instruction-override phrases with a placeholder, truncates to MAX_PROMPT_LENGTH, and formats untrusted prompt blocks; tests verify normalization, injection filtering, and truncation.
Rate limiter and tests
frontend/src/lib/rateLimit.ts, frontend/src/lib/rateLimit.test.ts
Module-level Map-backed per-identifier rate limiter with env-configurable windowMs, maxRequests, and cooldownMs, proxy-aware client identifier resolution, bucket cleanup, checkRateLimit/resetRateLimit, and tests for allow/block/retry-after/cooldown behaviors.
Server-side API route and tests
frontend/src/app/api/generate/route.ts, frontend/src/app/api/generate/route.test.ts
POST validates payload via Zod, enforces IP-based rate limiting and server-only GEMINI_API_KEY, sanitizes prompt, calls Gemini with timeout/abort, parses/validates model JSON, and returns structured responses; GET returns 405. Tests cover success, prompt-injection sanitization, validation errors, method handling, missing config, and proxy-aware rate-limiting.
Client adapter and fallback logic
frontend/src/lib/gemini.ts, frontend/src/lib/generateCommit.ts, frontend/src/lib/generateCommit.test.ts
callGemini now POSTs to /api/generate, validates the API response, and throws GenerateApiError for invalid/unavailable responses; generateCommit conditionally falls back to rule-based generation for network/config/invalid-response errors; tests cover fallback and error propagation.
Project config and docs
frontend/package.json, frontend/vitest.config.ts, frontend/README.md
Adds vitest script and dependency, adds zod dependency, configures Vitest (@ path alias, node env), and updates README to require server-side GEMINI_API_KEY and mention new lib/ modules.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

level:intermediate, quality:clean, gssoc:approved, mentor:nirvik34

Poem

🐰 I hop to clean the prompt and gate the key,
Server-side whispers keep secrets free.
Rate limits guard the rolling tide,
Tests and schemas walk beside.
A tidy spring — secure commits for thee.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main security-focused changes: moving Gemini to server-side and hardening the prompt pipeline against injection attacks.
Linked Issues check ✅ Passed All key objectives from issue #49 are implemented: server-side /api/generate route, server-only GEMINI_API_KEY, prompt sanitization, rate limiting, Zod validation, and improved fallback handling.
Out of Scope Changes check ✅ Passed All changes are directly aligned with securing the Gemini architecture and hardening the prompt pipeline. No unrelated modifications detected in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
frontend/src/app/api/generate/route.test.ts (1)

106-127: ⚡ Quick win

Add a multi-hop/forged forwarding-header regression test.

Given IP-based throttling, add a case with crafted x-forwarded-for chains to lock expected identifier behavior and prevent future bypass regressions.

Also applies to: 130-136

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/app/api/generate/route.test.ts` around lines 106 - 127, Add a
new test that verifies IP-based throttling cannot be bypassed by forged
X-Forwarded-For chains: call the exported POST handler (imported from "./route")
twice with the same effective client identifier but different X-Forwarded-For
header values (e.g., a multi-hop comma-separated list like "203.0.113.10,
198.51.100.5") and assert the second call is rate-limited (status 429 and
Retry-After "60") after setting AI_RATE_LIMIT_MAX and AI_RATE_LIMIT_COOLDOWN_MS;
reuse the existing request(...) helper and generateContentMock setup so this
regression test ensures the route's rate-limit logic uses the intended IP from
the X-Forwarded-For chain.
frontend/src/lib/rateLimit.test.ts (1)

26-31: ⚡ Quick win

Add a regression test for cooldownMs > windowMs.

Current tests won’t catch the cooldown-bypass edge case. Add one case that exceeds the limit, advances past windowMs but not cooldownMs, and still expects allowed: false.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/rateLimit.test.ts` around lines 26 - 31, Add a regression
test in rateLimit.test.ts that exercises the cooldown>window edge-case: call
checkRateLimit("127.0.0.1", 0, config) to consume the allowed request, then call
checkRateLimit again at a timestamp greater than windowMs but less than
cooldownMs and assert allowed is false; use the existing checkRateLimit function
name and a config such as { windowMs: 500, maxRequests: 1, cooldownMs: 1_000 }
and name the spec something like "respects cooldown when cooldownMs > windowMs"
so it fails if cooldown is incorrectly bypassed after window expiry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/app/api/generate/route.ts`:
- Around line 108-110: The getClientIdentifier function currently trusts
x-forwarded-for directly which is spoofable; change it to prefer a
server-derived address (e.g., connection remote address /
request.socket.remoteAddress or framework-provided trusted client IP) and only
accept x-forwarded-for when you explicitly trust a proxy (controlled by a config
flag like PROXY_TRUSTED); validate the chosen value as a proper IP (IPv4/IPv6)
and fall back to x-real-ip or "anonymous" only after these checks. Ensure you
update getClientIdentifier to check an env/config flag before reading
x-forwarded-for, parse and validate the first entry if used, and otherwise use
the server-side remote address so per-IP rate limiting isn’t bypassable.
- Around line 67-71: generateWithGemini currently calls
model.generateContent(...) with no timeout or cancellation; update
generateWithGemini to create an AbortController, pass a RequestOptions object to
model.generateContent(prompt, { timeout: <reasonable ms>, signal:
controller.signal }) and ensure you clear/abort the controller on timeout or
when the request finishes (pick e.g. 15000 ms). Also change getClientIdentifier
to stop trusting the first token of the x-forwarded-for header for
rate-limiting; use the transport-level address (e.g., req.socket.remoteAddress
or connection.remoteAddress) as the primary client identifier and only consider
x-forwarded-for when you explicitly trust the proxy chain, to prevent client IP
spoofing.

In `@frontend/src/lib/rateLimit.ts`:
- Around line 38-40: The bucket reset logic currently resets based on resetAt
before checking cooldown, allowing a client with blockedUntil > now to bypass
the cooldown when config.cooldownMs > config.windowMs; update the logic around
the const bucket assignment (using variables existing, now, config.windowMs,
cooldownMs, and the bucket.blockedUntil field) to first check if
existing?.blockedUntil > now and keep the existing bucket (do not reset) while
still honoring resetAt otherwise; apply the same change to the analogous logic
in the block handling code referenced (the section around lines 42-49) so
blockedUntil is always respected before any reset.

---

Nitpick comments:
In `@frontend/src/app/api/generate/route.test.ts`:
- Around line 106-127: Add a new test that verifies IP-based throttling cannot
be bypassed by forged X-Forwarded-For chains: call the exported POST handler
(imported from "./route") twice with the same effective client identifier but
different X-Forwarded-For header values (e.g., a multi-hop comma-separated list
like "203.0.113.10, 198.51.100.5") and assert the second call is rate-limited
(status 429 and Retry-After "60") after setting AI_RATE_LIMIT_MAX and
AI_RATE_LIMIT_COOLDOWN_MS; reuse the existing request(...) helper and
generateContentMock setup so this regression test ensures the route's rate-limit
logic uses the intended IP from the X-Forwarded-For chain.

In `@frontend/src/lib/rateLimit.test.ts`:
- Around line 26-31: Add a regression test in rateLimit.test.ts that exercises
the cooldown>window edge-case: call checkRateLimit("127.0.0.1", 0, config) to
consume the allowed request, then call checkRateLimit again at a timestamp
greater than windowMs but less than cooldownMs and assert allowed is false; use
the existing checkRateLimit function name and a config such as { windowMs: 500,
maxRequests: 1, cooldownMs: 1_000 } and name the spec something like "respects
cooldown when cooldownMs > windowMs" so it fails if cooldown is incorrectly
bypassed after window expiry.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6090d198-8b54-484c-996f-edffbaeb78fe

📥 Commits

Reviewing files that changed from the base of the PR and between cc91567 and 63bd3b6.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • frontend/README.md
  • frontend/package.json
  • frontend/src/app/api/generate/route.test.ts
  • frontend/src/app/api/generate/route.ts
  • frontend/src/lib/gemini.ts
  • frontend/src/lib/generateCommit.test.ts
  • frontend/src/lib/generateCommit.ts
  • frontend/src/lib/rateLimit.test.ts
  • frontend/src/lib/rateLimit.ts
  • frontend/src/lib/sanitizePrompt.test.ts
  • frontend/src/lib/sanitizePrompt.ts
  • frontend/src/lib/validation.test.ts
  • frontend/src/lib/validation.ts
  • frontend/vitest.config.ts

Comment thread frontend/src/app/api/generate/route.ts Outdated
Comment thread frontend/src/app/api/generate/route.ts Outdated
Comment thread frontend/src/lib/rateLimit.ts Outdated
@vraj826
Copy link
Copy Markdown
Author

vraj826 commented May 26, 2026

@nirvik34 any updates on the PR?

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/app/api/generate/route.ts`:
- Around line 136-137: The code currently trusts the x-real-ip header
unconditionally; update the IP extraction in generate/route.ts so that you only
read and validate request.headers.get("x-real-ip") (variable realIp) when the
proxy-trust flag (e.g., PROXY_TRUSTED or equivalent env/config) is enabled; if
proxy trust is disabled, do not use header-based IPs and return "anonymous"
instead, ensuring isValidIp(realIp) is only called inside the proxy-trust branch
and all header-based logic is gated by the proxy flag.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 436ad367-be7d-401c-bd02-249f81351b79

📥 Commits

Reviewing files that changed from the base of the PR and between 63bd3b6 and 09306ac.

📒 Files selected for processing (4)
  • frontend/src/app/api/generate/route.test.ts
  • frontend/src/app/api/generate/route.ts
  • frontend/src/lib/rateLimit.test.ts
  • frontend/src/lib/rateLimit.ts

Comment thread frontend/src/app/api/generate/route.ts
Copy link
Copy Markdown
Owner

@nirvik34 nirvik34 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Current code trusts the x-forwarded-for header directly without validation:
if (isValidIp(forwardedFor)) {
  return forwardedFor;
}
  • Only use x-forwarded-for when explicitly trusted (e.g., behind a known proxy)
  • Check a PROXY_TRUSTED environment variable first
  • Prefer server-derived client IP (e.g., request.socket.remoteAddress)

Verify that multi-hop X-Forwarded-For chains (spoofed IPs) are properly rejected when proxy trust is disabled.

Comment thread frontend/src/app/api/generate/route.ts
Comment thread frontend/src/lib/rateLimit.ts Outdated
@vraj826 vraj826 requested a review from nirvik34 May 28, 2026 10:41
@vraj826
Copy link
Copy Markdown
Author

vraj826 commented May 28, 2026

@nirvik34 I have made the requested changes, can you review this!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/lib/rateLimit.ts (1)

117-123: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the block duration cover the remaining window.

When windowMs > cooldownMs, this returns Retry-After = cooldownMs, but the bucket still cannot reset until resetAt. The /api/generate route forwards retryAfterSeconds directly as the HTTP Retry-After header, so clients that wait exactly what we advertise can still get another 429 immediately. Clamp blockedUntil to at least bucket.resetAt when the limit is exceeded.

🔧 Proposed fix
   if (bucket.count > config.maxRequests) {
-    bucket.blockedUntil = now + config.cooldownMs;
+    bucket.blockedUntil = Math.max(bucket.resetAt, now + config.cooldownMs);
     buckets.set(key, bucket);
     return {
       allowed: false,
       retryAfterSeconds: secondsUntil(bucket.blockedUntil, now),
       remaining: 0,
     };
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/rateLimit.ts` around lines 117 - 123, When the bucket count
exceeds config.maxRequests, clamp bucket.blockedUntil to cover the remaining
window by setting it to the later of now + config.cooldownMs and bucket.resetAt
(instead of always now + config.cooldownMs), update buckets.set(key, bucket)
with that clamped value, and compute retryAfterSeconds via
secondsUntil(bucket.blockedUntil, now) so the returned retryAfterSeconds cannot
understate how long the bucket remains blocked; apply this change in the branch
that returns { allowed: false, retryAfterSeconds, remaining: 0 }.
🧹 Nitpick comments (1)
frontend/src/lib/rateLimit.ts (1)

21-27: ⚡ Quick win

Tighten IP validation in resolveIdentifier (regex-based).

  • frontend/src/app/api/generate/route.ts already derives the rate-limit key using node:net isIP, so malformed x-forwarded-for values won’t pass in the live request path.
  • The handwritten IP_RE in frontend/src/lib/rateLimit.ts only impacts resolveIdentifier (no production call sites found—only frontend/src/lib/rateLimit.test.ts uses it). If resolveIdentifier is meant to be used, harden isValidIp and add regression tests for invalid IPv4/IPv6 inputs (e.g., 999.999.999.999, :::).
🔧 Proposed fix
+import { isIP } from "node:net";
+
-// Regex for a bare IPv4 or IPv6 address (no port, no CIDR).
-const IP_RE =
-  /^(?:(?:\d{1,3}\.){3}\d{1,3}|(?:[0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}|::(?:[fF]{4}:)?\d{1,3}(?:\.\d{1,3}){3})$/;
-
 /** Returns true for a syntactically valid IP address (v4 or v6). */
 function isValidIp(value: string): boolean {
-  return IP_RE.test(value.trim());
+  return isIP(value.trim()) !== 0;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/rateLimit.ts` around lines 21 - 27, The current IP_RE used
by isValidIp is too permissive; update isValidIp to use stricter validation by
replacing the single loose regex with separate, robust IPv4 and IPv6 checks
(e.g., an IPv4 regex that enforces 0-255 per octet and a stricter IPv6 pattern)
or delegate to a well-tested utility if available, and ensure resolveIdentifier
(which relies on isValidIp) uses the tightened function; add regression tests
covering invalid inputs such as "999.999.999.999", ":::","abcd::12345", empty
string, and malformed mixed IPv4/IPv6 to frontend/src/lib/rateLimit.test.ts to
prevent regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/src/lib/rateLimit.ts`:
- Around line 117-123: When the bucket count exceeds config.maxRequests, clamp
bucket.blockedUntil to cover the remaining window by setting it to the later of
now + config.cooldownMs and bucket.resetAt (instead of always now +
config.cooldownMs), update buckets.set(key, bucket) with that clamped value, and
compute retryAfterSeconds via secondsUntil(bucket.blockedUntil, now) so the
returned retryAfterSeconds cannot understate how long the bucket remains
blocked; apply this change in the branch that returns { allowed: false,
retryAfterSeconds, remaining: 0 }.

---

Nitpick comments:
In `@frontend/src/lib/rateLimit.ts`:
- Around line 21-27: The current IP_RE used by isValidIp is too permissive;
update isValidIp to use stricter validation by replacing the single loose regex
with separate, robust IPv4 and IPv6 checks (e.g., an IPv4 regex that enforces
0-255 per octet and a stricter IPv6 pattern) or delegate to a well-tested
utility if available, and ensure resolveIdentifier (which relies on isValidIp)
uses the tightened function; add regression tests covering invalid inputs such
as "999.999.999.999", ":::","abcd::12345", empty string, and malformed mixed
IPv4/IPv6 to frontend/src/lib/rateLimit.test.ts to prevent regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b8c54157-c24a-4dad-a002-2bb4494789bc

📥 Commits

Reviewing files that changed from the base of the PR and between 09306ac and 0edbd5a.

📒 Files selected for processing (2)
  • frontend/src/lib/rateLimit.test.ts
  • frontend/src/lib/rateLimit.ts

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.

[FEATURE]: Secure Gemini API Architecture & Prompt Injection Hardening

2 participants