Read the docs
TI-2026-67021 Aliases GHSA-gj2h-2fpw-fhv9

@nuxt/ui: UAuthForm / UForm SSR markup omits `method`, leaking credentials via GET if submitted before hydration

Priority LOW 38CWE-200Published · Updated

Key facts

Attack vector
—
Privileges required
—
User interaction
—
Attack complexity
—
Impact type
Information disclosure
Confidentiality · integrity · availability
—
Fix status
Fixed

No CVSS vector from any source. Fix status from GitHub. Impact type from CWE-200.

Summary

### Summary `UForm` and `UAuthForm` render a server-side `<form>` element with no `method` and no `action` attribute, relying on a hydrated `@submit.prevent` handler to intercept submission. If a user submits the form before Vue hydration has attached the handler (autofill plus Enter on a slow network, JS bundle blocked by CSP or CDN failure, etc.), the browser performs the native default: a `GET` to the current URL with every named field, including `<input type="password">`, serialised into the query string. ### Details `src/runtime/components/Form.vue` (around the template's `<form>` element) emits: ```vue <component :is="parentBus ? 'div' : 'form'" :id="formId" ref="formRef" :class="ui({ class: [uiProp?.base, props.class] })" @submit.prevent="onSubmitWrapper" > ``` No `method`, no `action`. `@submit.prevent` is the only thing stopping native submission, and it only exists after hydration. `UAuthForm` composes `UForm` and inherits the same shape. The SSR snapshot of `UAuthForm` (`test/components/__snapshots__/AuthForm.spec.ts.snap`) shows the rendered markup, with `<input type="password" name="password">` inside a `<form>` that has no `method`. ### Proof of concept Reported by @nimonian: 1. Create a minimal Nuxt app with a `UAuthForm`. 2. Build for production and visit in a browser with network throttling at 4G or slower. 3. Enter credentials. 4. Submit (or let autofill + Enter fire before hydration). The URL becomes `/login?email=…&password=…`. Reproducible deterministically in Playwright by triggering submit immediately on `load`. ### Impact Any application using `UAuthForm` (or `UForm` with credential-shaped fields) as documented. The cleartext password lands in: - the address bar, - `window.history`, - the `Referer` header of every same-origin subresource fetched from the resulting URL, - access logs of any reverse proxy, CDN, or WAF that records request URLs. ### Patch Default the rendered `<form>` to `method="post"` so the pre-hydration fallback submits as POST rather than GET. Vue's `@submit.prevent` still intercepts the hydrated case; the attribute only matters in the race window. Applications that explicitly want native GET submission can opt back in by passing `method="get"`. ### Credit Reported by @nimonian. Originally filed as `GHSA-92g7-2fpq-hmq8` against `nuxt/nuxt`; moved here because the affected code lives in `@nuxt/ui`.

Why it matters now

Fix Fixed @nuxt/ui (npm): 4.8.1

SSVC decision points

Not available: CISA has not published SSVC decision points for this record.

Affected products

VendorProductAffected versionsFixed inStatusSource
—@nuxt/ui (npm)before 4.8.14.8.1Patch availableGHSA-gj2h-2fpw-fhv9
  • @nuxt/ui (npm) Vendor— Affected before 4.8.1 Fixed in 4.8.1 Patch available GHSA-gj2h-2fpw-fhv9

Remediation

  • Fix · GHSA-gj2h-2fpw-fhv9 @nuxt/ui (npm) Fixed in 4.8.1 Advisory →

Timeline

  1. 2026-10-03 Threatist record created from GHSA-gj2h-2fpw-fhv9

References

Sources

This product uses the NVD API but is not endorsed or certified by the NVD. Sources and licences