Skip to content

Commit c70b32f

Browse files
committed
Python: Require quote escaping for html.escape
1 parent 00dc55d commit c70b32f

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4851,7 +4851,19 @@ module StdlibPrivate {
48514851
* See https://docs.python.org/3/library/html.html#html.escape
48524852
*/
48534853
private class HtmlEscapeCall extends Escaping::Range, API::CallNode {
4854-
HtmlEscapeCall() { this = API::moduleImport("html").getMember("escape").getACall() }
4854+
HtmlEscapeCall() {
4855+
this = API::moduleImport("html").getMember("escape").getACall() and
4856+
// if quote escaping is disabled, that might lead to XSS if the result is inserted
4857+
// in the attribute value of a tag, such as `<foo bar="escape_result">`. Since we
4858+
// don't know how values are being inserted, and we don't want to lose these
4859+
// results (FNs), we require quote escaping to be enabled. This might lead to some
4860+
// FPs, so we might need to revisit this in the future.
4861+
not this.getParameter(1, "quote")
4862+
.getAValueReachingSink()
4863+
.asExpr()
4864+
.(ImmutableLiteral)
4865+
.booleanValue() = false
4866+
}
48554867

48564868
override DataFlow::Node getAnInput() { result = this.getParameter(0, "s").asSink() }
48574869

python/ql/test/library-tests/frameworks/stdlib/test_html.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
html.escape(s) # $ escapeInput=s escapeKind=html escapeOutput=html.escape(..)
66
html.escape(s, True) # $ escapeInput=s escapeKind=html escapeOutput=html.escape(..)
7-
html.escape(s, False) # $ escapeInput=s escapeKind=html escapeOutput=html.escape(..)
8-
html.escape(s, quote=False) # $ escapeInput=s escapeKind=html escapeOutput=html.escape(..)
7+
# not considered html escapes, since they don't escape all relevant characters
8+
html.escape(s, False)
9+
html.escape(s, quote=False)

0 commit comments

Comments
 (0)