Inline event handlers and scripts

The page relies on inline scripts, on* event-handler attributes or javascript: URLs. These are not vulnerabilities by themselves, but they prevent deploying a Content-Security-Policy that would actually stop XSS.

Do this: Move inline handlers into a script file so CSP can block injection. Inline handlers force 'unsafe-inline' in the CSP, which is what makes injected script run.
PassThe page uses no inline event handlers or javascript: URLs.
InfoThe page contains inline scripts, event-handler attributes or javascript: URLs.

The fix, in one snippet

Example to adapt Move the handler into a file
<!-- before --> <button onclick="save()">Save</button>
<!-- after  --> <button id="save">Save</button>
<script src="/app.js"></script>   // document.getElementById('save').addEventListener('click', save)

Illustrative values. Change the paths, hostnames and options to match your own site before using it.

The sections below explain what is tested, why it matters and the alternatives.

What we test

Scan.now parses the homepage and counts three constructs: <script> blocks without a src attribute, HTML attributes beginning with on (onclick, onload, onerror, and so on), and href or src values beginning with javascript:. The result is informational: it reports the counts and a few examples, and notes whether the current Content-Security-Policy, if any, allows them through 'unsafe-inline' or through nonces and hashes. The reason this inventory exists is that the constructs determine which CSP you can deploy. Nonces cover inline <script> blocks but not event-handler attributes or javascript: URLs, which need 'unsafe-hashes' plus a hash of each handler's text. Related checks: content-security-policy and csp-weak-directives.

Why it matters

A Content-Security-Policy stops cross-site scripting by refusing to run script that does not come from an approved source, and in practice the biggest obstacle to enforcing one is a codebase full of inline handlers. Teams discover that a strict policy breaks the site, add 'unsafe-inline' to make it work, and end up with a policy that permits exactly the injected inline script CSP was meant to block. Inline handlers are also where injection bugs tend to sit in server-rendered templates: a value interpolated into onclick="show('...')" is in a double context (HTML attribute and JavaScript string) that ordinary HTML escaping does not protect. Moving behaviour into external files or nonce-carrying blocks makes both problems tractable. The CSP guide describes the migration path and the XSS guide the attack it defends against.

How to fix it

Replace attribute handlers with listeners registered from a script file. Before:

<button onclick="openMenu()">Menu</button>
<a href='javascript:void(0)' onclick="track('cta')">Start</a>

After:

<button id="menu-btn">Menu</button>
<a href='/start' data-track="cta">Start</a>
<script src="/js/ui.js" defer></script>

// ui.js
document.getElementById('menu-btn').addEventListener('click', openMenu);
document.querySelectorAll('[data-track]').forEach(el =>
  el.addEventListener('click', () => track(el.dataset.track)));

Inline blocks that must stay inline (configuration, analytics bootstraps) get a per-response nonce:

<script nonce="{RANDOM}">window.config = {...};</script>

For a handler you cannot yet move, CSP Level 3 allows it by hash: script-src 'unsafe-hashes' 'sha256-<hash of the handler text>'. Deploy the target policy as Content-Security-Policy-Report-Only first; every violation report points at one inline construct to migrate. Modern frameworks (React, Vue, Svelte) attach handlers programmatically and produce none of these, so a rebuild on one of them clears the finding as a side effect.

Where this fits

Inline event handlers and scripts is check 8 of 10 that the website vulnerability scanner runs under page content and javascript, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.

Fix this one first

Above it in the same category sits Third-party scripts without Subresource Integrity (low), where scripts or stylesheets are loaded from third-party hosts without an integrity attribute. An attacker who has that does not need this, so it is the better use of the same hour.

What fixing this still leaves open

Inline event handlers and scripts closes one route in. Immediately below it: Password field autocomplete, where password fields on the page either try to disable autocomplete, which browsers ignore and password managers dislike, or lack the autocomplete tokens that let password managers fill and generate credentials safely; Third-party script inventory, where an inventory of every script the page loads from other domains.

Found in the same scan

The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and Exposed .env configuration file, where a .env configuration file is served from the web root. A single run of website vulnerability scanner answers all of them at once.

Prompt for an AI Hand this check to an assistant Sign in to copy it
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.

Finding: Inline event handlers and scripts (info severity)
Scanner check id: inline-event-handlers
19 more lines, including the evidence and the exact fix

The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.

Sign in with Google

Signing in is free and takes one click. We store your email address and nothing else.

References

  1. MDN: CSP script-src, unsafe-hashes
  2. web.dev: Mitigate XSS with a strict CSP
  3. Google CSP Evaluator

Related guides