Diagnostic
- Rule: react-doctor/nextjs-no-side-effect-in-get-handler
- Severity: error
- Category: Security
- Version: react-doctor 0.9.14
Message
This GET handler's side effect (headers.set()) is prone to CSRF vulnerabilities, since prefetching or a forged request can trigger it.
Repro
function downloadHeaders({ filename, contentType, contentLength }: {
filename: string;
contentType: string;
contentLength?: string | null;
}): Headers {
const headers = new Headers({
'Content-Type': contentType,
'Content-Disposition': `attachment; filename="${filename}"`,
});
if (contentLength) headers.set('Content-Length', contentLength);
return headers;
}
export async function GET(request: Request) {
const denied = await authorize();
if (denied) return denied;
const upstream = await fetch(/* ... */);
return new Response(upstream.body, {
headers: downloadHeaders({ filename: 'x', contentType: 'video/mp4', contentLength: '123' }),
});
}
Why this looks wrong
headers.set() is called on a Headers instance the helper just constructed with new Headers(...) for the response about to be returned. It never touches an external or shared Headers/cookie store, request state, or anything a forged/prefetched GET could observe or influence beyond the handler's own return value. The rule appears to pattern-match on any .headers.set() (or similar) call reachable from a GET handler, without distinguishing a locally constructed response object from shared/external state — the actual CSRF-relevant case.
Suggested fix
Scope the rule to Headers.set()/similar calls on an object that either (a) isn't a local new Headers(...)/new Response(...) freshly constructed within the handler's own call graph, or (b) is known to mutate state outside the handler's own response (cookies, a database write, an external API call with side effects, etc.).
Diagnostic
Message
This GET handler's side effect (headers.set()) is prone to CSRF vulnerabilities, since prefetching or a forged request can trigger it.Repro
Why this looks wrong
headers.set()is called on aHeadersinstance the helper just constructed withnew Headers(...)for the response about to be returned. It never touches an external or sharedHeaders/cookie store, request state, or anything a forged/prefetched GET could observe or influence beyond the handler's own return value. The rule appears to pattern-match on any.headers.set()(or similar) call reachable from a GET handler, without distinguishing a locally constructed response object from shared/external state — the actual CSRF-relevant case.Suggested fix
Scope the rule to
Headers.set()/similar calls on an object that either (a) isn't a localnew Headers(...)/new Response(...)freshly constructed within the handler's own call graph, or (b) is known to mutate state outside the handler's own response (cookies, a database write, an external API call with side effects, etc.).