Skip to content

fix(uploads): drop the stray 'use server' directive that enables Server Actions app-wide - #6335

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/remove-use-server-directive
Aug 6, 2026
Merged

fix(uploads): drop the stray 'use server' directive that enables Server Actions app-wide#6335
waleedlatif1 merged 2 commits into
stagingfrom
fix/remove-use-server-directive

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Problem

Any unauthenticated POST with Content-Type: multipart/form-data to any App Router path returns HTTP 500.

Next decides a request is a Server Action from headers alonenext/dist/server/app-render/server-action-request-meta.js:36, no body inspection, no auth. The fetch-style action path returns a graceful 404, but the non-fetch multipart path does a bare throw (action-handler.js:589,743) that becomes a 500.

Next has an escape hatch at action-handler.js:412: when hasServerActions() is false it returns 404 early and none of this runs. Sim had exactly one 'use server' file — apps/sim/lib/uploads/utils/file-utils.server.ts — and it was the sole reason that flag was true.

Availability impact

~180 requests (60/min for 3 min from a single IP) is enough to drive the ALB 5xx alarm ...-alb-high-error-percentage (>5% for 3 consecutive 60s periods) and page on-call. It fired today at 17:22:16Z. This is an unauthenticated, zero-cost DoS against the alerting path.

Auth-surface impact

'use server' also published every export of that module as a remotely invocable endpoint with no auth wrapper: downloadFileFromUrl, resolveInternalFileUrl, downloadFileFromStorage, downloadServableFileFromStorage, resolveFileInputToUrl. Several take a caller-supplied URL and fetch it — SSRF-shaped. Exploitability was not confirmed (Next's action IDs are build-derived and hard to guess), but the surface should not exist at all. Removing the directive removes it.

Fix

Delete the directive. Nothing ever invoked these as Server Actions.

server-only was considered and rejected: it is not currently a dependency, is used nowhere in the repo, and the .server.ts suffix already carries the server-only convention here. Adding a dependency for a one-line deletion is not the minimal fix.

Verification

Only 'use server' in the repo (rg over apps/ + packages/): 1 hit, this file.

Zero 'use client' importers: all ~77 importers are route handlers, executor code, and other .server.ts modules. No useActionState/useFormState/<form action={...}> anywhere.

Actions manifest — the load-bearing check. .next/server/server-reference-manifest.json:

node actions edge actions
before 5 0
after 0 0

After: {"node":{},"edge":{},"encryptionKey":"..."}hasServerActions() is now false, so Next takes the early-404 path and the multipart 500 is gone.

(Both builds compiled successfully and then failed identically at page-data collection on Missing DATABASE_URL — a local-env limitation, unrelated to this change and present on both sides. The manifest is written at compile time, so the evidence is valid.)

Regression guard

scripts/check-client-boundary-imports.ts (already wired into CI as bun run check:client-boundary) now also fails on any 'use server' directive — module prologue or inline in a function body — across apps/ and packages/. Directive detection was factored into a shared leadingDirective() helper rather than duplicated.

Confirmed the guard fails without the fix:

✗ 1 'use server' directive(s) found.
  apps/sim/lib/uploads/utils/file-utils.server.ts:1

and passes with it.

Checks

  • bunx tsc --noEmit -p tsconfig.json — clean
  • bun run lint — 23/23 tasks pass
  • bunx vitest run lib/uploads/ providers/file-attachments.server.test.ts executor/utils/file-tool-processor.test.ts lib/execution/payloads/materialization.server.test.ts — 315 passed / 30 files
  • bun run check:client-boundary — passes

Not verified

  • SSRF exploitability of the exposed action endpoints (surface removed regardless).
  • No live reproduction of the 500 against a deployed environment; the causal chain is established from the Next source, the manifest delta, and the alarm timing.

@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Aug 6, 2026 7:25pm

Request Review

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Touches Next.js Server Action enablement and request routing—security and availability critical—even though the functional fix is removing one directive and adding a static guard.

Overview
Removes the 'use server' prologue from file-utils.server.ts, which was the only such directive in apps/ and packages/. That single module had turned on Next’s hasServerActions() app-wide, so unauthenticated multipart/form-data POSTs to App Router paths could hit Server Action handling and return 500s (availability risk for ALB alarms) while also registering the module’s exports as remotely invocable actions. The upload helpers stay ordinary .server.ts modules imported from route handlers and executors—no behavior change to the file APIs themselves.

scripts/check-client-boundary-imports.ts now also fails CI when any 'use server' appears (module prologue or inline) across apps and packages, with shared leadingDirective() / comment-stripping for 'use client' detection. The existing 'use client' import guard is unchanged but shares the same exit path in --check mode.

Reviewed by Cursor Bugbot for commit c39ddeb. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR removes the upload utility module’s stray use server directive and extends the existing boundary-check script to reject future Server Action directives.

  • Removes the directive that populated Next’s Server Actions manifest.
  • Scans application and package sources for use server.
  • Shares directive parsing between the server-action and client-boundary checks.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/lib/uploads/utils/file-utils.server.ts Removes the module-level Server Action directive without changing the upload utility implementations.
scripts/check-client-boundary-imports.ts Extends the CI boundary checker to reject Server Action directives and consolidates directive parsing.

Reviews (2): Last reviewed commit: "fix(scripts): match boundary directives ..." | Re-trigger Greptile

Comment thread scripts/check-client-boundary-imports.ts Outdated
Comment thread scripts/check-client-boundary-imports.ts Outdated
…er Actions app-wide

`file-utils.server.ts` was the repo's only `'use server'` module, and the sole
reason Next's `hasServerActions()` returned true. With actions registered, Next
loses its early-404 escape hatch for Server Action requests — and it classifies
a request as an action from headers alone, with no body inspection and no auth.
Any unauthenticated `POST` with `Content-Type: multipart/form-data` to any App
Router path therefore took the non-fetch action path, which bare-throws and
surfaces as an HTTP 500.

Nothing invokes these functions as Server Actions: every one of the ~77
importers is server-side, with zero `'use client'` importers. The directive was
a misuse of `'use server'` where "server-only module" was meant — the `.server.ts`
suffix already carries that convention.

Extends check-client-boundary-imports.ts to fail on any `'use server'` directive
so this cannot regress.
A directive keeps its meaning when a note follows it on the same line, so
strip a trailing '//' or block comment before matching. Shared by the
'use client' and 'use server' detectors.
@waleedlatif1
waleedlatif1 force-pushed the fix/remove-use-server-directive branch from 13d579a to c39ddeb Compare August 6, 2026 19:21
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit c39ddeb. Configure here.

@waleedlatif1
waleedlatif1 merged commit 3e3d860 into staging Aug 6, 2026
4 of 5 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/remove-use-server-directive branch August 6, 2026 19:25
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.

1 participant