Diagnostics

LUM4009: Unsafe URL blocked in a URL attribute

A dynamic value for a URL attribute would run script, so Lumiose rendered a placeholder instead.

Severity: warning · Category: islands and boundaries (4xxx)

Reported by: the runtime (lumiose/dom and lumiose/server), as a console warning in development. The value is blocked in production too, without the warning.

#What it means

A URL attribute (href, src, action, formaction, xlink:href, poster, data, cite, background, …) got a value from an expression whose scheme is javascript:, vbscript: or data:text/html. Such a URL runs script in your page when it is followed, which is how injected links turn into cross-site scripting. Lumiose writes about:blank#blocked instead, on the server and in the browser alike (decision-29). The check ignores case, leading spaces and control characters, and tabs or newlines inside the scheme, as browsers do.

Only dynamic values are checked. A string literal in your JSX (<a href="javascript:void 0">) is written as it is.

#Example

tsx
export function Profile(props: { website: string }) {
  // A user who saves "javascript:alert(document.cookie)" as their website gets a dead link.
  return <a href={props.website}>Website</a>;
}

#How to fix it

  • Run code with an event handler, not a script URL: <button onClick={save}>.
  • For user-supplied links, validate the URL when you store it, and accept only http: and https: (new URL(value).protocol).