Safeguard
Security Guides•

Why do scanners miss stored XSS, and how do you close the gap?

Scanners miss stored XSS because the payload goes in on one request and fires on another page. Here is why, and how to test the places they skip.

Safeguard Security Team
4 min read

Scanners miss stored XSS because the attack needs two steps in two places: a payload saved by one request, then rendered by a different page, often one the scanner never visits or cannot see. You close the gap with authenticated crawling, unique markers you search for later, and manual checks of admin views.

What stored XSS is

Stored cross-site scripting happens when an application accepts input, saves it, and later shows it to users without making it safe for the browser. The OWASP Web Security Testing Guide notes that this usually involves at least two requests, which is why it is also called second-order XSS. It also points out that the victim does not need to click a crafted link. Opening the page that holds the data is enough.

That second property is what makes it serious. A comment, a profile name or a support ticket can run script in the browser of whoever reads it next, including staff with high privileges.

Why the two-step shape trips up scanners

A scanner that tests reflected XSS gets its answer in the same response: send a probe, look for it in the reply. Stored XSS breaks that loop in several ways.

  • The probe is accepted on a form, but the page that renders it is a different URL.
  • The rendering page sits behind a role the scanner does not have, such as a moderation queue or an admin dashboard.
  • The data appears only after a delay, an approval step, or a background job.
  • The data leaves the web app entirely. The testing guide tells testers to look at out-of-band channels such as email or integrations with external applications that receive and store user input.
  • The scanner has no way to tell which of a thousand pages shows the value it saved ten minutes ago.

None of this means scanners are useless here. It means coverage depends on how you set up the scan.

How to close the gap

  1. Scan while signed in. Many stored inputs sit behind login: profiles, carts, settings, tickets. Use at least two roles so content written by a low-privilege user is also viewed as a higher one.
  2. Use unique markers. Submit a harmless, unique string per field (for example a short random token tied to the field name). Then search every page, export, email and log view for that token and see how it is encoded on the way out.
  3. List every place input is stored. The testing guide names profile pages, shopping carts, file managers, application settings, forums, blogs and logs. Check URL paths, cookies and headers too, not only form fields.
  4. Look at the reading side. For each stored value, find every screen that displays it. The riskiest are the ones staff use.
  5. Check the encoding, not just the alert. If a marker comes back with angle brackets and quotes turned into entities, that context is handled. If it comes back raw, you have a finding even before you prove script execution.
  6. Fix at output. Context-sensitive output encoding is OWASP's primary defense for server-side XSS. Validate input too, but treat that as a second layer.
GapWhat helps
Payload and render on different pagesUnique markers, search across the site afterward
Render page needs a higher roleAuthenticated scans with more than one role
Delayed or moderated displayRe-crawl after the queue runs, test by hand
Output goes to email or exportsManual review of those channels

Try it yourself

Click through it at your own pace, or open it full screen. Watch how a crawl finds forms and what it reports for each input it tests.

Quick check

Can a scanner find stored XSS at all?

Yes, when it can reach both the input and the page that displays it, and when it can match what it stored to where it shows up. It struggles with delayed, role-gated or out-of-band output, so test those by hand.

Is stored XSS worse than reflected XSS?

OWASP describes stored XSS as the most dangerous type because victims need no crafted link and privileged users may be exposed. Severity still depends on who views the data and what the page can do.

If you want a quick look at your dependencies as a starting point, Safeguard offers a free scan at gold.safeguard.sh/scan, and its policies and gates can block risky changes at pull request time.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.