@@ -25,28 +25,43 @@ module ReflectedXss {
25
25
* is to prevent us from flagging plain-text or JSON responses as vulnerable.
26
26
*/
27
27
class HttpResponseSink extends Sink instanceof Http:: ResponseSendArgument {
28
- HttpResponseSink ( ) { not exists ( getANonHtmlHeaderDefinition ( this ) ) }
28
+ HttpResponseSink ( ) { not exists ( getAXSSSafeHeaderDefinition ( this ) ) }
29
29
}
30
30
31
31
/**
32
- * Gets a HeaderDefinition that defines a non-html content-type for `send`.
32
+ * Gets a HeaderDefinition that defines a XSS safe content-type for `send`.
33
33
*/
34
- Http:: HeaderDefinition getANonHtmlHeaderDefinition ( Http:: ResponseSendArgument send ) {
34
+ Http:: HeaderDefinition getAXSSSafeHeaderDefinition ( Http:: ResponseSendArgument send ) {
35
35
exists ( Http:: RouteHandler h |
36
36
send .getRouteHandler ( ) = h and
37
- result = nonHtmlContentTypeHeader ( h )
37
+ result = xssSafeContentTypeHeader ( h )
38
38
|
39
39
// The HeaderDefinition affects a response sent at `send`.
40
40
headerAffects ( result , send )
41
41
)
42
42
}
43
43
44
44
/**
45
- * Holds if `h` may send a response with a content type other than HTML.
45
+ * A content-type that may lead to javascript code being executed in the browser.
46
+ * ref: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#content-types
46
47
*/
47
- Http:: HeaderDefinition nonHtmlContentTypeHeader ( Http:: RouteHandler h ) {
48
+ string xssUnsafeContentType ( ) {
49
+ result =
50
+ [
51
+ "text/html" , "application/xhtml+xml" , "application/xml" , "text/xml" , "image/svg+xml" ,
52
+ "text/xsl" , "application/vnd.wap.xhtml+xml" , "text/rdf" , "application/rdf+xml" ,
53
+ "application/mathml+xml" , "text/vtt" , "text/cache-manifest"
54
+ ]
55
+ }
56
+
57
+ /**
58
+ * Holds if `h` may send a response with a content type that is safe for XSS.
59
+ */
60
+ Http:: HeaderDefinition xssSafeContentTypeHeader ( Http:: RouteHandler h ) {
48
61
result = h .getAResponseHeader ( "content-type" ) and
49
- not exists ( string tp | result .defines ( "content-type" , tp ) | tp .regexpMatch ( "(?i).*html.*" ) )
62
+ not exists ( string tp | result .defines ( "content-type" , tp ) |
63
+ tp .toLowerCase ( ) .matches ( xssUnsafeContentType ( ) + "%" )
64
+ )
50
65
}
51
66
52
67
/**
0 commit comments