Skip to content

Fix(security): remove NEXT_PUBLIC_ usage from server-only route handlers#75

Open
Ayush8923 wants to merge 2 commits intomainfrom
fix/remove-next-public-server
Open

Fix(security): remove NEXT_PUBLIC_ usage from server-only route handlers#75
Ayush8923 wants to merge 2 commits intomainfrom
fix/remove-next-public-server

Conversation

@Ayush8923
Copy link
Collaborator

@Ayush8923 Ayush8923 commented Mar 18, 2026

Issue: #45

Summary

  • Removes the usage of NEXT_PUBLIC_ environment variables from server-only route handlers and replaces them with server-side environment variables.
  • Replaced process.env.NEXT_PUBLIC_BACKEND_URL with process.env.BACKEND_URL in all server-only route handlers

Notes

  • Make sure BACKEND_URL is properly defined in environment variables for all environments (local, staging, production)
  • Server restart is required after updating environment variables

Summary by CodeRabbit

  • Chores

    • Switched backend URL configuration to use a private environment variable across server routes; no change to behavior or user experience.
  • Documentation

    • Expanded product documentation with architecture, evaluation types, prompt-editor and shared component descriptions, and notes on backend configuration.
    • Documented upcoming features including CSV export for metrics and enhanced prompt/versioning workflows.

@Ayush8923 Ayush8923 self-assigned this Mar 18, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Systematically replaces the backend URL environment variable source from NEXT_PUBLIC_BACKEND_URL to BACKEND_URL across 30+ server-side API route handlers and one documentation file. The default fallback URL remains http://localhost:8000; no request handling, headers, or error logic were modified.

Changes

Cohort / File(s) Summary
Assistant Routes
app/api/assistant/[assistant_id]/route.ts
Switched env var from NEXT_PUBLIC_BACKEND_URL to BACKEND_URL in route handler.
Collections Routes
app/api/collections/route.ts, app/api/collections/[collection_id]/route.ts, app/api/collections/jobs/[job_id]/route.ts
Replaced public env var usage with BACKEND_URL across GET/POST/DELETE handlers.
Configs Routes
app/api/configs/route.ts, app/api/configs/[config_id]/route.ts, app/api/configs/[config_id]/versions/route.ts, app/api/configs/[config_id]/versions/[version_number]/route.ts
Replaced NEXT_PUBLIC_BACKEND_URL with BACKEND_URL in GET/POST/PATCH/DELETE handlers.
Document Routes
app/api/document/route.ts, app/api/document/[document_id]/route.ts
Updated backend env var reference in GET/POST/DELETE handlers.
Evaluations Base Routes
app/api/evaluations/route.ts, app/api/evaluations/[id]/route.ts
Switched to BACKEND_URL for backend requests in GET/POST handlers.
Evaluations Datasets Routes
app/api/evaluations/datasets/route.ts, app/api/evaluations/datasets/[dataset_id]/route.ts
Replaced env var source in GET/POST/DELETE dataset handlers.
Evaluations STT Routes
app/api/evaluations/stt/datasets/route.ts, app/api/evaluations/stt/datasets/[dataset_id]/route.ts, app/api/evaluations/stt/files/route.ts, app/api/evaluations/stt/runs/route.ts, app/api/evaluations/stt/runs/[run_id]/route.ts, app/api/evaluations/stt/results/[result_id]/route.ts, app/api/evaluations/stt/samples/[sample_id]/route.ts
Replaced NEXT_PUBLIC_BACKEND_URL with BACKEND_URL across STT GET/POST/PATCH/DELETE handlers.
Evaluations TTS Routes
app/api/evaluations/tts/datasets/route.ts, app/api/evaluations/tts/datasets/[dataset_id]/route.ts, app/api/evaluations/tts/runs/route.ts, app/api/evaluations/tts/runs/[run_id]/route.ts, app/api/evaluations/tts/results/[result_id]/route.ts
Updated TTS evaluation routes to use BACKEND_URL in GET/POST/PATCH/DELETE handlers.
Languages Routes
app/api/languages/route.ts
Replaced public env var with BACKEND_URL in handler.
Documentation
instructions/CLAUDE.md
Docs updated to reference BACKEND_URL (plus numerous doc additions); documentation only, no runtime code changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Possibly related PRs

  • UI overhaul #69 — Modifies same evaluation route handlers and previously used NEXT_PUBLIC_BACKEND_URL; changes should be coordinated.
  • TTS Evaluation #58 — Touches TTS evaluation routes also updated here; relevant for consistent env var usage.
  • UI: STT Evals #44 — Alters STT evaluation routes that overlap with this PR's edits; likely related.

