URL: /rules/security/password-form-get

---
title: "Password form submitted by GET: the password in the URL warning"
description: "A form with a password field and method=get, or no method, puts the password in the URL. squirrel checks method and formmethod on every password form."
---

## What a password form sent by GET is

A form with `method="get"`, or with no `method` at all because GET is the default, submits its fields in the URL query string. For a password field that means the password lands in browser history, in server and proxy logs, in analytics, and in the `Referer` header sent to other sites. [security/form-https](/rules/security/form-https) checks where a form submits. This rule checks how.

A submit button can override the form with `formmethod`. One GET button on a POST form is enough to expose the password, and Enter in a field submits through the form's first submit button.

## What squirrel checks

The rule runs on every crawled page. It assesses each `<form>` that contains an enabled `<input type="password">`, including one attached from outside the form with the `form` attribute. Forms with no password field are not assessed. The rule reads the markup only and submits nothing.

For each password form it works out the method of every way to submit it: each enabled submit control (`button` without `type="button"`, `"reset"` or `"menu"`, `input type="submit"` and `input type="image"`, in the form or attached with `form`) uses its `formmethod` when present, else the form's `method`. A form with no submit control uses its own `method`. Values are read in any letter case, `dialog` goes nowhere on the network, and any other value is GET.

- Fail with `N form(s) with a password field submit by GET` when any way of submitting is GET because the markup says so: an explicit `method="get"` (or any value that is not `post` or `dialog`), a `formmethod` of GET on a submit control, or no `method` on a form that has a real `action` (it goes by GET without a script). Each item names the form by its id, name or action, with its action and position (`form 2 of 3`). Severity error.
- `password-form-get-no-method`, warning: a password form with no `method` at all, no usable `action` (none, empty or `javascript:`, which is what React puts there) and no inline handler. That is how a script-driven login form built with React, Vue or Svelte looks in the DOM: the script submits it. It is GET only if that script has not loaded or fails, and then the password goes in the URL. `method="post"` removes the risk.
- Pass with `Every form with a password field submits by POST` when every submit control posts.
- `password-form-get-undetermined`, info: a password form that would submit by GET (a `method` that is GET, or none) with no usable `action`, and an inline `onsubmit` on the form or `onclick` on a submit control. A script probably sends it, so squirrel does not call it a failure. Handlers attached with `addEventListener` are not visible in markup, so a form with an action is assessed on its attributes.

The action shown in a finding is the path only: its query, fragment and any credentials are dropped, because an action can carry a token. That applies to the label, the item's selector and its snippet.
- Nothing at all when no form has a password field.

## How to fix it

```html
<form action="/login" method="post">
  <input type="password" name="password" autocomplete="current-password">
  <button>Sign in</button>
</form>
```

Set `method="post"` on the form and remove any `formmethod="get"` from its buttons. Check logs and analytics for passwords that were already sent in a URL, and rotate those.

| | |
|---|---|
| **Rule ID** | `security/password-form-get` |
| **Category** | [Security](/rules/security) |
| **Scope** | Per-page |
| **Severity** | error |
| **Weight** | 8/10 |

## Enable / disable

### Disable this rule

```toml squirrel.toml
[rules]
disable = ["security/password-form-get"]
```

### Disable all Security rules

```toml squirrel.toml
[rules]
disable = ["security/*"]
```

### Enable only this rule

```toml squirrel.toml
[rules]
enable = ["security/password-form-get"]
```

`enable` replaces the default `["*"]`, so this is the only rule selected. Leave `disable` out: a rule that matches any `disable` pattern is skipped even when `enable` names it. Only an `enabled` setting under a rule's own `[rule_options]` table overrides both lists.

## Related rules

- [security/form-https](/rules/security/form-https): where a form submits.
- [security/form-captcha](/rules/security/form-captcha): the same forms, checked for bot protection.
- [security/referrer-policy](/rules/security/referrer-policy): limits what the Referer header carries to other sites.

Security findings ship in every audit next to the SEO, performance and agent experience rules. See [Website security scan with AI](https://squirrelscan.com/learn/audit-website-security-with-ai) for how an agent works through a report.

## References

- [The form element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/form)
- [Password fields, OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)

## Check your site

Run `squirrel audit https://example.com` and open the Security section of the report. Every password form sent by GET is listed by page with the form's selector and a markup snippet. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

<CardGroup cols={2}>
  <Card title="Install squirrel" icon="terminal" href="/quickstart">
    One command to install, one to run your first audit.
  </Card>
  <Card title="See a sample report" icon="file-text" href="https://squirrelscan.com/reports/squirrelscan-sample">
    What the Security section looks like on a real site.
  </Card>
</CardGroup>
