defmodule StripJs do
@moduledoc ~S"""
StripJs is an Elixir module for stripping executable JavaScript from
blocks of HTML and CSS, based on the Floki parsing library.
It handles:
* `` and `` tags
* Event handler attributes such as `onclick="..."`
* `javascript:...` URLs in HTML and CSS
* CSS `expression(...)` directives
* HTML entity attacks (like `<script>`)
StripJs is production ready, and has sanitized over 1.5 billion payloads
at Appcues.
## Installation
Add `strip_js` to your application's `mix.exs`:
def application do
[applications: [:strip_js]]
end
def deps do
[{:strip_js, "~> #{StripJs.Mixfile.project()[:version]}"}]
end
## Usage
`clean_html/2` removes all JS vectors from an HTML string:
iex> html = ""
iex> StripJs.clean_html(html)
""
`clean_css/2` removes all JS vectors from a CSS string:
iex> css = "body { background-image: url('javascript:alert()'); }"
iex> StripJs.clean_css(css)
"body { background-image: url('removed_by_strip_js:alert()'); }"
StripJs relies on the [Floki](https://github.com/philss/floki)
HTML parser library, which is built using
[Mochiweb](https://github.com/mochi/mochiweb) by default.
StripJs provides a `clean_html_tree/1` function to strip JS from
`Floki.parse_fragment/1`- and `:mochiweb_html.parse/1`- style HTML parse trees.
## Security
StripJs blocks every JS injection vector known to the authors. It has
survived four years in production, multiple professional penetration
tests, and over a billion invocations with no known security issues.
If you believe there are JS injection methods not covered by this library,
please submit an issue with a test case!
## Bugs and Limitations
The brokenness of invalid HTML may be amplified by `clean_html/2`.
In uncommon cases, innocent CSS which very closely resembles
JS-injection techniques may be mangled by `clean_css/2`.
## Authorship and License
Copyright 2017-2021, Appcues, Inc.
Project homepage:
[StripJs](https://github.com/appcues/strip_js)
StripJs is released under the
[MIT License](https://opensource.org/licenses/MIT).
"""
require Logger
# reserved for future use
@type opts :: Keyword.t()
@type html_tag :: String.t()
@type html_attr :: {String.t(), String.t()}
@type html_node :: String.t() | {html_tag, [html_attr], [html_node]}
@type html_tree :: html_node | [html_node]
@doc ~S"""
Removes JS vectors from the given HTML string.
All non-tag text and tag attribute values will be HTML-escaped, except
for the contents of `