The Form That Exposes What It Should Protect
A GitHub security advisory for @nuxt/ui documents a vulnerability in UForm and UAuthForm — the standard form components in Nuxt's official UI library. Both components render server-side HTML with a <form> element that contains no method attribute and no action attribute. The components rely entirely on a client-side @submit.prevent handler, injected during JavaScript hydration, to intercept form submission and send data via POST. When hydration does not complete — because JavaScript fails to load, is blocked by a content security policy, times out on a slow connection, or is deliberately disabled — the browser falls back to the HTML specification default: GET. Credentials typed into the form are appended to the URL as query parameters.
Where GET Credentials End Up
When a form submits via GET, the field values — including passwords, tokens, and authentication codes — become part of the URL. This URL is recorded in multiple locations that were never designed to store secrets. Web server access logs capture the full request URL by default. Reverse proxies and CDN edge nodes cache and log URLs for performance diagnostics. Browser history stores the URL with visible query parameters. Analytics platforms that track page URLs ingest the credentials as page view data. Referrer headers propagate the URL to any external resource loaded on the resulting page. Each of these is a distinct exposure surface, and each persists independently — deleting browser history does not delete server logs, and rotating a password does not remove it from CDN caches.
SSR's Promise and Its Failure Mode
Server-side rendering is adopted specifically to improve reliability. The premise: the server delivers complete, functional HTML that works before JavaScript loads. Nuxt, built on Vue.js, is one of the frameworks that markets SSR as a first-class feature. The vulnerability in UForm inverts this promise. The SSR output is not functional — it is incomplete. A form without method="POST" is not a resilient fallback; it is a misconfigured default that activates precisely when the user is most vulnerable: when JavaScript has failed and the safety net is needed. The SSR markup is what the browser uses when the client-side layer is absent, and that markup sends credentials in cleartext URLs.
AI Crawlers and Bots Do Not Hydrate
The vulnerability's exposure extends beyond users with failed JavaScript. AI crawlers — GPTBot, ClaudeBot, PerplexityBot — and traditional web bots interact with SSR markup directly. They do not execute JavaScript. They do not wait for hydration. If an AI agent or automated system interacts with a Nuxt UI form, it processes the SSR HTML as delivered: a form with no method attribute. Any programmatic form submission by these agents defaults to GET. In a web where bot traffic accounts for nearly half of all requests, the population that will trigger the vulnerable code path is not a rounding error — it is a primary audience.
The Fix Is One Attribute
The remediation for this class of vulnerability is adding method="POST" to the server-rendered form element. This is not a complex engineering change — it is a single HTML attribute that the HTML specification has supported since 1995. The fact that it was omitted reflects a broader pattern in component frameworks: the assumption that client-side JavaScript is always present and always executes. That assumption is architecturally embedded in component libraries that treat server-rendered HTML as a temporary scaffold rather than a functional interface. Organizations using Nuxt UI for authentication should audit their SSR output for form elements without explicit method attributes and verify that credentials are never transmitted as URL query parameters, regardless of whether JavaScript is available.


