Expand description
contextual output encoding for XSS defense.
this crate provides context-aware encoding functions inspired by the OWASP Java Encoder. each function encodes input for safe embedding in a specific output context (HTML, XML, JavaScript, CSS, URI, Java, or Rust).
disclaimer: contextual-encoder is an independent Rust crate. its API and security model are inspired by the OWASP Java Encoder, but this project is not affiliated with, endorsed by, or maintained by the OWASP Foundation.
§quick start
use contextual_encoder::{for_html, for_javascript, for_css_string, for_uri_component};
let user_input = "<script>alert('xss')</script>";
// safe for HTML text content and quoted attributes
let html_safe = for_html(user_input);
// safe for javascript string literals (universal)
let js_safe = for_javascript(user_input);
// safe for quoted CSS string values
let css_safe = for_css_string(user_input);
// safe as a URI query parameter value
let uri_safe = for_uri_component(user_input);§available contexts
§HTML / XML
| function | safe for |
|---|---|
for_html | text content + quoted attributes |
for_html_content | text content only |
for_html_attribute | quoted attributes only |
for_html_unquoted_attribute | unquoted attribute values |
§XML
| function | safe for |
|---|---|
for_xml | XML text content + quoted attributes (alias for for_html) |
for_xml_content | XML text content only (alias for for_html_content) |
for_xml_attribute | quoted XML attributes only (alias for for_html_attribute) |
for_xml_comment | XML comment content |
for_cdata | CDATA section content |
§XML 1.1
| function | safe for |
|---|---|
for_xml11 | XML 1.1 content + quoted attributes |
for_xml11_content | XML 1.1 content only |
for_xml11_attribute | XML 1.1 quoted attributes only |
§JavaScript
| function | safe for |
|---|---|
for_javascript | all JS contexts (universal) |
for_javascript_attribute | HTML event attributes |
for_javascript_block | <script> blocks |
for_javascript_source | standalone .js files |
§CSS
| function | safe for |
|---|---|
for_css_string | quoted CSS string values |
for_css_url | CSS url() values |
§URI
| function | safe for |
|---|---|
for_uri_component | URI components (query params, path segments) |
§Java
| function | safe for |
|---|---|
for_java | Java string / char literals |
§Rust
| function | safe for |
|---|---|
for_rust_string | Rust string literals ("...") |
for_rust_char | Rust char literals ('...') |
for_rust_byte_string | Rust byte string literals (b"...") |
§security model
this is a contextual output encoder, not a sanitizer. it prevents cross-site scripting by encoding output for specific contexts, but it does not validate or sanitize input.
important caveats:
- encoding is not sanitization. encoding
<script>as<script>makes it display safely in HTML, but does not remove it. if you need to allow a subset of HTML, use a dedicated sanitizer. - context matters. using the wrong encoder for a context can leave
you vulnerable.
for_html_contentoutput is not safe in attributes. - tag and attribute names cannot be encoded. never pass untrusted data as a tag name, attribute name, or event handler name. validate these against a whitelist.
- full URLs must be validated separately.
for_uri_componentencodes a component, not a full URL. ajavascript:URL will be encoded but still execute. always validate the scheme. - template literals. the JavaScript encoders do not encode backticks. never embed untrusted data directly in ES2015+ template literals.
- grave accent. unpatched Internet Explorer treats
`as an attribute delimiter.for_html_unquoted_attributeencodes it, but numeric entities decode back to the original character, so this is not a complete fix. avoid unquoted attributes. - HTML comments. no HTML comment encoder is provided because HTML
comments have vendor-specific extensions (e.g., conditional comments)
that make safe encoding impractical.
for_xml_commentis for XML comments only.
§writer-based API
every for_* function has a corresponding write_* function that writes
to any std::fmt::Write implementor, avoiding allocation when writing to
an existing buffer:
use contextual_encoder::write_html;
let mut buf = String::new();
write_html(&mut buf, "safe & sound").unwrap();
assert_eq!(buf, "safe & sound");Re-exports§
pub use css::for_css_string;pub use css::for_css_url;pub use css::write_css_string;pub use css::write_css_url;pub use html::for_html;pub use html::for_html_attribute;pub use html::for_html_content;pub use html::for_html_unquoted_attribute;pub use html::write_html;pub use html::write_html_attribute;pub use html::write_html_content;pub use html::write_html_unquoted_attribute;pub use java::for_java;pub use java::write_java;pub use javascript::for_javascript;pub use javascript::for_javascript_attribute;pub use javascript::for_javascript_block;pub use javascript::for_javascript_source;pub use javascript::write_javascript;pub use javascript::write_javascript_attribute;pub use javascript::write_javascript_block;pub use javascript::write_javascript_source;pub use rust::for_rust_byte_string;pub use rust::for_rust_char;pub use rust::for_rust_string;pub use rust::write_rust_byte_string;pub use rust::write_rust_char;pub use rust::write_rust_string;pub use uri::for_uri_component;pub use uri::write_uri_component;pub use xml::for_cdata;pub use xml::for_xml;pub use xml::for_xml11;pub use xml::for_xml11_attribute;pub use xml::for_xml11_content;pub use xml::for_xml_attribute;pub use xml::for_xml_comment;pub use xml::for_xml_content;pub use xml::write_cdata;pub use xml::write_xml;pub use xml::write_xml11;pub use xml::write_xml11_attribute;pub use xml::write_xml11_content;pub use xml::write_xml_attribute;pub use xml::write_xml_comment;pub use xml::write_xml_content;