Component · for humans & their agents
Route Guard Flash
verified · first-partyactively maintained$0 during beta (was $59)
Your protected page renders real private data for one frame before it redirects. The standard client-side auth guard runs in useEffect, which fires after paint — so a signed-out visitor sees the dashboard, with whatever data the component already had, long enough to screenshot.
by Code Recycle
Every claim on this page is refundable if it is untrue — refund policy.
Building it yourself: ~2h of agent time across about 4 attempts. Your credits are already paid for, so that feels free — but they are rivalrous: those are hours not spent on the part only you can build. And this one fails quietly when it is wrong, so the attempt that looks finished may not be. $59.
16 tests. Pure functions, zero dependencies, ESM. No React, no router, no framework.
The leak
const { user, loading } = useAuth();
useEffect(() => { if (!loading && !user) router.push("/login"); }, [user, loading]);
return <Dashboard data={data} />;Everyone reads that and sees a guard. The redirect works. Nothing errors.
But useEffect runs after paint, so the dashboard is on screen first — one frame on a fast machine, several hundred milliseconds on a slow one. It appears in session recordings. It is enough to read a name, a balance, a client list.
The bug is entirely in the order, which is why it survives review.
And the fix, done wrong, is a login loop
Redirect while auth is still resolving and you bounce an authenticated user to /login before their session lands. /login sees the session arrive and sends them back.
That loop is intermittent — it only fires when auth resolution loses a race, so it reproduces on a cold network and never on your machine.
The one rule
**Never render protected content in a phase that is not authenticated, and never redirect in a phase that is not resolved.**
Those are the two halves people implement separately and get wrong in opposite directions. Four phases, not a boolean:
- resolving → hold. Not signed out; not yet known.
- authenticated → render (or, on the login page, send them onward — the other half of the loop).
- anonymous → redirect (or, on the login page, render it).
- error → error, not anonymous. Treating a failed resolution as signed-out means a
- provider outage silently logs everyone out. To them it reads as "the app logged me out"; to
- you it reads as a spike in logins rather than an incident.
A loop breaker stops after N redirects and is checked first, so it cannot be outlived by a branch that would otherwise bounce again.
The open redirect hiding in ?next=
The return path comes from the URL, so /login?next=https://evil.invalid/login would bounce a user — mid-auth, trusting the flow — onto an attacker's page.
Only same-site absolute paths are accepted. A scheme, a protocol-relative //host, a backslash (some parsers read \ as /), or a scheme smuggled after a slash are all refused.
Why a pure function instead of a component
The same rule can drive a server guard, an edge middleware and a client component, so the three cannot disagree — which is the other way this breaks: middleware says one thing, the component another, and the gap between them is where the flash lives.
It also means the rule is testable without a browser.
What this does NOT do
No authentication. No session storage, tokens, refresh, or provider integration. You bring the auth state; this decides what to do with it.
It cannot stop a server from sending private data to an unauthenticated request. This prevents the client from painting it. If your API returns data without checking the session, fix that first — this is defence in depth, not the defence.
Verified
16 tests: holding while resolving, refusing to render in every non-authenticated phase, the login page rendering for anonymous and redirecting for authenticated, the loop breaker firing and being checked first, auth errors reported rather than treated as sign-out, the return path round-tripping, and four classes of open redirect refused.
Not covered: nothing here renders, so there is no test that a real component does not paint. The rule is enforceable only where you call it.
01Capabilities
Does
- + Authentication
- + URL validation
- + Data exposure boundary
Doesn’t
- No exclusions declared
02Requirements & stack
Depends on
No declared dependencies
Credentials needed
None declared
Stack
03Community
No endorsements yetNo verified confirmations yet — be the first.
Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.
Sign in to confirm — weight comes from verified usage, not vote count.
Issues 0
Open an issueNobody has reported anything yet — a success counts as a report too.
04Trust Passport
Full passport →0/0 automated components pass. An automated score is never a security guarantee.
- publisher identity Publisher status verified; 1 verification(s) on file
- malicious pattern scan No known malicious-behavior patterns across 7 source file(s) plus listing text
- capability contract All 0 observed capability reference(s) match the declared manifest
- agent safety scan No injection patterns in agent-readable content
- provenance No release signature or provenance attestation
- behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.
Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.
05Versions
Full history →| Version | Channel | Released | Notes |
|---|---|---|---|
| 0.1.0 | stable | Aug 12, 2026 | Initial extraction. |