pub fn for_html_unquoted_attribute(input: &str) -> StringExpand description
encodes input for safe embedding in an unquoted HTML attribute value.
this is the most aggressive HTML encoder, encoding whitespace, quote characters, grave accents, and many punctuation characters that could terminate an unquoted attribute value.
prefer quoted attributes whenever possible. unquoted attributes are fragile and this encoder exists only for cases where quoting is not an option.
§caveat: grave accent
the grave accent (`, U+0060) is encoded as ` because
unpatched internet explorer treats it as an attribute delimiter.
however, numeric character references decode back to the original
character, so this encoding cannot fully protect against the IE bug
in all injection scenarios. the safest mitigation is to avoid
unquoted attributes entirely.
§encoded characters (partial list)
| input | output |
|---|---|
| tab | 	 |
| LF | |
| FF |  |
| CR | |
| space |   |
& | & |
< | < |
> | > |
" | " |
' | ' |
/ | / |
= | = |
` | ` |
C0/C1 control characters, DEL, and unicode non-characters are replaced
with -. NEL (U+0085) is encoded as …. line separator (U+2028)
and paragraph separator (U+2029) are encoded as 
 and 
.
§examples
use contextual_encoder::for_html_unquoted_attribute;
assert_eq!(for_html_unquoted_attribute("hello world"), "hello world");
assert_eq!(for_html_unquoted_attribute("a=b"), "a=b");Examples found in repository?
17fn main() {
18 let input = r#"<script>alert("xss")</script>"#;
19
20 println!("input: {input}");
21 println!();
22
23 // -----------------------------------------------------------------------
24 // comparison: same input across all encoders
25 // -----------------------------------------------------------------------
26
27 // html text content AND quoted attributes (safe default when unsure)
28 println!("--- html ---");
29 println!(" for_html: {}", for_html(input));
30
31 // html text nodes only — does NOT encode quotes, so never use in attributes
32 println!(
33 " for_html_content: {}",
34 for_html_content(input)
35 );
36
37 // quoted attribute values only — does NOT encode >, slightly more minimal
38 println!(
39 " for_html_attribute: {}",
40 for_html_attribute(input)
41 );
42
43 // unquoted attribute values — most aggressive, encodes whitespace/grave/etc.
44 println!(
45 " for_html_unquoted_attribute: {}",
46 for_html_unquoted_attribute(input)
47 );
48 println!();
49
50 // universal js encoder — safe in event attrs, <script> blocks, and .js files
51 println!("--- javascript ---");
52 println!(" for_javascript: {}", for_javascript(input));
53
54 // html event attributes (onclick="...") — does not escape /
55 println!(
56 " for_javascript_attribute: {}",
57 for_javascript_attribute(input)
58 );
59
60 // <script> blocks — uses \" and \' (not safe in html attributes)
61 println!(
62 " for_javascript_block: {}",
63 for_javascript_block(input)
64 );
65
66 // standalone .js / json files — minimal, NOT safe in any html context
67 println!(
68 " for_javascript_source: {}",
69 for_javascript_source(input)
70 );
71
72 // ES6 template literals (`...`) — escapes backtick and ${} interpolation
73 let template_input = r#"`Hello ${name}`, welcome</script>"#;
74 println!(
75 " for_js_template: {}",
76 for_js_template(template_input)
77 );
78 println!();
79
80 // quoted css string values, e.g., content: "..." or font-family: "..."
81 println!("--- css ---");
82 println!(" for_css_string: {}", for_css_string(input));
83
84 // css url() values — like for_css_string but parens pass through
85 println!(" for_css_url: {}", for_css_url(input));
86 println!();
87
88 // uri component (query params, path segments) — NOT for full urls
89 println!("--- uri ---");
90 println!(
91 " for_uri_component: {}",
92 for_uri_component(input)
93 );
94 println!();
95
96 // xml 1.0 aliases — identical to the html encoders
97 println!("--- xml 1.0 ---");
98 println!(" for_xml: {}", for_xml(input));
99 println!(" for_xml_content: {}", for_xml_content(input));
100 println!(
101 " for_xml_attribute: {}",
102 for_xml_attribute(input)
103 );
104
105 // xml-only contexts
106 println!(" for_xml_comment: {}", for_xml_comment(input));
107 println!(" for_cdata: {}", for_cdata(input));
108 println!();
109
110 // xml 1.1 — restricted chars get &#xHH; instead of space
111 println!("--- xml 1.1 ---");
112 let xml11_input = "a\x01b<c>";
113 println!(" for_xml11: {}", for_xml11(xml11_input));
114 println!(
115 " for_xml11_content: {}",
116 for_xml11_content(xml11_input)
117 );
118 println!(
119 " for_xml11_attribute: {}",
120 for_xml11_attribute(xml11_input)
121 );
122 println!();
123
124 // rust literals — \xHH escapes, UTF-8 byte encoding for byte strings
125 println!("--- rust ---");
126 println!(" for_rust_string: {}", for_rust_string(input));
127 println!(" for_rust_char: {}", for_rust_char(input));
128 println!(
129 " for_rust_byte_string: {}",
130 for_rust_byte_string(input)
131 );
132 println!();
133
134 // json string value — \\uXXXX escapes for control chars and specials
135 println!("--- json ---");
136 println!(" for_json: {}", for_json(input));
137 println!();
138
139 // sql string literals — single-quote doubling (standard) or backslash escaping (mysql)
140 println!("--- sql ---");
141 println!(" for_sql: {}", for_sql(input));
142 println!(
143 " for_sql_backslash: {}",
144 for_sql_backslash(input)
145 );
146
147 // -----------------------------------------------------------------------
148 // practical: one realistic input per sink, correct encoder for each
149 // -----------------------------------------------------------------------
150
151 let user_name = r#"Bob <img src=x onerror="alert(1)">"#;
152 let user_query = "hello world & goodbye";
153 let user_text = r#"hi from </script><script>alert(1)</script>"#;
154 let user_css_text = r#"hello "css" \ test"#;
155
156 println!("--- practical usage ---");
157
158 // html text node — for_html_content is the right encoder
159 println!(r#" <p>{}</p>"#, for_html_content(user_name));
160
161 // nested context: uri component inside an html attribute.
162 // encode from inside out: first percent-encode the query value,
163 // then html-attribute-encode the entire href.
164 let href = format!("/search?q={}", for_uri_component(user_query));
165 println!(r#" <a href="{}">search</a>"#, for_html_attribute(&href),);
166
167 // actual css string context: a quoted content value in a stylesheet
168 println!(
169 r#" <style>.msg::after {{ content: "{}"; }}</style>"#,
170 for_css_string(user_css_text),
171 );
172
173 // javascript string inside an event-handler attribute
174 println!(
175 r#" <button onclick="greet('{}');">hi</button>"#,
176 for_javascript_attribute(user_text),
177 );
178}