Skip to content

isSelfHostedMode() fails open by default — all auth bypassed and paid API calls exposed on every fresh deploy #47

@tg12

Description

@tg12

Summary

lib/app-mode.ts implements authentication as opt-in rather than opt-out. When NEXT_PUBLIC_APP_MODE is unset (the default for any new deployment), isSelfHostedMode() returns true and all authentication checks in the events, deepresearch, and entities routes are bypassed.

Evidence

lib/app-mode.ts:

export function isSelfHostedMode(): boolean {
  return process.env.NEXT_PUBLIC_APP_MODE !== "valyu";
}

app/api/events/route.ts:

const selfHosted = isSelfHostedMode();
if (!selfHosted && !accessToken) {
  return NextResponse.json({ error: "Authentication required" }, { status: 401 });
}

Because NEXT_PUBLIC_APP_MODE is not set by default, every fresh deployment of this project — including deployments following the README instructions — runs with authentication completely disabled.

The same isSelfHostedMode() guard is used in at minimum app/api/events/route.ts and app/api/deepresearch/route.ts.

In this open state:

  • The events endpoint calls OpenAI gpt-4.1-nano on every request (paid API calls)
  • The deepresearch endpoint creates Valyu intelligence dossiers on arbitrary topics (paid API calls + credits)
  • All 31 hardcoded THREAT_QUERIES are executed against Valyu on every call

Why this matters

This is the canonical fail-open auth antipattern. Auth is disabled by default and must be actively opted into by setting an env var. The inverse of a secure default.

  • Billing abuse: Any visitor triggers paid OpenAI and Valyu API calls with no authentication or quota
  • Operator unawareness: Deployers following the README will run publicly with auth off and may not realise until they receive an unexpected bill
  • Information exposure: The deepresearch route generates "intelligence dossiers" on user-supplied topics via Valyu — open to anyone on a default deploy

Attack or failure scenario

  1. Operator deploys following the README without setting NEXT_PUBLIC_APP_MODE=valyu
  2. Bot or attacker discovers the deployment
  3. Bot floods /api/events with repeated requests
  4. Each request triggers 31 Valyu searches + one OpenAI gpt-4.1-nano classification call per event result
  5. Operator's Valyu credits and OpenAI bill exhaust silently

Root cause

Auth is conditioned on an opt-in env var rather than failing closed when the var is absent. The logic should be inverted: require explicit opt-out to disable auth, not opt-in to enable it.

Recommended fix

// Current (fail-open):
export function isSelfHostedMode(): boolean {
  return process.env.NEXT_PUBLIC_APP_MODE !== "valyu";
}

// Fixed (fail-closed):
export function isAuthRequired(): boolean {
  return process.env.DISABLE_AUTH !== "true";  // explicit opt-out
}

Or more directly: make NEXT_PUBLIC_APP_MODE=selfhosted the value that disables auth, so the absence of the variable means auth is enforced.

Add rate limits and cost caps on the OpenAI and Valyu calls regardless of auth mode.

Acceptance criteria

  • A fresh deploy with no env vars set requires authentication before any paid API call is triggered
  • README explicitly documents how to enable self-hosted open mode and its billing implications
  • Cost caps or request quotas applied to OpenAI and Valyu routes

Suggested labels

security, bug, production-readiness

Priority

P1

Severity

Critical — default deploy is fully open; any visitor triggers paid API calls with no authentication.

Confidence

Confirmed — code read directly; isSelfHostedMode() and its call site both confirmed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions