aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askama/src/lib.rs11
-rw-r--r--askama_shared/src/escaping.rs7
-rw-r--r--testing/tests/filters.rs7
3 files changed, 16 insertions, 9 deletions
diff --git a/askama/src/lib.rs b/askama/src/lib.rs
index d56326c..04c73f6 100644
--- a/askama/src/lib.rs
+++ b/askama/src/lib.rs
@@ -44,10 +44,13 @@
//! (`none`), the parsed syntax tree (`ast`), the generated code (`code`)
//! or `all` for both. The requested data will be printed to stdout at
//! compile time.
-//! * `escape` (as `escape = "none"`): disable escaping of expression output.
-//! By default, Askama escapes `&`, `<` and `>` to their corresponding
-//! HTML character entities. This can be enabled explicitly by setting this
-//! value to `html` or disabled by setting it to `none`.
+//! * `escape` (as `escape = "none"`): change escape mode for expression
+//! output. By default, Askama escapes content according to the [OWASP
+//! escaping recommendations][owasp]. This can be enabled explicitly by
+//! setting this value to `html` or disabled by setting it to `none`.
+//!
+//! [owasp]: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content
+//!
//!
//! ## Variables
//!
diff --git a/askama_shared/src/escaping.rs b/askama_shared/src/escaping.rs
index ed4b3d7..a8a3559 100644
--- a/askama_shared/src/escaping.rs
+++ b/askama_shared/src/escaping.rs
@@ -42,7 +42,7 @@ impl<T> Display for MarkupDisplay<T> where T: Display {
fn escapable(b: &u8) -> bool {
- *b == b'<' || *b == b'>' || *b == b'&'
+ *b == b'<' || *b == b'>' || *b == b'&' || *b == b'"' || *b == b'\'' || *b == b'/'
}
pub fn escape(s: String) -> String {
@@ -57,7 +57,7 @@ pub fn escape(s: String) -> String {
}
let bytes = s.as_bytes();
- let max_len = bytes.len() + found.len() * 3;
+ let max_len = bytes.len() + found.len() * 5;
let mut res = Vec::<u8>::with_capacity(max_len);
let mut start = 0;
for idx in &found {
@@ -69,6 +69,9 @@ pub fn escape(s: String) -> String {
b'<' => { res.extend(b"&lt;"); },
b'>' => { res.extend(b"&gt;"); },
b'&' => { res.extend(b"&amp;"); },
+ b'"' => { res.extend(b"&quot;"); },
+ b'\'' => { res.extend(b"&#x27;"); },
+ b'/' => { res.extend(b"&#x2f;"); },
_ => panic!("incorrect indexing"),
}
}
diff --git a/testing/tests/filters.rs b/testing/tests/filters.rs
index 8e558ba..fe218e3 100644
--- a/testing/tests/filters.rs
+++ b/testing/tests/filters.rs
@@ -16,15 +16,16 @@ struct TestTemplate {
#[test]
fn filter_escape() {
let s = TestTemplate {
- strvar: "my <html> is unsafe & should be escaped".to_string(),
+ strvar: "// my <html> is \"unsafe\" & should be 'escaped'".to_string(),
};
assert_eq!(s.render().unwrap(),
- "my &lt;html&gt; is unsafe &amp; should be escaped");
+ "&#x2f;&#x2f; my &lt;html&gt; is &quot;unsafe&quot; &amp; \
+ should be &#x27;escaped&#x27;");
}
#[derive(Template)]
-#[template(path = "format.html")]
+#[template(path = "format.html", escape = "none")]
struct FormatTemplate<'a> {
var: &'a str,
}