Skip to content

IDOR on deep-research task results — no ownership check #39

@Hag-Zilla

Description

@Hag-Zilla
  • Context: Cloud / Both
  • Category: Vulnerability (Insecure Direct Object Reference)
  • Severity: High

Evidence

The task-status route authenticates the caller but never verifies that the taskId belongs to the authenticated session:

// app/api/deepresearch/[taskId]/route.ts
export async function GET(request, { params }) {
  const { taskId } = await params;
  const accessToken = searchParams.get("accessToken");

  const selfHosted = isSelfHostedMode();
  if (!selfHosted && !accessToken) {
    return NextResponse.json({ error: "Authentication required" }, { status: 401 });
  }
  // ✅ Checks: is the user authenticated?
  // ❌ Missing: does this taskId belong to this user/session?
  const statusData = await getStatusViaProxy(taskId, accessToken);
  // statusData contains: generated content, sources, pdfUrl, deliverables
}

The response includes the full generated intelligence dossier, source list, PDF/PPTX download URLs, and CSV export data.

Scenario: User A starts a deep-research task; their taskId leaks via a server log, an APM trace, a Referer header (because taskId appears in the polling URL), or a shared log aggregator. Any other authenticated user who learns the taskId can retrieve the complete dossier without authorization.

If Valyu's backend enforces ownership on its side, this risk is partially mitigated — but the application provides no defense-in-depth layer, and any self-hosted-mode request (no auth required) bypasses even that.

Impact: Unauthorized read access to potentially sensitive intelligence dossiers generated by other users.

Affected files: app/api/deepresearch/[taskId]/route.ts, components/search/entity-search.tsx

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