Skip to content

Commit e74eccd

Browse files
committed
Swift: Get the query 'working' (though lots of issues with results right now).
1 parent 38ecfd8 commit e74eccd

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

swift/ql/src/queries/Security/CWE-116/BadTagFilter.ql

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @problem.severity warning
66
* @security-severity 7.8
77
* @precision high
8-
* @id rb/bad-tag-filter
8+
* @id swift/bad-tag-filter
99
* @tags correctness
1010
* security
1111
* external/cwe/cwe-116
@@ -14,9 +14,12 @@
1414
* external/cwe/cwe-186
1515
*/
1616

17-
private import codeql.ruby.regexp.RegExpTreeView::RegexTreeView as TreeView
17+
import codeql.swift.regex.Regex
18+
private import codeql.swift.regex.RegexTreeView::RegexTreeView as TreeView
1819
import codeql.regex.nfa.BadTagFilterQuery::Make<TreeView>
1920

2021
from HtmlMatchingRegExp regexp, string msg
21-
where msg = min(string m | isBadRegexpFilter(regexp, m) | m order by m.length(), m) // there might be multiple, we arbitrarily pick the shortest one
22+
where
23+
// there might be multiple messages, we arbitrarily pick the shortest one
24+
msg = min(string m | isBadRegexpFilter(regexp, m) | m order by m.length(), m)
2225
select regexp, msg
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
| test.swift:79:26:79:48 | <script.*?>.*?<\\/script> | This regular expression does not match upper case <SCRIPT> tags. |
2+
| test.swift:87:26:87:53 | <script.*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
3+
| test.swift:91:26:91:33 | <!--.*--> | This regular expression does not match comments containing newlines. |
4+
| test.swift:95:26:95:35 | <!--.*--!?> | This regular expression does not match comments containing newlines. |
5+
| test.swift:99:26:99:35 | <!--.*--!?> | This regular expression does not match comments containing newlines. |
6+
| test.swift:103:26:103:58 | <script.*?>(.\|\\s)*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
7+
| test.swift:107:26:107:56 | <script[^>]*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
8+
| test.swift:111:26:111:63 | <script(\\s\|\\w\|=\|")*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
9+
| test.swift:118:28:118:65 | <script(\\s\|\\w\|=\|')*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
10+
| test.swift:122:50:122:87 | <script(\\s\|\\w\|=\|')*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
11+
| test.swift:129:28:129:69 | <script( \|\\n\|\\w\|=\|'\|")*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
12+
| test.swift:133:50:133:91 | <script( \|\\n\|\\w\|=\|'\|")*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
13+
| test.swift:140:28:140:55 | <script.*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
14+
| test.swift:143:50:143:77 | <script.*?>.*?<\\/script[^>]*> | This regular expression does not match upper case <SCRIPT> tags. |
15+
| test.swift:150:28:150:73 | <(script\|SCRIPT).*?>.*?<\\/(script\|SCRIPT)[^>]*> | This regular expression does not match mixed case <sCrIpT> tags. |
16+
| test.swift:153:50:153:95 | <(script\|SCRIPT).*?>.*?<\\/(script\|SCRIPT)[^>]*> | This regular expression does not match mixed case <sCrIpT> tags. |
17+
| test.swift:160:28:160:60 | <script[^>]*?>[\\s\\S]*?<\\/script.*> | This regular expression does not match upper case <SCRIPT> tags. |
18+
| test.swift:163:50:163:82 | <script[^>]*?>[\\s\\S]*?<\\/script.*> | This regular expression does not match upper case <SCRIPT> tags. |
19+
| test.swift:170:28:170:64 | <script[^>]*?>[\\s\\S]*?<\\/script[^>]*?> | This regular expression does not match upper case <SCRIPT> tags. |
20+
| test.swift:173:50:173:86 | <script[^>]*?>[\\s\\S]*?<\\/script[^>]*?> | This regular expression does not match upper case <SCRIPT> tags. |
21+
| test.swift:177:27:177:68 | <(?:!--([\\S\|\\s]*?)-->)\|([^\\/\\s>]+)[\\S\\s]*?> | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 1 and comments ending with --!> are matched with capture group 2. |
22+
| test.swift:180:50:180:91 | <(?:!--([\\S\|\\s]*?)-->)\|([^\\/\\s>]+)[\\S\\s]*?> | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 1 and comments ending with --!> are matched with capture group 2. |
23+
| test.swift:184:27:184:167 | <(?:(?:\\/([^>]+)>)\|(?:!--([\\S\|\\s]*?)-->)\|(?:([^\\/\\s>]+)((?:\\s+[\\w\\-:.]+(?:\\s*=\\s*?(?:(?:"[^"]*")\|(?:'[^']*')\|[^\\s"'\\/>]+))?)*)[\\S\\s]*?(\\/?)>)) | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 2 and comments ending with --!> are matched with capture group 3, 4. |
24+
| test.swift:187:50:187:190 | <(?:(?:\\/([^>]+)>)\|(?:!--([\\S\|\\s]*?)-->)\|(?:([^\\/\\s>]+)((?:\\s+[\\w\\-:.]+(?:\\s*=\\s*?(?:(?:"[^"]*")\|(?:'[^']*')\|[^\\s"'\\/>]+))?)*)[\\S\\s]*?(\\/?)>)) | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 2 and comments ending with --!> are matched with capture group 3, 4. |
25+
| test.swift:191:51:191:84 | <script\\b[^>]*>([\\s\\S]*?)<\\/script> | This regular expression does not match upper case <SCRIPT> tags. |
26+
| test.swift:195:51:195:104 | (<[a-z\\/!$]("[^"]*"\|'[^']*'\|[^'">])*>\|<!(--.*?--\\s*)+>) | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 3 and comments ending with --!> are matched with capture group 1. |
27+
| test.swift:199:51:199:293 | <(?:(?:!--([\\w\\W]*?)-->)\|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)\|(?:!DOCTYPE([\\w\\W]*?)>)\|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)\|(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)\|(?:([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)((?:\\s+[^"'>]+(?:(?:"[^"]*")\|(?:'[^']*')\|[^>]*))*\|\\/\|\\s+)>)) | This regular expression only parses --> (capture group 1) and not --!> as an HTML comment end tag. |
28+
| test.swift:203:51:203:77 | <!--([\\w\\W]*?)-->\|<([^>]*?)> | Comments ending with --> are matched differently from comments ending with --!>. The first is matched with capture group 1 and comments ending with --!> are matched with capture group 2. |
29+
| test.swift:207:51:207:93 | <script([^>]*)>([\\\\S\\\\s]*?)<\\/script([^>]*)> | This regular expression does not match script end tags like </script >. |
30+
| test.swift:211:51:211:52 | --> | This regular expression only parses --> and not --!> as a HTML comment end tag. |

swift/ql/test/query-tests/Security/CWE-116/test.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,19 @@ func myRegexpVariantsTests(myUrl: URL) throws {
7979
let re1 = try Regex(#"<script.*?>.*?<\/script>"#).ignoresCase(true)
8080
_ = try re1.firstMatch(in: tainted)
8181

82-
// BAD - doesn't match `</script >`
82+
// BAD - doesn't match `</script >` [NOT DETECTED]
8383
let re2 = try Regex(#"<script.*?>.*?<\/script>/is"#).ignoresCase(true)
8484
_ = try re2.firstMatch(in: tainted)
8585

86-
// GOOD
86+
// GOOD [FALSE POSITIVE]
8787
let re3 = try Regex(#"<script.*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true)
8888
_ = try re3.firstMatch(in: tainted)
8989

90-
// GOOD - we don't care regexps that only match comments
90+
// GOOD - we don't care regexps that only match comments [FALSE POSITIVE]
9191
let re4 = try Regex(#"<!--.*-->"#).ignoresCase(true).dotMatchesNewlines(true)
9292
_ = try re4.firstMatch(in: tainted)
9393

94-
// GOOD
94+
// GOOD [FALSE POSITIVE]
9595
let re5 = try Regex(#"<!--.*--!?>"#).ignoresCase(true).dotMatchesNewlines(true)
9696
_ = try re5.firstMatch(in: tainted)
9797

@@ -111,7 +111,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
111111
let re9 = try Regex(#"<script(\s|\w|=|")*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true)
112112
_ = try re9.firstMatch(in: tainted)
113113

114-
// BAD - does not match double quotes for attribute values
114+
// BAD - does not match double quotes for attribute values [NOT DETECTED]
115115
let re10a = try Regex(#"(?is)<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#)
116116
_ = try re10a.firstMatch(in: tainted)
117117
// BAD - does not match double quotes for attribute values
@@ -122,7 +122,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
122122
let ns10 = try NSRegularExpression(pattern: #"<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#, options: options10)
123123
_ = ns10.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
124124

125-
// BAD - does not match tabs between attributes
125+
// BAD - does not match tabs between attributes [NOT DETECTED]
126126
let re11a = try Regex(#"(?is)<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#)
127127
_ = try re11a.firstMatch(in: tainted)
128128
// BAD - does not match tabs between attributes
@@ -133,7 +133,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
133133
let ns11 = try NSRegularExpression(pattern: #"<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#, options: options11)
134134
_ = ns11.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
135135

136-
// BAD - does not match uppercase SCRIPT tags
136+
// BAD - does not match uppercase SCRIPT tags [NOT DETECTED]
137137
let re12a = try Regex(#"(?s)<script.*?>.*?<\/script[^>]*>"#)
138138
_ = try re12a.firstMatch(in: tainted)
139139
// BAD - does not match uppercase SCRIPT tags
@@ -143,7 +143,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
143143
let ns12 = try NSRegularExpression(pattern: #"<script.*?>.*?<\/script[^>]*>"#, options: .dotMatchesLineSeparators)
144144
_ = ns12.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
145145

146-
// BAD - does not match mixed case script tags
146+
// BAD - does not match mixed case script tags [NOT DETECTED]
147147
let re13a = try Regex(#"(?s)<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#)
148148
_ = try re13a.firstMatch(in: tainted)
149149
// BAD - does not match mixed case script tags
@@ -153,7 +153,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
153153
let ns13 = try NSRegularExpression(pattern: #"<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#, options: .dotMatchesLineSeparators)
154154
_ = ns13.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
155155

156-
// BAD - doesn't match newlines in the end tag
156+
// BAD - doesn't match newlines in the end tag [NOT DETECTED]
157157
let re14a = try Regex(#"(?i)<script[^>]*?>[\s\S]*?<\/script.*>"#)
158158
_ = try re14a.firstMatch(in: tainted)
159159
// BAD - doesn't match newlines in the end tag
@@ -166,10 +166,10 @@ func myRegexpVariantsTests(myUrl: URL) throws {
166166
// GOOD
167167
let re15a = try Regex(#"(?i)<script[^>]*?>[\s\S]*?<\/script[^>]*?>"#)
168168
_ = try re15a.firstMatch(in: tainted)
169-
// GOOD
169+
// GOOD [FALSE POSITIVE]
170170
let re15b = try Regex(#"<script[^>]*?>[\s\S]*?<\/script[^>]*?>"#).ignoresCase(true)
171171
_ = try re15b.firstMatch(in: tainted)
172-
// GOOD
172+
// GOOD [FALSE POSITIVE]
173173
let ns15 = try NSRegularExpression(pattern: #"<script[^>]*?>[\s\S]*?<\/script[^>]*?>"#, options: .caseInsensitive)
174174
_ = ns15.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
175175

@@ -203,7 +203,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
203203
let ns2_4 = try NSRegularExpression(pattern: #"<!--([\w\W]*?)-->|<([^>]*?)>"#)
204204
_ = ns2_4.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
205205

206-
// GOOD - it's used with the ignorecase flag
206+
// GOOD - it's used with the ignorecase flag [FALSE POSITIVE]
207207
let ns2_5 = try NSRegularExpression(pattern: #"<script([^>]*)>([\\S\\s]*?)<\/script([^>]*)>"#, options: .caseInsensitive)
208208
_ = ns2_5.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
209209

0 commit comments

Comments
 (0)