Suggested labels

enhancement

Suggested reviewers

  • AkhileshNegi
  • nishika26
  • Prajna1999

Poem

🐰
I hopped through routes both near and far,
Tucked URLs out of sight in a jar.
NEXT_PUBLIC sleeps, BACKEND wakes—
Quiet, safe, no client breaks.
🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main security fix: removing NEXT_PUBLIC_ environment variable usage from server-only route handlers throughout the codebase.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/remove-next-public-server
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can enforce grammar and style rules using `languagetool`.

Configure the reviews.tools.languagetool setting to enable/disable rules and categories. Refer to the LanguageTool Community to learn more.

@Ayush8923 Ayush8923 changed the title fix(security): remove NEXT_PUBLIC_ usage from server-only route handlers Fix(security): remove NEXT_PUBLIC_ usage from server-only route handlers Mar 18, 2026
Copy link

@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.

🧹 Nitpick comments (5)
app/api/evaluations/stt/samples/[sample_id]/route.ts (1)

8-8: Fail fast when BACKEND_URL is missing.

After this env rename, silently falling back to http://localhost:8000 can hide misconfiguration in non-local environments. Prefer explicit failure (or fallback only in development).

Proposed change
-  const backendUrl = process.env.BACKEND_URL || 'http://localhost:8000';
+  const backendUrl =
+    process.env.BACKEND_URL ??
+    (process.env.NODE_ENV === 'development' ? 'http://localhost:8000' : undefined);
+
+  if (!backendUrl) {
+    return NextResponse.json(
+      { success: false, error: 'Server misconfiguration: BACKEND_URL is not set' },
+      { status: 500 }
+    );
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/stt/samples/`[sample_id]/route.ts at line 8, The code
currently sets backendUrl = process.env.BACKEND_URL || 'http://localhost:8000',
which hides missing configuration; change this so that when
process.env.BACKEND_URL is not set it throws an explicit error (or only falls
back to 'http://localhost:8000' when process.env.NODE_ENV === 'development').
Update the initialization of backendUrl in
app/api/evaluations/stt/samples/[sample_id]/route.ts (the backendUrl constant)
to validate process.env.BACKEND_URL and fail fast with a clear error message if
absent in non-development environments.
app/api/evaluations/tts/runs/route.ts (1)

16-20: Pre-existing issue: Inconsistent error handling compared to POST handler.

The GET handler returns the raw error object while the POST handler (line 49) correctly uses error instanceof Error ? error.message : String(error). Consider aligning the error handling for consistency.

♻️ Suggested fix
   } catch (error) {
     return NextResponse.json(
-      { success: false, error: error, data: null },
+      { success: false, error: error instanceof Error ? error.message : String(error), data: null },
       { status: 500 }
     );
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/tts/runs/route.ts` around lines 16 - 20, The GET
handler's catch currently returns the raw error object; update the catch block
in the GET route to format the error the same way the POST handler does (use
error instanceof Error ? error.message : String(error)) and pass that string
into NextResponse.json instead of the raw error so both handlers return
consistent error messages via NextResponse.json.
app/api/languages/route.ts (1)

16-20: Pre-existing issue: Raw error object may not serialize properly.

The error object is returned directly which may not serialize correctly to JSON and could potentially leak stack traces in production. Consider using error instanceof Error ? error.message : String(error) like other handlers in this PR.

♻️ Suggested fix
   } catch (error) {
     return NextResponse.json(
-      { success: false, error: error, data: null },
+      { success: false, error: error instanceof Error ? error.message : String(error), data: null },
       { status: 500 }
     );
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/languages/route.ts` around lines 16 - 20, The catch block currently
returns the raw error object via NextResponse.json which may not serialize and
can leak stack traces; replace the returned error value with a sanitized string
using a check like error instanceof Error ? error.message : String(error) (same
pattern used elsewhere) so the response becomes { success: false, error:
<sanitized-message>, data: null } while keeping the NextResponse.json call and
status 500 intact.
app/api/configs/route.ts (1)

7-12: Consider adding API key validation to the GET handler for consistency.

The POST handler validates the API key and returns a 401 if missing, but the GET handler passes an empty string when the key is absent. This inconsistency may allow unauthenticated requests to reach the backend.

♻️ Suggested improvement
 export async function GET(request: Request) {
   const backendUrl = process.env.BACKEND_URL || 'http://localhost:8000';
   const apiKey = request.headers.get('X-API-KEY');
+
+  if (!apiKey) {
+    return NextResponse.json(
+      { error: 'Missing X-API-KEY header' },
+      { status: 401 }
+    );
+  }

   try {
     const response = await fetch(`${backendUrl}/api/v1/configs/`, {
       headers: {
-        'X-API-KEY': apiKey || '',
+        'X-API-KEY': apiKey,
       },
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/configs/route.ts` around lines 7 - 12, The GET handler in
app/api/configs/route.ts currently sends 'X-API-KEY': apiKey || '' to the
backend without validating it; change the GET handler to validate apiKey the
same way the POST handler does and return a 401 Unauthorized response when the
key is missing/empty before performing the fetch. Locate the GET handler (the
function that performs the fetch to `${backendUrl}/api/v1/configs/`) and add the
same API key existence check and early return used by the POST handler so
unauthenticated requests are blocked.
app/api/collections/jobs/[job_id]/route.ts (1)

3-3: Consider centralizing backend URL resolution in one server-only helper.

This replacement is correct, but the same env-resolution snippet is duplicated across many handlers. Extracting it to a shared utility will reduce config drift and make future security/config changes one-touch.

♻️ Example pattern to apply consistently
-const backendUrl = process.env.BACKEND_URL || 'http://localhost:8000';
+const backendUrl = getBackendUrl();
// e.g. server-only helper
export function getBackendUrl(): string {
  return process.env.BACKEND_URL || 'http://localhost:8000';
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/collections/jobs/`[job_id]/route.ts at line 3, The duplicated inline
backend URL resolution (const backendUrl = process.env.BACKEND_URL ||
'http://localhost:8000') should be extracted into a single server-only helper
(e.g., export function getBackendUrl(): string) and all handlers should import
and call getBackendUrl() instead of repeating the expression; create the helper
in a shared server utilities module, replace references to the backendUrl
variable in route.ts and other handlers with getBackendUrl(), and ensure the
helper is only used on the server side (no client bundling).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/api/collections/jobs/`[job_id]/route.ts:
- Line 3: The duplicated inline backend URL resolution (const backendUrl =
process.env.BACKEND_URL || 'http://localhost:8000') should be extracted into a
single server-only helper (e.g., export function getBackendUrl(): string) and
all handlers should import and call getBackendUrl() instead of repeating the
expression; create the helper in a shared server utilities module, replace
references to the backendUrl variable in route.ts and other handlers with
getBackendUrl(), and ensure the helper is only used on the server side (no
client bundling).

In `@app/api/configs/route.ts`:
- Around line 7-12: The GET handler in app/api/configs/route.ts currently sends
'X-API-KEY': apiKey || '' to the backend without validating it; change the GET
handler to validate apiKey the same way the POST handler does and return a 401
Unauthorized response when the key is missing/empty before performing the fetch.
Locate the GET handler (the function that performs the fetch to
`${backendUrl}/api/v1/configs/`) and add the same API key existence check and
early return used by the POST handler so unauthenticated requests are blocked.

In `@app/api/evaluations/stt/samples/`[sample_id]/route.ts:
- Line 8: The code currently sets backendUrl = process.env.BACKEND_URL ||
'http://localhost:8000', which hides missing configuration; change this so that
when process.env.BACKEND_URL is not set it throws an explicit error (or only
falls back to 'http://localhost:8000' when process.env.NODE_ENV ===
'development'). Update the initialization of backendUrl in
app/api/evaluations/stt/samples/[sample_id]/route.ts (the backendUrl constant)
to validate process.env.BACKEND_URL and fail fast with a clear error message if
absent in non-development environments.

In `@app/api/evaluations/tts/runs/route.ts`:
- Around line 16-20: The GET handler's catch currently returns the raw error
object; update the catch block in the GET route to format the error the same way
the POST handler does (use error instanceof Error ? error.message :
String(error)) and pass that string into NextResponse.json instead of the raw
error so both handlers return consistent error messages via NextResponse.json.

In `@app/api/languages/route.ts`:
- Around line 16-20: The catch block currently returns the raw error object via
NextResponse.json which may not serialize and can leak stack traces; replace the
returned error value with a sanitized string using a check like error instanceof
Error ? error.message : String(error) (same pattern used elsewhere) so the
response becomes { success: false, error: <sanitized-message>, data: null }
while keeping the NextResponse.json call and status 500 intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5895d65e-a271-443c-8a56-b360805cb358

📥 Commits

Reviewing files that changed from the base of the PR and between 31b0489 and 37aa2ae.

📒 Files selected for processing (27)
  • app/api/assistant/[assistant_id]/route.ts
  • app/api/collections/[collection_id]/route.ts
  • app/api/collections/jobs/[job_id]/route.ts
  • app/api/collections/route.ts
  • app/api/configs/[config_id]/route.ts
  • app/api/configs/[config_id]/versions/[version_number]/route.ts
  • app/api/configs/[config_id]/versions/route.ts
  • app/api/configs/route.ts
  • app/api/document/[document_id]/route.ts
  • app/api/document/route.ts
  • app/api/evaluations/[id]/route.ts
  • app/api/evaluations/datasets/[dataset_id]/route.ts
  • app/api/evaluations/datasets/route.ts
  • app/api/evaluations/route.ts
  • app/api/evaluations/stt/datasets/[dataset_id]/route.ts
  • app/api/evaluations/stt/datasets/route.ts
  • app/api/evaluations/stt/files/route.ts
  • app/api/evaluations/stt/results/[result_id]/route.ts
  • app/api/evaluations/stt/runs/[run_id]/route.ts
  • app/api/evaluations/stt/runs/route.ts
  • app/api/evaluations/stt/samples/[sample_id]/route.ts
  • app/api/evaluations/tts/datasets/[dataset_id]/route.ts
  • app/api/evaluations/tts/datasets/route.ts
  • app/api/evaluations/tts/results/[result_id]/route.ts
  • app/api/evaluations/tts/runs/[run_id]/route.ts
  • app/api/evaluations/tts/runs/route.ts
  • app/api/languages/route.ts

Copy link

@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.

🧹 Nitpick comments (1)
instructions/CLAUDE.md (1)

8-298: Documentation expansions beyond the PR scope.

While the core objective of this PR is to remove NEXT_PUBLIC_ usage from server-only routes, this file includes extensive documentation additions covering components, type systems, features, and architecture details. These additions improve the documentation quality but are outside the stated PR scope.

Consider separating documentation improvements into a dedicated PR to keep changes focused and make reviews easier to follow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@instructions/CLAUDE.md` around lines 8 - 298, This PR accidentally bundles
large documentation expansions in instructions/CLAUDE.md unrelated to the stated
scope (removing NEXT_PUBLIC_ usage); revert or remove the unrelated additions
from this PR so the diff only contains server-only env changes (search for the
NEXT_PUBLIC_ token to validate scope), and move the architecture/component/type
system content into a separate docs PR or a new file (e.g., ARCHITECTURE.md) so
reviews remain focused; ensure the CLAUDE.md in this PR only contains the
minimal changes required for the env var cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@instructions/CLAUDE.md`:
- Around line 8-298: This PR accidentally bundles large documentation expansions
in instructions/CLAUDE.md unrelated to the stated scope (removing NEXT_PUBLIC_
usage); revert or remove the unrelated additions from this PR so the diff only
contains server-only env changes (search for the NEXT_PUBLIC_ token to validate
scope), and move the architecture/component/type system content into a separate
docs PR or a new file (e.g., ARCHITECTURE.md) so reviews remain focused; ensure
the CLAUDE.md in this PR only contains the minimal changes required for the env
var cleanup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c1e45bf2-65f4-404f-aa1d-a2e012431f6d

📥 Commits

Reviewing files that changed from the base of the PR and between 37aa2ae and 51a06f7.

📒 Files selected for processing (1)
  • instructions/CLAUDE.md

Copy link
Collaborator

@vprashrex vprashrex left a comment

Choose a reason for hiding this comment

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

@Ayush8923 @Prajna1999 After the merge .env need to be updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants