Skip to content
Report library
Purpose / Other

Clerk Custom Ui Skill Security Audit

What the author says it does (original text)

Custom authentication flows and component appearance - hooks (useSignIn,

Independent security check

Security risks found

Files checked
6
Risks found
3
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.No risks found
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.Risks found: 1
Low risk

Complete examples expose raw authentication error objects on public auth pages

Source references: 4
What we found

The references state that `errors.raw` contains Clerk's raw error array, while both complete examples render the entire `errors` object with `JSON.stringify(errors)`.

Why this matters

Visitors to sign-in or sign-up pages may see internal error codes, detailed failure reasons, or account-state information beyond what the interface needs. The exact exposure depends on the errors Clerk returns.

The reference says `errors` can contain Clerk's raw error array, while both “complete” examples render the entire object on public authentication pages. If used in production and Clerk includes internal diagnostic fields, signed-out visitors could see more than the intended friendly message. The source does not show that the raw entries contain secrets, so credential exposure cannot be asserted. Users can require allowlisted field messages and keep full diagnostics in protected logs.

core-3/custom-sign-in.md:173In the instructionsOpen original file
// Global errors (not tied to a field)errors?.global // ClerkGlobalHookError[] | null// Raw error arrayerrors?.raw // ClerkError[] | null```
Show 3 other places
core-3/custom-sign-in.md:300In the instructionsOpen original file
        </div>        <button type="submit" disabled={fetchStatus === 'fetching'}>          Continue        </button>      </form>      {errors && <p>{JSON.stringify(errors, null, 2)}</p>}    </>  )
core-3/custom-sign-up.md:142In the instructionsOpen original file
// Global errorserrors?.global // ClerkGlobalHookError[] | null// Raw error arrayerrors?.raw // ClerkError[] | null```
core-3/custom-sign-up.md:242In the instructionsOpen original file
        </div>        <button type="submit" disabled={fetchStatus === 'fetching'}>          Continue        </button>      </form>      {errors && <p>{JSON.stringify(errors, null, 2)}</p>}      {/* Required for sign-up flows. Clerk's bot sign-up protection is enabled by default */}      <div id="clerk-captcha" />    </>
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.No risks found
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 1
Low risk

The install command does not pin a dependency version

Source references: 2
What we found

The installation command does not specify dependency versions. The same command may download different code later, so what you install can differ from what was checked.

Why this matters

A later install may download different code even though the command and this report have not changed.

The skill instructs the user to install `@clerk/ui` without pinning a version. npm may therefore resolve different code over time. This is a reproducibility and supply-chain change risk, not evidence that the package is malicious. A user can ask for a tested version range and lockfile, and review the resolved version before installation.

SKILL.md:105In the instructionsOpen original file
```bashnpm install @clerk/ui```
Show 1 other places
SKILL.md:102In the instructionsOpen original file
Install themes from `@clerk/ui`:```bashnpm install @clerk/ui```
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.No risks found
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.Risks found: 1
Medium risk

The sign-up example can record legal acceptance without actual user consent

Source references: 1
What we found

The `signUp.update()` example hard-codes `legalAccepted` to `true` instead of deriving it from a consent checkbox or another explicit user action.

Why this matters

If copied into a production sign-up flow, it could mark users as having accepted terms they did not explicitly accept, making consent records unreliable and creating contractual, audit, or compliance disputes.

This is a documentation example, not automatically executed code, but it sets `legalAccepted` to `true` alongside ordinary profile fields without showing an affirmative consent input. If copied into a real sign-up flow, it could record acceptance without the user's actual agreement, affecting compliance records and user decisions. The user can require an explicit consent action and recording of the terms version, timestamp, and evidence.

core-3/custom-sign-up.md:48In the instructionsOpen original file
### Update (add fields to existing sign-up)Use `update()` to add optional fields (name, metadata, legal acceptance, locale) to an existing sign-up before finalization.```typescriptconst { error } = await signUp.update({  firstName: 'Jane',  lastName: 'Doe',  unsafeMetadata: { referralSource: 'twitter' },  legalAccepted: true,})```

Inside this skill

6 instruction sections

The Skill selects either the Core 2 or current reference based on the project's Clerk SDK version, then guides the agent in building sign-in, sign-up, or appearance customization.

View source
SKILL.md:156In the instructionsOpen original file
1. Identify customization needs (custom flow or appearance)2. For custom flows: check SDK version → read appropriate `core-2/` or `core-3/` reference3. For appearance: WebFetch the appropriate documentation from table above4. Apply appearance prop to your Clerk components or build custom flow with hooks

The appearance workflow fetches documentation from clerk.com and may instruct installation of Clerk's theme package, causing network access and adding a dependency to the user's project.

View source
SKILL.md:102In the instructionsOpen original file
Install themes from `@clerk/ui`:```bashnpm install @clerk/ui```
SKILL.md:156In the instructionsOpen original file
1. Identify customization needs (custom flow or appearance)2. For custom flows: check SDK version → read appropriate `core-2/` or `core-3/` reference3. For appearance: WebFetch the appropriate documentation from table above4. Apply appearance prop to your Clerk components or build custom flow with hooks

The custom authentication examples collect passwords, verification codes, and MFA codes, then activate a Clerk session after authentication completes. The supplied text does not direct these credentials to a destination outside Clerk.

View source
core-2/custom-sign-in.md:145In the instructionsOpen original file
    try {      const result = await signIn.create({ identifier, password })      if (result.status === 'needs_second_factor') {        setStep('mfa')        return      }      if (result.status === 'complete') {        await setActive({ session: result.createdSessionId })        router.push('/')      }
core-2/custom-sign-up.md:133In the instructionsOpen original file
    try {      const result = await signUp.attemptVerification({        strategy: 'email_code',        code,      })      if (result.status === 'complete') {        await setActive({ session: result.createdSessionId })        router.push('/')      }

The `<Show>` checks for roles, permissions, and plans only control browser visibility. The Skill explicitly warns that this is not a security boundary and calls for server-side access verification.

View source
core-3/show-component.md:106In the instructionsOpen original file
## Security Caveat**`<Show>` only visually hides content** — it remains in browser source. It is not a security boundary. For protecting sensitive data, always verify authentication server-side with `auth()` or use `auth.protect()` in middleware.
Start here · InstructionsSKILL.md
clerk-custom-ui
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.
Files and check records6 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included
  • core-2/custom-sign-in.mdFull text included
  • core-2/custom-sign-up.mdFull text included
  • core-3/custom-sign-in.mdFull text included
  • core-3/custom-sign-up.mdFull text included
  • core-3/show-component.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions
  • core-2/custom-sign-in.mdSupporting file
  • core-2/custom-sign-up.mdSupporting file
  • core-3/custom-sign-in.mdSupporting file
  • core-3/custom-sign-up.mdSupporting file
  • core-3/show-component.mdSupporting file

Operations mentioned in code and instructions

Connect to websites
SKILL.md:51In the instructionsOpen original file
|------|---------------|| Appearance prop overview | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/overview || Options (structure, logo, buttons) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/layout |
SKILL.md:52In the instructionsOpen original file
| Appearance prop overview | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/overview || Options (structure, logo, buttons) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/layout || Themes (pre-built dark/light) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/themes |
SKILL.md:53In the instructionsOpen original file
| Options (structure, logo, buttons) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/layout || Themes (pre-built dark/light) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/themes || Variables (colors, fonts, spacing) | https://clerk.com/docs/nextjs/guides/customizing-clerk/appearance-prop/variables |
Run commands
SKILL.md:104In the instructionsOpen original file
```bashnpm install @clerk/ui
Install extra software packages
SKILL.md:105In the instructionsOpen original file
```bashnpm install @clerk/ui```
Read keys or account settings
core-2/custom-sign-in.md:136In the instructionsOpen original file
  const [mfaCode, setMfaCode] = useState('')  const [step, setStep] = useState<'credentials' | 'mfa'>('credentials')  const [error, setError] = useState('')
Lines read
1,293
File checksum (to compare versions)
ed0e8d2b3d9cbf79f5eed453849b80086479036d2c46877cd5d26cd3e7788cdf