mirror of
https://github.com/github/codeql.git
synced 2026-06-12 08:21:09 +02:00
Compare commits
9 Commits
mario-camp
...
copilot/co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d73a911d74 | ||
|
|
de8b3360bc | ||
|
|
ad18659373 | ||
|
|
923fe2dcb9 | ||
|
|
2884428b62 | ||
|
|
e10750b35e | ||
|
|
18550039f2 | ||
|
|
0caa483925 | ||
|
|
640b17ec78 |
@@ -2,7 +2,7 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
## 0.4.36
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
## 0.6.28
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added `UseMemoDirective` and `UseNoMemoDirective` classes to model the React compiler directives `"use memo"` and `"use no memo"`.
|
||||
@@ -435,6 +435,32 @@ module Directive {
|
||||
UseClientDirective() { this.getDirectiveText() = "use client" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `use memo` directive.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* "use memo";
|
||||
* ```
|
||||
*/
|
||||
class UseMemoDirective extends KnownDirective {
|
||||
UseMemoDirective() { this.getDirectiveText() = "use memo" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `use no memo` directive.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* "use no memo";
|
||||
* ```
|
||||
*/
|
||||
class UseNoMemoDirective extends KnownDirective {
|
||||
UseNoMemoDirective() { this.getDirectiveText() = "use no memo" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `use cache` directive.
|
||||
*
|
||||
|
||||
@@ -3,14 +3,18 @@
|
||||
| tst.js:3:1:3:9 | 'bundle'; | bundle |
|
||||
| tst.js:4:1:4:13 | 'use server'; | use server |
|
||||
| tst.js:5:1:5:13 | 'use client'; | use client |
|
||||
| tst.js:6:1:6:12 | 'use cache'; | use cache |
|
||||
| tst.js:7:1:7:20 | 'use cache: remote'; | use cache: remote |
|
||||
| tst.js:8:1:8:21 | 'use ca ... ivate'; | use cache: private |
|
||||
| tst.js:17:3:17:12 | 'use asm'; | use asm |
|
||||
| tst.js:18:3:18:11 | 'bundle'; | bundle |
|
||||
| tst.js:19:3:19:15 | 'use server'; | use server |
|
||||
| tst.js:20:3:20:15 | 'use client'; | use client |
|
||||
| tst.js:21:3:21:14 | 'use cache'; | use cache |
|
||||
| tst.js:22:3:22:22 | 'use cache: remote'; | use cache: remote |
|
||||
| tst.js:23:3:23:23 | 'use ca ... ivate'; | use cache: private |
|
||||
| tst.js:30:5:30:17 | 'use strict'; | use strict |
|
||||
| tst.js:6:1:6:11 | 'use memo'; | use memo |
|
||||
| tst.js:7:1:7:14 | 'use no memo'; | use no memo |
|
||||
| tst.js:8:1:8:12 | 'use cache'; | use cache |
|
||||
| tst.js:9:1:9:20 | 'use cache: remote'; | use cache: remote |
|
||||
| tst.js:10:1:10:21 | 'use ca ... ivate'; | use cache: private |
|
||||
| tst.js:19:3:19:12 | 'use asm'; | use asm |
|
||||
| tst.js:20:3:20:11 | 'bundle'; | bundle |
|
||||
| tst.js:21:3:21:15 | 'use server'; | use server |
|
||||
| tst.js:22:3:22:15 | 'use client'; | use client |
|
||||
| tst.js:23:3:23:13 | 'use memo'; | use memo |
|
||||
| tst.js:24:3:24:16 | 'use no memo'; | use no memo |
|
||||
| tst.js:25:3:25:14 | 'use cache'; | use cache |
|
||||
| tst.js:26:3:26:22 | 'use cache: remote'; | use cache: remote |
|
||||
| tst.js:27:3:27:23 | 'use ca ... ivate'; | use cache: private |
|
||||
| tst.js:34:5:34:17 | 'use strict'; | use strict |
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
'bundle';// and this
|
||||
'use server';
|
||||
'use client';
|
||||
'use memo';
|
||||
'use no memo';
|
||||
'use cache';
|
||||
'use cache: remote';
|
||||
'use cache: private';
|
||||
@@ -18,6 +20,8 @@ function f() {
|
||||
'bundle';
|
||||
'use server';
|
||||
'use client';
|
||||
'use memo';
|
||||
'use no memo';
|
||||
'use cache';
|
||||
'use cache: remote';
|
||||
'use cache: private';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example `py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example `py/clear-text-logging-sensitive-data`) may find more correct results and less fewer positive results after these changes.
|
||||
|
||||
## 7.1.1
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example `py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example `py/clear-text-logging-sensitive-data`) may find more correct results and less fewer positive results after these changes.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-020/IncompleteHostnameRegex.ql
|
||||
query: queries/Security/CWE-020/IncompleteHostnameRegex.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-020/MissingRegexAnchor.ql
|
||||
query: queries/Security/CWE-020/MissingRegexAnchor.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -47,63 +47,63 @@ class NSString : NSObject {
|
||||
|
||||
func tests(input: String) throws {
|
||||
_ = try Regex("^a|").firstMatch(in: input)
|
||||
_ = try Regex("^a|b").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("^a|b").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("a|^b").firstMatch(in: input)
|
||||
_ = try Regex("^a|^b").firstMatch(in: input)
|
||||
_ = try Regex("^a|b|c").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("^a|b|c").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("a|^b|c").firstMatch(in: input)
|
||||
_ = try Regex("a|b|^c").firstMatch(in: input)
|
||||
_ = try Regex("^a|^b|c").firstMatch(in: input)
|
||||
|
||||
_ = try Regex("(^a)|b").firstMatch(in: input)
|
||||
_ = try Regex("^a|(b)").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("^a|(b)").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("^a|(^b)").firstMatch(in: input)
|
||||
_ = try Regex("^(a)|(b)").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("^(a)|(b)").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
|
||||
_ = try Regex("a|b$").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("a|b$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("a$|b").firstMatch(in: input)
|
||||
_ = try Regex("a$|b$").firstMatch(in: input)
|
||||
_ = try Regex("a|b|c$").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("a|b|c$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("a|b$|c").firstMatch(in: input)
|
||||
_ = try Regex("a$|b|c").firstMatch(in: input)
|
||||
_ = try Regex("a|b$|c$").firstMatch(in: input)
|
||||
|
||||
_ = try Regex("a|(b$)").firstMatch(in: input)
|
||||
_ = try Regex("(a)|b$").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("(a)|b$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("(a$)|b$").firstMatch(in: input)
|
||||
_ = try Regex("(a)|(b)$").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("(a)|(b)$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
|
||||
_ = try Regex(#"^good.com|better.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\.com|better\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\.com|better\\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\\.com|better\\\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\\\.com|better\\\\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^good.com|better.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\.com|better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\.com|better\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\\.com|better\\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^good\\\\.com|better\\\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
|
||||
_ = try Regex("^foo|bar|baz$").firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex("^foo|bar|baz$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex("^foo|%").firstMatch(in: input)
|
||||
}
|
||||
|
||||
func realWorld(input: String) throws {
|
||||
// real-world examples that have been anonymized a bit
|
||||
// the following are bad:
|
||||
_ = try Regex(#"(\.xxx)|(\.yyy)|(\.zzz)$"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"(^left|right|center)\sbottom$"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|zzz$"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^([A-Z]|xxx[XY]$)"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)|(1st( xxx)? yyy)|xxx|1st"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx:)|(yyy:)|(zzz:)"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx?:)|(yyy:zzz\/)"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^@media|@page"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^\s*(xxx?|yyy|zzz):|xxx:yyy"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^click|mouse|touch"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://good\.com|http://better\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^https?://good\.com|https?://better\.com"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^mouse|touch|click|contextmenu|drop|dragover|dragend"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"^xxx:|yyy:"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"_xxx|_yyy|_zzz$"#).firstMatch(in: input) // BAD (missing anchor)
|
||||
_ = try Regex(#"(\.xxx)|(\.yyy)|(\.zzz)$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"(^left|right|center)\sbottom$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"\.xxx|\.yyy|zzz$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^([A-Z]|xxx[XY]$)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)|(1st( xxx)? yyy)|xxx|1st"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx:)|(yyy:)|(zzz:)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^(xxx?:)|(yyy:zzz\/)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^@media|@page"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^\s*(xxx?|yyy|zzz):|xxx:yyy"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^click|mouse|touch"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://good\.com|http://better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^https?://good\.com|https?://better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^mouse|touch|click|contextmenu|drop|dragover|dragend"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^xxx:|yyy:"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"_xxx|_yyy|_zzz$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"em|%$"#).firstMatch(in: input) // BAD (missing anchor) [NOT DETECTED] - not flagged at the moment due to the anchor not being for letters
|
||||
|
||||
// the following are MAYBE OK due to apparent complexity; not flagged
|
||||
|
||||
@@ -59,36 +59,36 @@ func tests(url: String, secure: Bool) throws {
|
||||
let input = "http://evil.com/?http://good.com"
|
||||
let inputRange = NSMakeRange(0, input.utf16.count)
|
||||
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "^https?://good.com").matches(in: input, range: inputRange) // BAD (missing post-anchor)
|
||||
_ = try NSRegularExpression(pattern: "(^https?://good1.com)|(^https?://good2.com)").matches(in: input, range: inputRange) // BAD (missing post-anchor)
|
||||
_ = try NSRegularExpression(pattern: "(https?://good.com)|(^https?://goodie.com)").matches(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "^https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing post-anchor)
|
||||
_ = try NSRegularExpression(pattern: "(^https?://good1.com)|(^https?://good2.com)").matches(in: input, range: inputRange) // $ Alert // BAD (missing post-anchor)
|
||||
_ = try NSRegularExpression(pattern: "(https?://good.com)|(^https?://goodie.com)").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
|
||||
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com"#).matches(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com"#).matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
|
||||
if let _ = try NSRegularExpression(pattern: "https?://good.com").firstMatch(in: input, range: inputRange) { } // BAD (missing anchor)
|
||||
if let _ = try NSRegularExpression(pattern: "https?://good.com").firstMatch(in: input, range: inputRange) { } // $ Alert // BAD (missing anchor)
|
||||
|
||||
let input2 = "something"
|
||||
let input2Range = NSMakeRange(0, input2.utf16.count)
|
||||
_ = try NSRegularExpression(pattern: "other").firstMatch(in: input2, range: input2Range) // OK
|
||||
_ = try NSRegularExpression(pattern: "x.commissary").firstMatch(in: input2, range: input2Range) // OK
|
||||
|
||||
_ = try NSRegularExpression(pattern: #"https?://good.com"#).firstMatch(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: #"https?://good.com:8080"#).firstMatch(in: input, range: inputRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: #"https?://good.com"#).firstMatch(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: #"https?://good.com:8080"#).firstMatch(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
|
||||
|
||||
let trustedUrlRegexs = [
|
||||
"https?://good.com", // BAD (missing anchor), referenced below
|
||||
#"https?:\/\/good.com"#, // BAD (missing anchor), referenced below
|
||||
"^https?://good.com" // BAD (missing post-anchor), referenced below
|
||||
"https?://good.com", // $ Alert // BAD (missing anchor), referenced below
|
||||
#"https?:\/\/good.com"#, // $ Alert // BAD (missing anchor), referenced below
|
||||
"^https?://good.com" // $ Alert // BAD (missing post-anchor), referenced below
|
||||
]
|
||||
for trustedUrlRegex in trustedUrlRegexs {
|
||||
if let _ = try NSRegularExpression(pattern: trustedUrlRegex).firstMatch(in: input, range: inputRange) { }
|
||||
}
|
||||
|
||||
let trustedUrlRegexs2 = [
|
||||
"https?://good.com", // BAD (missing anchor), referenced below
|
||||
"https?://good.com", // $ Alert // BAD (missing anchor), referenced below
|
||||
]
|
||||
if let _ = try NSRegularExpression(pattern: trustedUrlRegexs2[0]).firstMatch(in: input, range: inputRange) { }
|
||||
|
||||
@@ -98,13 +98,13 @@ func tests(url: String, secure: Bool) throws {
|
||||
for _ in notUsedUrlRegexs {
|
||||
}
|
||||
|
||||
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange) // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange) // $ Alert // BAD (missing anchor)
|
||||
_ = try NSRegularExpression(pattern: "https://verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK
|
||||
_ = try NSRegularExpression(pattern: "http" + (secure ? "s" : "") + "://" + "verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK
|
||||
_ = try NSRegularExpression(pattern: "verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK
|
||||
|
||||
_ = try NSRegularExpression(pattern: #"\.com|\.org"#).matches(in: input, range: inputRange) // OK, has no domain name
|
||||
_ = try NSRegularExpression(pattern: #"example\.com|whatever"#).matches(in: input, range: inputRange) // OK, the other disjunction doesn't match a hostname [FALSE POSITIVE]
|
||||
_ = try NSRegularExpression(pattern: #"example\.com|whatever"#).matches(in: input, range: inputRange) // $ Alert // OK, the other disjunction doesn't match a hostname [FALSE POSITIVE]
|
||||
|
||||
// tests for the `isLineAnchoredHostnameRegExp` case
|
||||
|
||||
|
||||
@@ -53,49 +53,49 @@ func testHostnames(myUrl: URL) throws {
|
||||
|
||||
_ = try Regex(#"^http://example\.com/"#).firstMatch(in: tainted) // GOOD
|
||||
_ = try Regex(#"^http://example.com/"#).firstMatch(in: tainted) // GOOD (only '.' here gives a valid top-level domain)
|
||||
_ = try Regex(#"^http://example.com"#).firstMatch(in: tainted) // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://example.com"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://test\.example\.com/"#).firstMatch(in: tainted) // GOOD
|
||||
_ = try Regex(#"^http://test\.example.com/"#).firstMatch(in: tainted) // GOOD (only '.' here gives a valid top-level domain)
|
||||
_ = try Regex(#"^http://test\.example.com"#).firstMatch(in: tainted) // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://test.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test\.example.com"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^http://test.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test[.]example[.]com/"#).firstMatch(in: tainted) // GOOD (alternative method of escaping)
|
||||
|
||||
_ = try Regex(#"^http://test.example.net/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test.(example-a|example-b).com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://(.+).example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname x 2)
|
||||
_ = try Regex(#"^http://test.example.net/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test.(example-a|example-b).com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://(.+).example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname x 2)
|
||||
_ = try Regex(#"^http://(\.+)\.example.com/"#).firstMatch(in: tainted) // GOOD
|
||||
_ = try Regex(#"^http://(?:.+)\.test\.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test.example.com/(?:.*)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(.+\.(?:example-a|example-b)\.com)/"#).firstMatch(in: tainted) // BAD (missing anchor)
|
||||
_ = try Regex(#"^(https?:)?//((service|www).)?example.com(?=$|/)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(http|https)://www.example.com/p/f/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(http://sub.example.com/)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^https?://api.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://(?:.+)\.test\.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http://test.example.com/(?:.*)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(.+\.(?:example-a|example-b)\.com)/"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
|
||||
_ = try Regex(#"^(https?:)?//((service|www).)?example.com(?=$|/)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(http|https)://www.example.com/p/f/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(http://sub.example.com/)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^https?://api.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^http[s]?://?sub1\.sub2\.example\.com/f/(.+)"#).firstMatch(in: tainted) // GOOD (it has a capture group after the TLD, so should be ignored)
|
||||
_ = try Regex(#"^https://[a-z]*.example.com$"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(example.dev|example.com)"#).firstMatch(in: tainted) // GOOD (any extended hostname wouldn't be included in the capture group) [FALSE POSITIVE]
|
||||
_ = try Regex(#"^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)"#).firstMatch(in: tainted) // BAD (incomplete hostname x3, missing anchor x 1)
|
||||
_ = try Regex(#"^https://[a-z]*.example.com$"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"^(example.dev|example.com)"#).firstMatch(in: tainted) // $ Alert // GOOD (any extended hostname wouldn't be included in the capture group) [FALSE POSITIVE]
|
||||
_ = try Regex(#"^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname x3, missing anchor x 1)
|
||||
|
||||
_ = try Regex(#"^http://(..|...)\.example\.com/index\.html"#).firstMatch(in: tainted) // GOOD (wildcards are intentional)
|
||||
_ = try Regex(#"^http://.\.example\.com/index\.html"#).firstMatch(in: tainted) // GOOD (the wildcard is intentional)
|
||||
_ = try Regex(#"^(foo.example\.com|whatever)$"#).firstMatch(in: tainted) // DUBIOUS (one disjunction doesn't even look like a hostname) [DETECTED incomplete hostname, missing anchor]
|
||||
_ = try Regex(#"^(foo.example\.com|whatever)$"#).firstMatch(in: tainted) // $ Alert // DUBIOUS (one disjunction doesn't even look like a hostname) [DETECTED incomplete hostname, missing anchor]
|
||||
|
||||
_ = try Regex(#"^test.example.com$"#).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(#"test.example.com"#).wholeMatch(in: tainted) // BAD (incomplete hostname, missing anchor)
|
||||
_ = try Regex(#"^test.example.com$"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(#"test.example.com"#).wholeMatch(in: tainted) // $ Alert // BAD (incomplete hostname, missing anchor)
|
||||
|
||||
_ = try Regex(id(id(id(#"test.example.com$"#)))).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try Regex(id(id(id(#"test.example.com$"#)))).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
|
||||
let hostname = #"test.example.com$"# // BAD (incomplete hostname) [NOT DETECTED]
|
||||
_ = try Regex("\(hostname)").firstMatch(in: tainted)
|
||||
|
||||
var domain = MyDomain("")
|
||||
domain.hostname = #"test.example.com$"# // BAD (incomplete hostname)
|
||||
domain.hostname = #"test.example.com$"# // $ Alert // BAD (incomplete hostname)
|
||||
_ = try Regex(domain.hostname).firstMatch(in: tainted)
|
||||
|
||||
func convert1(_ domain: MyDomain) throws -> Regex<AnyRegexOutput> {
|
||||
return try Regex(domain.hostname)
|
||||
}
|
||||
_ = try convert1(MyDomain(#"test.example.com$"#)).firstMatch(in: tainted) // BAD (incomplete hostname)
|
||||
_ = try convert1(MyDomain(#"test.example.com$"#)).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
|
||||
|
||||
let domains = [ MyDomain(#"test.example.com$"#) ] // BAD (incomplete hostname) [NOT DETECTED]
|
||||
func convert2(_ domain: MyDomain) throws -> Regex<AnyRegexOutput> {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
experimental/Security/CWE-022/UnsafeUnpack.ql
|
||||
query: experimental/Security/CWE-022/UnsafeUnpack.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -59,12 +59,12 @@ func testCommandInjectionQhelpExamples() {
|
||||
let source = URL(fileURLWithPath: "/sourcePath")
|
||||
let destination = URL(fileURLWithPath: "/destination")
|
||||
|
||||
try Data(contentsOf: remoteURL, options: []).write(to: source)
|
||||
try Data(contentsOf: remoteURL, options: []).write(to: source) // $ Source
|
||||
do {
|
||||
try Zip.unzipFile(source, destination: destination, overwrite: true, password: nil) // BAD
|
||||
try Zip.unzipFile(source, destination: destination, overwrite: true, password: nil) // $ Alert
|
||||
|
||||
let fileManager = FileManager()
|
||||
try fileManager.unzipItem(at: source, to: destination) // BAD
|
||||
try fileManager.unzipItem(at: source, to: destination) // $ Alert
|
||||
} catch {
|
||||
print("Error: \(error)")
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-079/UnsafeWebViewFetch.ql
|
||||
query: queries/Security/CWE-079/UnsafeWebViewFetch.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -91,7 +91,7 @@ func getRemoteData() -> String {
|
||||
let url = URL(string: "http://example.com/")
|
||||
do
|
||||
{
|
||||
return try String(contentsOf: url!)
|
||||
return try String(contentsOf: url!) // $ Source
|
||||
} catch {
|
||||
return ""
|
||||
}
|
||||
@@ -100,13 +100,13 @@ func getRemoteData() -> String {
|
||||
func testSimpleFlows() {
|
||||
let webview = UIWebView()
|
||||
|
||||
webview.loadHTMLString(try! String(contentsOf: URL(string: "http://example.com/")!), baseURL: nil) // BAD
|
||||
webview.loadHTMLString(try! String(contentsOf: URL(string: "http://example.com/")!), baseURL: nil) // $ Alert
|
||||
|
||||
let data = try! String(contentsOf: URL(string: "http://example.com/")!)
|
||||
webview.loadHTMLString(data, baseURL: nil) // BAD
|
||||
let data = try! String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
webview.loadHTMLString(data, baseURL: nil) // $ Alert
|
||||
|
||||
let url = URL(string: "http://example.com/")
|
||||
webview.loadHTMLString(try! String(contentsOf: url!), baseURL: nil) // BAD
|
||||
webview.loadHTMLString(try! String(contentsOf: url!), baseURL: nil) // $ Alert
|
||||
}
|
||||
|
||||
func testUIWebView() {
|
||||
@@ -117,14 +117,14 @@ func testUIWebView() {
|
||||
let remoteString = getRemoteData()
|
||||
|
||||
webview.loadHTMLString(localString, baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(getRemoteData(), baseURL: nil) // BAD: HTML contains remote input, may access local secrets
|
||||
webview.loadHTMLString(remoteString, baseURL: nil) // BAD
|
||||
webview.loadHTMLString(getRemoteData(), baseURL: nil) // $ Alert // BAD: HTML contains remote input, may access local secrets
|
||||
webview.loadHTMLString(remoteString, baseURL: nil) // $ Alert
|
||||
|
||||
webview.loadHTMLString("<html>" + localStringFragment + "</html>", baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString("<html>" + remoteString + "</html>", baseURL: nil) // BAD
|
||||
webview.loadHTMLString("<html>" + remoteString + "</html>", baseURL: nil) // $ Alert
|
||||
|
||||
webview.loadHTMLString("<html>\(localStringFragment)</html>", baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString("<html>\(remoteString)</html>", baseURL: nil) // BAD
|
||||
webview.loadHTMLString("<html>\(remoteString)</html>", baseURL: nil) // $ Alert
|
||||
|
||||
let localSafeURL = URL(string: "about:blank")
|
||||
let localURL = URL(string: "http://example.com/")
|
||||
@@ -136,9 +136,9 @@ func testUIWebView() {
|
||||
webview.loadHTMLString(localString, baseURL: localURL!) // GOOD: a presumed safe baseURL is specified
|
||||
webview.loadHTMLString(remoteString, baseURL: localURL!) // GOOD: a presumed safe baseURL is specified
|
||||
webview.loadHTMLString(localString, baseURL: remoteURL!) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL!) // BAD
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL!) // $ Alert
|
||||
webview.loadHTMLString(localString, baseURL: remoteURL2!) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL2!) // BAD
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL2!) // $ Alert
|
||||
|
||||
let localRequest = URLRequest(url: localURL!)
|
||||
let remoteRequest = URLRequest(url: remoteURL!)
|
||||
@@ -151,7 +151,7 @@ func testUIWebView() {
|
||||
webview.load(localData, mimeType: "text/html", textEncodingName: "utf-8", baseURL: localSafeURL!) // GOOD: the data is local
|
||||
webview.load(remoteData, mimeType: "text/html", textEncodingName: "utf-8", baseURL: localSafeURL!) // GOOD: a safe baseURL is specified
|
||||
webview.load(localData, mimeType: "text/html", textEncodingName: "utf-8", baseURL: remoteURL!) // GOOD: the HTML data is local
|
||||
webview.load(remoteData, mimeType: "text/html", textEncodingName: "utf-8", baseURL: remoteURL!) // BAD
|
||||
webview.load(remoteData, mimeType: "text/html", textEncodingName: "utf-8", baseURL: remoteURL!) // $ Alert
|
||||
}
|
||||
|
||||
func testWKWebView() {
|
||||
@@ -164,14 +164,14 @@ func testWKWebView() {
|
||||
let remoteString = getRemoteData()
|
||||
|
||||
webview.loadHTMLString(localString, baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(getRemoteData(), baseURL: nil) // BAD
|
||||
webview.loadHTMLString(remoteString, baseURL: nil) // BAD
|
||||
webview.loadHTMLString(getRemoteData(), baseURL: nil) // $ Alert
|
||||
webview.loadHTMLString(remoteString, baseURL: nil) // $ Alert
|
||||
|
||||
webview.loadHTMLString("<html>" + localStringFragment + "</html>", baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString("<html>" + remoteString + "</html>", baseURL: nil) // BAD
|
||||
webview.loadHTMLString("<html>" + remoteString + "</html>", baseURL: nil) // $ Alert
|
||||
|
||||
webview.loadHTMLString("<html>\(localStringFragment)</html>", baseURL: nil) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString("<html>\(remoteString)</html>", baseURL: nil) // BAD
|
||||
webview.loadHTMLString("<html>\(remoteString)</html>", baseURL: nil) // $ Alert
|
||||
|
||||
let localSafeURL = URL(string: "about:blank")
|
||||
let localURL = URL(string: "http://example.com/")
|
||||
@@ -183,9 +183,9 @@ func testWKWebView() {
|
||||
webview.loadHTMLString(localString, baseURL: localURL!) // GOOD: a presumed safe baseURL is specified
|
||||
webview.loadHTMLString(remoteString, baseURL: localURL!) // GOOD: a presumed safe baseURL is specified
|
||||
webview.loadHTMLString(localString, baseURL: remoteURL!) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL!) // BAD
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL!) // $ Alert
|
||||
webview.loadHTMLString(localString, baseURL: remoteURL2!) // GOOD: the HTML data is local
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL2!) // BAD
|
||||
webview.loadHTMLString(remoteString, baseURL: remoteURL2!) // $ Alert
|
||||
|
||||
let localRequest = URLRequest(url: localURL!)
|
||||
let remoteRequest = URLRequest(url: remoteURL!)
|
||||
@@ -198,7 +198,7 @@ func testWKWebView() {
|
||||
webview.load(localData, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: localSafeURL!) // GOOD: the data is local
|
||||
webview.load(remoteData, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: localSafeURL!) // GOOD: a safe baseURL is specified
|
||||
webview.load(localData, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: remoteURL!) // GOOD: the HTML data is local
|
||||
webview.load(remoteData, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: remoteURL!) // BAD
|
||||
webview.load(remoteData, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: remoteURL!) // $ Alert
|
||||
}
|
||||
|
||||
func testQHelpExamples() {
|
||||
@@ -207,7 +207,7 @@ func testQHelpExamples() {
|
||||
|
||||
// ...
|
||||
|
||||
webview.loadHTMLString(htmlData, baseURL: nil) // BAD
|
||||
webview.loadHTMLString(htmlData, baseURL: nil) // $ Alert
|
||||
webview.loadHTMLString(htmlData, baseURL: URL(string: "about:blank")) // GOOD
|
||||
}
|
||||
|
||||
|
||||
@@ -101,54 +101,54 @@ class CommonTableExpression {
|
||||
|
||||
func test(database: Database) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = database.allStatements(sql: remoteString) // BAD
|
||||
let _ = database.allStatements(sql: remoteString) // $ Alert
|
||||
let _ = database.allStatements(sql: localString) // GOOD
|
||||
let _ = database.allStatements(sql: remoteString, arguments: nil) // BAD
|
||||
let _ = database.allStatements(sql: remoteString, arguments: nil) // $ Alert
|
||||
let _ = database.allStatements(sql: localString, arguments: nil) // GOOD
|
||||
|
||||
let _ = database.cachedStatement(sql: remoteString) // BAD
|
||||
let _ = database.cachedStatement(sql: remoteString) // $ Alert
|
||||
let _ = database.cachedStatement(sql: localString) // GOOD
|
||||
|
||||
let _ = database.internalCachedStatement(sql: remoteString) // BAD
|
||||
let _ = database.internalCachedStatement(sql: remoteString) // $ Alert
|
||||
let _ = database.internalCachedStatement(sql: localString) // GOOD
|
||||
|
||||
database.execute(sql: remoteString) // BAD
|
||||
database.execute(sql: remoteString) // $ Alert
|
||||
database.execute(sql: localString) // GOOD
|
||||
database.execute(sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
database.execute(sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
database.execute(sql: localString, arguments: StatementArguments()) // GOOD
|
||||
|
||||
let _ = database.makeStatement(sql: remoteString) // BAD
|
||||
let _ = database.makeStatement(sql: remoteString) // $ Alert
|
||||
let _ = database.makeStatement(sql: localString) // GOOD
|
||||
let _ = database.makeStatement(sql: remoteString, prepFlags: 0) // BAD
|
||||
let _ = database.makeStatement(sql: remoteString, prepFlags: 0) // $ Alert
|
||||
let _ = database.makeStatement(sql: localString, prepFlags: 0) // GOOD
|
||||
}
|
||||
|
||||
func testSqlRequest() throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = SQLRequest(stringLiteral: remoteString) // BAD
|
||||
let _ = SQLRequest(stringLiteral: remoteString) // $ Alert
|
||||
let _ = SQLRequest(stringLiteral: localString) // GOOD
|
||||
|
||||
let _ = SQLRequest(unicodeScalarLiteral: remoteString) // BAD
|
||||
let _ = SQLRequest(unicodeScalarLiteral: remoteString) // $ Alert
|
||||
let _ = SQLRequest(unicodeScalarLiteral: localString) // GOOD
|
||||
|
||||
let _ = SQLRequest(extendedGraphemeClusterLiteral: remoteString) // BAD
|
||||
let _ = SQLRequest(extendedGraphemeClusterLiteral: remoteString) // $ Alert
|
||||
let _ = SQLRequest(extendedGraphemeClusterLiteral: localString) // GOOD
|
||||
|
||||
let _ = SQLRequest(stringInterpolation: remoteString) // BAD
|
||||
let _ = SQLRequest(stringInterpolation: remoteString) // $ Alert
|
||||
let _ = SQLRequest(stringInterpolation: localString) // GOOD
|
||||
|
||||
let _ = SQLRequest(sql: remoteString) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), cached: false) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), adapter: nil, cached: false) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, adapter: nil) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, adapter: nil, cached: false) // BAD
|
||||
let _ = SQLRequest(sql: remoteString, cached: false) // BAD
|
||||
let _ = SQLRequest(sql: remoteString) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, arguments: StatementArguments(), adapter: nil, cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, adapter: nil) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, adapter: nil, cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: remoteString, cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: localString) // GOOD
|
||||
let _ = SQLRequest(sql: localString, arguments: StatementArguments()) // GOOD
|
||||
let _ = SQLRequest(sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
@@ -161,15 +161,15 @@ func testSqlRequest() throws {
|
||||
|
||||
func testSql() throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = SQL(stringLiteral: remoteString) // BAD
|
||||
let _ = SQL(unicodeScalarLiteral: remoteString) // BAD
|
||||
let _ = SQL(extendedGraphemeClusterLiteral: remoteString) // BAD
|
||||
let _ = SQL(stringInterpolation: remoteString) // BAD
|
||||
let _ = SQL(sql: remoteString) // BAD
|
||||
let _ = SQL(stringLiteral: remoteString) // $ Alert
|
||||
let _ = SQL(unicodeScalarLiteral: remoteString) // $ Alert
|
||||
let _ = SQL(extendedGraphemeClusterLiteral: remoteString) // $ Alert
|
||||
let _ = SQL(stringInterpolation: remoteString) // $ Alert
|
||||
let _ = SQL(sql: remoteString) // $ Alert
|
||||
let sql1 = SQL(stringLiteral: "")
|
||||
sql1.append(sql: remoteString) // BAD
|
||||
sql1.append(sql: remoteString) // $ Alert
|
||||
|
||||
let _ = SQL(stringLiteral: localString) // GOOD
|
||||
let _ = SQL(unicodeScalarLiteral: localString) // GOOD
|
||||
@@ -182,34 +182,34 @@ func testSql() throws {
|
||||
|
||||
func test(tableDefinition: TableDefinition) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
tableDefinition.column(sql: remoteString) // BAD
|
||||
tableDefinition.column(sql: remoteString) // $ Alert
|
||||
tableDefinition.column(sql: localString) // GOOD
|
||||
|
||||
tableDefinition.check(sql: remoteString) // BAD
|
||||
tableDefinition.check(sql: remoteString) // $ Alert
|
||||
tableDefinition.check(sql: localString) // GOOD
|
||||
|
||||
tableDefinition.constraint(sql: remoteString) // BAD
|
||||
tableDefinition.constraint(sql: remoteString) // $ Alert
|
||||
tableDefinition.constraint(sql: localString) // GOOD
|
||||
}
|
||||
|
||||
func test(tableAlteration: TableAlteration) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
tableAlteration.addColumn(sql: remoteString) // BAD
|
||||
tableAlteration.addColumn(sql: remoteString) // $ Alert
|
||||
tableAlteration.addColumn(sql: localString) // GOOD
|
||||
}
|
||||
|
||||
func test(columnDefinition: ColumnDefinition) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = columnDefinition.check(sql: remoteString) // BAD
|
||||
let _ = columnDefinition.defaults(sql: remoteString) // BAD
|
||||
let _ = columnDefinition.generatedAs(sql: remoteString) // BAD
|
||||
let _ = columnDefinition.generatedAs(sql: remoteString, .virtual) // BAD
|
||||
let _ = columnDefinition.check(sql: remoteString) // $ Alert
|
||||
let _ = columnDefinition.defaults(sql: remoteString) // $ Alert
|
||||
let _ = columnDefinition.generatedAs(sql: remoteString) // $ Alert
|
||||
let _ = columnDefinition.generatedAs(sql: remoteString, .virtual) // $ Alert
|
||||
|
||||
let _ = columnDefinition.check(sql: localString) // GOOD
|
||||
let _ = columnDefinition.defaults(sql: localString) // GOOD
|
||||
@@ -219,67 +219,67 @@ func test(columnDefinition: ColumnDefinition) throws {
|
||||
|
||||
func testTableRecord() throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = TableRecord.select(sql: remoteString) // BAD
|
||||
let _ = TableRecord.select(sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = TableRecord.select(sql: remoteString) // $ Alert
|
||||
let _ = TableRecord.select(sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = TableRecord.select(sql: localString) // GOOD
|
||||
let _ = TableRecord.select(sql: localString, arguments: StatementArguments()) // GOOD
|
||||
|
||||
let _ = TableRecord.filter(sql: remoteString) // BAD
|
||||
let _ = TableRecord.filter(sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = TableRecord.filter(sql: remoteString) // $ Alert
|
||||
let _ = TableRecord.filter(sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = TableRecord.filter(sql: localString) // GOOD
|
||||
let _ = TableRecord.filter(sql: localString, arguments: StatementArguments()) // GOOD
|
||||
|
||||
let _ = TableRecord.order(sql: remoteString) // BAD
|
||||
let _ = TableRecord.order(sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = TableRecord.order(sql: remoteString) // $ Alert
|
||||
let _ = TableRecord.order(sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = TableRecord.order(sql: localString) // GOOD
|
||||
let _ = TableRecord.order(sql: localString, arguments: StatementArguments()) // GOOD
|
||||
}
|
||||
|
||||
func test(statementCache: StatementCache) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = statementCache.statement(remoteString) // BAD
|
||||
let _ = statementCache.statement(remoteString) // $ Alert
|
||||
let _ = statementCache.statement(localString) // GOOD
|
||||
}
|
||||
|
||||
func test(row: Row, stmt: Statement) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
row.fetchCursor(stmt, sql: remoteString) // BAD
|
||||
row.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
row.fetchCursor(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
row.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
row.fetchCursor(stmt, sql: remoteString) // $ Alert
|
||||
row.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
row.fetchCursor(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
row.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
row.fetchCursor(stmt, sql: localString) // GOOD
|
||||
row.fetchCursor(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
row.fetchCursor(stmt, sql: localString, adapter: nil) // GOOD
|
||||
row.fetchCursor(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
row.fetchAll(stmt, sql: remoteString) // BAD
|
||||
row.fetchAll(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
row.fetchAll(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
row.fetchAll(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
row.fetchAll(stmt, sql: remoteString) // $ Alert
|
||||
row.fetchAll(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
row.fetchAll(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
row.fetchAll(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
row.fetchAll(stmt, sql: localString) // GOOD
|
||||
row.fetchAll(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
row.fetchAll(stmt, sql: localString, adapter: nil) // GOOD
|
||||
row.fetchAll(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
row.fetchOne(stmt, sql: remoteString) // BAD
|
||||
row.fetchOne(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
row.fetchOne(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
row.fetchOne(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
row.fetchOne(stmt, sql: remoteString) // $ Alert
|
||||
row.fetchOne(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
row.fetchOne(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
row.fetchOne(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
row.fetchOne(stmt, sql: localString) // GOOD
|
||||
row.fetchOne(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
row.fetchOne(stmt, sql: localString, adapter: nil) // GOOD
|
||||
row.fetchOne(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
row.fetchSet(stmt, sql: remoteString) // BAD
|
||||
row.fetchSet(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
row.fetchSet(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
row.fetchSet(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
row.fetchSet(stmt, sql: remoteString) // $ Alert
|
||||
row.fetchSet(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
row.fetchSet(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
row.fetchSet(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
row.fetchSet(stmt, sql: localString) // GOOD
|
||||
row.fetchSet(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
row.fetchSet(stmt, sql: localString, adapter: nil) // GOOD
|
||||
@@ -288,39 +288,39 @@ func test(row: Row, stmt: Statement) throws {
|
||||
|
||||
func test(databaseValueConvertible: DatabaseValueConvertible, stmt: Statement) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: localString) // GOOD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: localString, adapter: nil) // GOOD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: localString) // GOOD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: localString, adapter: nil) // GOOD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: localString) // GOOD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: localString, adapter: nil) // GOOD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: localString, arguments: StatementArguments(), adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: remoteString, arguments: StatementArguments(), adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: localString) // GOOD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: localString, adapter: nil) // GOOD
|
||||
@@ -329,26 +329,26 @@ func test(databaseValueConvertible: DatabaseValueConvertible, stmt: Statement) t
|
||||
|
||||
func testSqlStatementCursor(database: Database) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = SQLStatementCursor(database: database, sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = SQLStatementCursor(database: database, sql: remoteString, arguments: StatementArguments(), prepFlags: 0) // BAD
|
||||
let _ = SQLStatementCursor(database: database, sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = SQLStatementCursor(database: database, sql: remoteString, arguments: StatementArguments(), prepFlags: 0) // $ Alert
|
||||
let _ = SQLStatementCursor(database: database, sql: localString, arguments: StatementArguments()) // GOOD
|
||||
let _ = SQLStatementCursor(database: database, sql: localString, arguments: StatementArguments(), prepFlags: 0) // GOOD
|
||||
}
|
||||
|
||||
func testCommonTableExpression() throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
let _ = CommonTableExpression(named: "", sql: remoteString) // BAD
|
||||
let _ = CommonTableExpression(named: "", sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = CommonTableExpression(named: "", columns: [""], sql: remoteString) // BAD
|
||||
let _ = CommonTableExpression(named: "", columns: [""], sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: remoteString) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: [""], sql: remoteString) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: [""], sql: remoteString, arguments: StatementArguments()) // BAD
|
||||
let _ = CommonTableExpression(named: "", sql: remoteString) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", columns: [""], sql: remoteString) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", columns: [""], sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: remoteString) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: [""], sql: remoteString) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: [""], sql: remoteString, arguments: StatementArguments()) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", sql: localString) // GOOD
|
||||
let _ = CommonTableExpression(named: "", sql: localString, arguments: StatementArguments()) // GOOD
|
||||
let _ = CommonTableExpression(named: "", columns: [""], sql: localString) // GOOD
|
||||
|
||||
@@ -59,7 +59,7 @@ class Connection {
|
||||
|
||||
func test_sqlite_swift_api(db: Connection) throws {
|
||||
let localString = "user"
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
let remoteNumber = Int(remoteString) ?? 0
|
||||
|
||||
let unsafeQuery1 = remoteString
|
||||
@@ -70,9 +70,9 @@ func test_sqlite_swift_api(db: Connection) throws {
|
||||
|
||||
// --- execute ---
|
||||
|
||||
try db.execute(unsafeQuery1) // BAD
|
||||
try db.execute(unsafeQuery2) // BAD
|
||||
try db.execute(unsafeQuery3) // BAD
|
||||
try db.execute(unsafeQuery1) // $ Alert
|
||||
try db.execute(unsafeQuery2) // $ Alert
|
||||
try db.execute(unsafeQuery3) // $ Alert
|
||||
try db.execute(safeQuery1) // GOOD
|
||||
try db.execute(safeQuery2) // GOOD
|
||||
|
||||
@@ -80,7 +80,7 @@ func test_sqlite_swift_api(db: Connection) throws {
|
||||
|
||||
let varQuery = "SELECT * FROM users WHERE username=?"
|
||||
|
||||
let stmt1 = try db.prepare(unsafeQuery3) // BAD
|
||||
let stmt1 = try db.prepare(unsafeQuery3) // $ Alert
|
||||
try stmt1.run()
|
||||
|
||||
let stmt2 = try db.prepare(varQuery, localString) // GOOD
|
||||
@@ -92,31 +92,31 @@ func test_sqlite_swift_api(db: Connection) throws {
|
||||
let stmt4 = try Statement(db, localString) // GOOD
|
||||
try stmt4.run()
|
||||
|
||||
let stmt5 = try Statement(db, remoteString) // BAD
|
||||
let stmt5 = try Statement(db, remoteString) // $ Alert
|
||||
try stmt5.run()
|
||||
|
||||
// --- more variants ---
|
||||
|
||||
let stmt6 = try db.prepare(unsafeQuery1, "") // BAD
|
||||
let stmt6 = try db.prepare(unsafeQuery1, "") // $ Alert
|
||||
try stmt6.run()
|
||||
|
||||
let stmt7 = try db.prepare(unsafeQuery1, [""]) // BAD
|
||||
let stmt7 = try db.prepare(unsafeQuery1, [""]) // $ Alert
|
||||
try stmt7.run()
|
||||
|
||||
let stmt8 = try db.prepare(unsafeQuery1, ["username": ""]) // BAD
|
||||
let stmt8 = try db.prepare(unsafeQuery1, ["username": ""]) // $ Alert
|
||||
try stmt8.run()
|
||||
|
||||
try db.run(unsafeQuery1, "") // BAD
|
||||
try db.run(unsafeQuery1, "") // $ Alert
|
||||
|
||||
try db.run(unsafeQuery1, [""]) // BAD
|
||||
try db.run(unsafeQuery1, [""]) // $ Alert
|
||||
|
||||
try db.run(unsafeQuery1, ["username": ""]) // BAD
|
||||
try db.run(unsafeQuery1, ["username": ""]) // $ Alert
|
||||
|
||||
try db.scalar(unsafeQuery1, "") // BAD
|
||||
try db.scalar(unsafeQuery1, "") // $ Alert
|
||||
|
||||
try db.scalar(unsafeQuery1, [""]) // BAD
|
||||
try db.scalar(unsafeQuery1, [""]) // $ Alert
|
||||
|
||||
try db.scalar(unsafeQuery1, ["username": ""]) // BAD
|
||||
try db.scalar(unsafeQuery1, ["username": ""]) // $ Alert
|
||||
|
||||
let stmt9 = try db.prepare(varQuery) // GOOD
|
||||
try stmt9.bind(remoteString) // GOOD
|
||||
@@ -129,5 +129,5 @@ func test_sqlite_swift_api(db: Connection) throws {
|
||||
try stmt9.scalar([remoteString]) // GOOD
|
||||
try stmt9.scalar(["username": remoteString]) // GOOD
|
||||
|
||||
try Statement(db, remoteString).run() // BAD
|
||||
try Statement(db, remoteString).run() // $ Alert
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-089/SqlInjection.ql
|
||||
query: queries/Security/CWE-089/SqlInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -43,18 +43,18 @@ class MyDatabase {
|
||||
// --- tests ---
|
||||
|
||||
func test_heuristic(db: MyDatabase) throws {
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
|
||||
_ = MyDatabase() // GOOD
|
||||
_ = MyDatabase(sql: "some_fixed_sql") // GOOD
|
||||
_ = MyDatabase(sql: remoteString) // BAD
|
||||
_ = MyDatabase(sql: remoteString) // $ Alert
|
||||
|
||||
db.execute1(remoteString) // BAD
|
||||
db.execute2(remoteString) // BAD
|
||||
db.execute3(NSString(string: remoteString)) // BAD
|
||||
db.execute4(remoteString as! Sql) // BAD
|
||||
db.execute1(remoteString) // $ Alert
|
||||
db.execute2(remoteString) // $ Alert
|
||||
db.execute3(NSString(string: remoteString)) // $ Alert
|
||||
db.execute4(remoteString as! Sql) // $ Alert
|
||||
|
||||
db.query(sql: remoteString) // BAD
|
||||
db.query(sql: remoteString) // $ Alert
|
||||
db.query(sqlLiteral: remoteString) // BAD [NOT DETECTED]
|
||||
db.query(sqlStatement: remoteString) // BAD [NOT DETECTED]
|
||||
db.query(sqliteStatement: remoteString) // BAD [NOT DETECTED]
|
||||
|
||||
@@ -119,7 +119,7 @@ func sqlite3_finalize(
|
||||
|
||||
func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>) {
|
||||
let localString = "user"
|
||||
let remoteString = try! String(contentsOf: URL(string: "http://example.com/")!)
|
||||
let remoteString = try! String(contentsOf: URL(string: "http://example.com/")!) // $ Source
|
||||
let remoteNumber = Int(remoteString) ?? 0
|
||||
|
||||
let unsafeQuery1 = remoteString
|
||||
@@ -130,9 +130,9 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
// --- exec ---
|
||||
|
||||
let result1 = sqlite3_exec(db, unsafeQuery1, nil, nil, nil) // BAD
|
||||
let result2 = sqlite3_exec(db, unsafeQuery2, nil, nil, nil) // BAD
|
||||
let result3 = sqlite3_exec(db, unsafeQuery3, nil, nil, nil) // BAD
|
||||
let result1 = sqlite3_exec(db, unsafeQuery1, nil, nil, nil) // $ Alert
|
||||
let result2 = sqlite3_exec(db, unsafeQuery2, nil, nil, nil) // $ Alert
|
||||
let result3 = sqlite3_exec(db, unsafeQuery3, nil, nil, nil) // $ Alert
|
||||
let result4 = sqlite3_exec(db, safeQuery1, nil, nil, nil) // GOOD
|
||||
let result5 = sqlite3_exec(db, safeQuery2, nil, nil, nil) // GOOD
|
||||
|
||||
@@ -142,7 +142,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt1: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare(db, unsafeQuery3, -1, &stmt1, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare(db, unsafeQuery3, -1, &stmt1, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt1)
|
||||
// ...
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt4: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare_v2(db, unsafeQuery3, -1, &stmt4, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare_v2(db, unsafeQuery3, -1, &stmt4, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt4)
|
||||
// ...
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt5: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare_v3(db, unsafeQuery3, -1, 0, &stmt5, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare_v3(db, unsafeQuery3, -1, 0, &stmt5, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt5)
|
||||
// ...
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt6: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare16(db, buffer, Int32(data.count), &stmt6, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare16(db, buffer, Int32(data.count), &stmt6, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt6)
|
||||
// ...
|
||||
}
|
||||
@@ -199,7 +199,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt7: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare16_v2(db, buffer, Int32(data.count), &stmt7, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare16_v2(db, buffer, Int32(data.count), &stmt7, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt7)
|
||||
// ...
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, buffer: UnsafeMutablePointer<UInt8>)
|
||||
|
||||
var stmt8: OpaquePointer?
|
||||
|
||||
if (sqlite3_prepare16_v3(db, buffer, Int32(data.count), 0, &stmt8, nil) == SQLITE_OK) { // BAD
|
||||
if (sqlite3_prepare16_v3(db, buffer, Int32(data.count), 0, &stmt8, nil) == SQLITE_OK) { // $ Alert
|
||||
let result = sqlite3_step(stmt8)
|
||||
// ...
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-116/BadTagFilter.ql
|
||||
query: queries/Security/CWE-116/BadTagFilter.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -76,18 +76,18 @@ func myRegexpVariantsTests(myUrl: URL) throws {
|
||||
let tainted = String(contentsOf: myUrl) // tainted
|
||||
|
||||
// BAD - doesn't match newlines or `</script >`
|
||||
let re1 = try Regex(#"<script.*?>.*?<\/script>"#).ignoresCase(true)
|
||||
let re1 = try Regex(#"<script.*?>.*?<\/script>"#).ignoresCase(true) // $ Alert
|
||||
_ = try re1.firstMatch(in: tainted)
|
||||
|
||||
// BAD - doesn't match `</script >`
|
||||
let re2a = try Regex(#"(?is)<script.*?>.*?<\/script>"#)
|
||||
let re2a = try Regex(#"(?is)<script.*?>.*?<\/script>"#) // $ Alert
|
||||
_ = try re2a.firstMatch(in: tainted)
|
||||
// BAD - doesn't match `</script >`
|
||||
let re2b = try Regex(#"<script.*?>.*?<\/script>"#).ignoresCase(true).dotMatchesNewlines(true)
|
||||
let re2b = try Regex(#"<script.*?>.*?<\/script>"#).ignoresCase(true).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re2b.firstMatch(in: tainted)
|
||||
// BAD - doesn't match `</script >`
|
||||
let options2c: NSRegularExpression.Options = [.caseInsensitive, .dotMatchesLineSeparators]
|
||||
let ns2c = try NSRegularExpression(pattern: #"<script.*?>.*?<\/script>"#, options: options2c)
|
||||
let ns2c = try NSRegularExpression(pattern: #"<script.*?>.*?<\/script>"#, options: options2c) // $ Alert
|
||||
_ = ns2c.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// GOOD
|
||||
@@ -110,71 +110,71 @@ func myRegexpVariantsTests(myUrl: URL) throws {
|
||||
_ = try re5.firstMatch(in: tainted)
|
||||
|
||||
// BAD, does not match newlines
|
||||
let re6 = try Regex(#"<!--.*--!?>"#).ignoresCase(true)
|
||||
let re6 = try Regex(#"<!--.*--!?>"#).ignoresCase(true) // $ Alert
|
||||
_ = try re6.firstMatch(in: tainted)
|
||||
|
||||
// BAD - doesn't match newlines inside the script tag
|
||||
let re7 = try Regex(#"<script.*?>(.|\s)*?<\/script[^>]*>"#).ignoresCase(true)
|
||||
let re7 = try Regex(#"<script.*?>(.|\s)*?<\/script[^>]*>"#).ignoresCase(true) // $ Alert
|
||||
_ = try re7.firstMatch(in: tainted)
|
||||
|
||||
// BAD - doesn't match newlines inside the content
|
||||
let re8 = try Regex(#"<script[^>]*?>.*?<\/script[^>]*>"#).ignoresCase(true)
|
||||
let re8 = try Regex(#"<script[^>]*?>.*?<\/script[^>]*>"#).ignoresCase(true) // $ Alert
|
||||
_ = try re8.firstMatch(in: tainted)
|
||||
|
||||
// BAD - does not match single quotes for attribute values
|
||||
let re9 = try Regex(#"<script(\s|\w|=|")*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true)
|
||||
let re9 = try Regex(#"<script(\s|\w|=|")*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re9.firstMatch(in: tainted)
|
||||
|
||||
// BAD - does not match double quotes for attribute values
|
||||
let re10a = try Regex(#"(?is)<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#)
|
||||
let re10a = try Regex(#"(?is)<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#) // $ Alert
|
||||
_ = try re10a.firstMatch(in: tainted)
|
||||
// BAD - does not match double quotes for attribute values
|
||||
let re10b = try Regex(#"<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true)
|
||||
let re10b = try Regex(#"<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re10b.firstMatch(in: tainted)
|
||||
// BAD - does not match double quotes for attribute values
|
||||
let options10: NSRegularExpression.Options = [.caseInsensitive, .dotMatchesLineSeparators]
|
||||
let ns10 = try NSRegularExpression(pattern: #"<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#, options: options10)
|
||||
let ns10 = try NSRegularExpression(pattern: #"<script(\s|\w|=|')*?>.*?<\/script[^>]*>"#, options: options10) // $ Alert
|
||||
_ = ns10.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - does not match tabs between attributes
|
||||
let re11a = try Regex(#"(?is)<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#)
|
||||
let re11a = try Regex(#"(?is)<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#) // $ Alert
|
||||
_ = try re11a.firstMatch(in: tainted)
|
||||
// BAD - does not match tabs between attributes
|
||||
let re11b = try Regex(#"<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true)
|
||||
let re11b = try Regex(#"<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#).ignoresCase(true).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re11b.firstMatch(in: tainted)
|
||||
// BAD - does not match tabs between attributes
|
||||
let options11: NSRegularExpression.Options = [.caseInsensitive, .dotMatchesLineSeparators]
|
||||
let ns11 = try NSRegularExpression(pattern: #"<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#, options: options11)
|
||||
let ns11 = try NSRegularExpression(pattern: #"<script( |\n|\w|=|'|")*?>.*?<\/script[^>]*>"#, options: options11) // $ Alert
|
||||
_ = ns11.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - does not match uppercase SCRIPT tags
|
||||
let re12a = try Regex(#"(?s)<script.*?>.*?<\/script[^>]*>"#)
|
||||
let re12a = try Regex(#"(?s)<script.*?>.*?<\/script[^>]*>"#) // $ Alert
|
||||
_ = try re12a.firstMatch(in: tainted)
|
||||
// BAD - does not match uppercase SCRIPT tags
|
||||
let re12b = try Regex(#"<script.*?>.*?<\/script[^>]*>"#).dotMatchesNewlines(true)
|
||||
let re12b = try Regex(#"<script.*?>.*?<\/script[^>]*>"#).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re12b.firstMatch(in: tainted)
|
||||
// BAD - does not match uppercase SCRIPT tags
|
||||
let ns12 = try NSRegularExpression(pattern: #"<script.*?>.*?<\/script[^>]*>"#, options: .dotMatchesLineSeparators)
|
||||
let ns12 = try NSRegularExpression(pattern: #"<script.*?>.*?<\/script[^>]*>"#, options: .dotMatchesLineSeparators) // $ Alert
|
||||
_ = ns12.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - does not match mixed case script tags
|
||||
let re13a = try Regex(#"(?s)<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#)
|
||||
let re13a = try Regex(#"(?s)<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#) // $ Alert
|
||||
_ = try re13a.firstMatch(in: tainted)
|
||||
// BAD - does not match mixed case script tags
|
||||
let re13b = try Regex(#"<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#).dotMatchesNewlines(true)
|
||||
let re13b = try Regex(#"<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#).dotMatchesNewlines(true) // $ Alert
|
||||
_ = try re13b.firstMatch(in: tainted)
|
||||
// BAD - does not match mixed case script tags
|
||||
let ns13 = try NSRegularExpression(pattern: #"<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#, options: .dotMatchesLineSeparators)
|
||||
let ns13 = try NSRegularExpression(pattern: #"<(script|SCRIPT).*?>.*?<\/(script|SCRIPT)[^>]*>"#, options: .dotMatchesLineSeparators) // $ Alert
|
||||
_ = ns13.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - doesn't match newlines in the end tag
|
||||
let re14a = try Regex(#"(?i)<script[^>]*?>[\s\S]*?<\/script.*>"#)
|
||||
let re14a = try Regex(#"(?i)<script[^>]*?>[\s\S]*?<\/script.*>"#) // $ Alert
|
||||
_ = try re14a.firstMatch(in: tainted)
|
||||
// BAD - doesn't match newlines in the end tag
|
||||
let re14b = try Regex(#"<script[^>]*?>[\s\S]*?<\/script.*>"#).ignoresCase(true)
|
||||
let re14b = try Regex(#"<script[^>]*?>[\s\S]*?<\/script.*>"#).ignoresCase(true) // $ Alert
|
||||
_ = try re14b.firstMatch(in: tainted)
|
||||
// BAD - doesn't match newlines in the end tag
|
||||
let ns14 = try NSRegularExpression(pattern: #"<script[^>]*?>[\s\S]*?<\/script.*>"#, options: .caseInsensitive)
|
||||
let ns14 = try NSRegularExpression(pattern: #"<script[^>]*?>[\s\S]*?<\/script.*>"#, options: .caseInsensitive) // $ Alert
|
||||
_ = ns14.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// GOOD
|
||||
@@ -188,33 +188,33 @@ func myRegexpVariantsTests(myUrl: URL) throws {
|
||||
_ = ns15.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - doesn't match comments with the right capture groups
|
||||
let re16 = try Regex(#"<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>"#)
|
||||
let re16 = try Regex(#"<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>"#) // $ Alert
|
||||
_ = try re16.firstMatch(in: tainted)
|
||||
// BAD - doesn't match comments with the right capture groups
|
||||
let ns16 = try NSRegularExpression(pattern: #"<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>"#)
|
||||
let ns16 = try NSRegularExpression(pattern: #"<(?:!--([\S|\s]*?)-->)|([^\/\s>]+)[\S\s]*?>"#) // $ Alert
|
||||
_ = ns16.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - capture groups
|
||||
let re17 = try Regex(#"<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))"#)
|
||||
let re17 = try Regex(#"<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))"#) // $ Alert
|
||||
_ = try re17.firstMatch(in: tainted)
|
||||
// BAD - capture groups
|
||||
let ns17 = try NSRegularExpression(pattern: #"<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))"#, options: .caseInsensitive)
|
||||
let ns17 = try NSRegularExpression(pattern: #"<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))"#, options: .caseInsensitive) // $ Alert
|
||||
_ = ns17.firstMatch(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - too strict matching on the end tag
|
||||
let ns2_1 = try NSRegularExpression(pattern: #"<script\b[^>]*>([\s\S]*?)<\/script>"#, options: .caseInsensitive)
|
||||
let ns2_1 = try NSRegularExpression(pattern: #"<script\b[^>]*>([\s\S]*?)<\/script>"#, options: .caseInsensitive) // $ Alert
|
||||
_ = ns2_1.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - capture groups
|
||||
let ns2_2 = try NSRegularExpression(pattern: #"(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)"#, options: .caseInsensitive)
|
||||
let ns2_2 = try NSRegularExpression(pattern: #"(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)"#, options: .caseInsensitive) // $ Alert
|
||||
_ = ns2_2.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - capture groups
|
||||
let ns2_3 = try NSRegularExpression(pattern: #"<(?:(?:!--([\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+)>))"#)
|
||||
let ns2_3 = try NSRegularExpression(pattern: #"<(?:(?:!--([\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+)>))"#) // $ Alert
|
||||
_ = ns2_3.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - capture groups
|
||||
let ns2_4 = try NSRegularExpression(pattern: #"<!--([\w\W]*?)-->|<([^>]*?)>"#)
|
||||
let ns2_4 = try NSRegularExpression(pattern: #"<!--([\w\W]*?)-->|<([^>]*?)>"#) // $ Alert
|
||||
_ = ns2_4.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// GOOD - it's used with the ignorecase flag
|
||||
@@ -222,7 +222,7 @@ func myRegexpVariantsTests(myUrl: URL) throws {
|
||||
_ = ns2_5.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// BAD - doesn't match --!>
|
||||
let ns2_6 = try NSRegularExpression(pattern: #"-->"#)
|
||||
let ns2_6 = try NSRegularExpression(pattern: #"-->"#) // $ Alert
|
||||
_ = ns2_6.matches(in: tainted, range: NSMakeRange(0, tainted.utf16.count))
|
||||
|
||||
// GOOD
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-1204/StaticInitializationVector.ql
|
||||
query: queries/Security/CWE-1204/StaticInitializationVector.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -57,28 +57,28 @@ func test(myPassword: String) {
|
||||
let myKeyDerivationSettings = RNCryptorKeyDerivationSettings()
|
||||
let myHandler = {}
|
||||
let myRandomIV = Data(getRandomArray())
|
||||
let myConstIV1 = Data(0)
|
||||
let myConstIV2 = Data(123)
|
||||
let myConstIV3 = Data([1,2,3,4,5])
|
||||
let myConstIV4 = Data("iv")
|
||||
let myConstIV1 = Data(0) // $ Source
|
||||
let myConstIV2 = Data(123) // $ Source
|
||||
let myConstIV3 = Data([1,2,3,4,5]) // $ Source
|
||||
let myConstIV4 = Data("iv") // $ Source
|
||||
let mySalt = Data(0)
|
||||
let mySalt2 = Data(0)
|
||||
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myRandomIV, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myConstIV1, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myConstIV1, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myRandomIV, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myConstIV2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myConstIV2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myRandomIV, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myConstIV3, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myConstIV3, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myRandomIV, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myConstIV4, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myConstIV4, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // $ Alert
|
||||
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myRandomIV) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myConstIV1) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, encryptionKey: myKey, hmacKey: myHMACKey, iv: myConstIV1) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myRandomIV) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myConstIV2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, encryptionKey: myKey, HMACKey: myHMACKey, IV: myConstIV2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myRandomIV, encryptionSalt: mySalt, hmacSalt: mySalt2) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myConstIV3, encryptionSalt: mySalt, hmacSalt: mySalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myConstIV3, encryptionSalt: mySalt, hmacSalt: mySalt2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myRandomIV, encryptionSalt: mySalt, HMACSalt: mySalt2) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myConstIV4, encryptionSalt: mySalt, HMACSalt: mySalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myConstIV4, encryptionSalt: mySalt, HMACSalt: mySalt2) // $ Alert
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ final class GCM: BlockMode {
|
||||
enum Mode { case combined, detached }
|
||||
init(iv: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil, tagLength: Int = 16, mode: Mode = .detached) { }
|
||||
convenience init(iv: Array<UInt8>, authenticationTag: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil, mode: Mode = .detached) {
|
||||
self.init(iv: iv, additionalAuthenticatedData: additionalAuthenticatedData, tagLength: authenticationTag.count, mode: mode)
|
||||
self.init(iv: iv, additionalAuthenticatedData: additionalAuthenticatedData, tagLength: authenticationTag.count, mode: mode) // $ Alert
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ enum Padding: PaddingProtocol {
|
||||
|
||||
// Helper functions
|
||||
func getConstantString() -> String {
|
||||
"this string is constant"
|
||||
"this string is constant" // $ Source
|
||||
}
|
||||
|
||||
func getConstantArray() -> Array<UInt8> {
|
||||
@@ -96,7 +96,7 @@ func getRandomArray() -> Array<UInt8> {
|
||||
// --- tests ---
|
||||
|
||||
func test() {
|
||||
let iv: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f]
|
||||
let iv: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f] // $ Source
|
||||
let iv2 = getConstantArray()
|
||||
let ivString = getConstantString()
|
||||
|
||||
@@ -109,63 +109,63 @@ func test() {
|
||||
let keyString = String(cString: key)
|
||||
|
||||
// AES test cases
|
||||
let ab1 = AES(key: keyString, iv: ivString) // BAD
|
||||
let ab2 = AES(key: keyString, iv: ivString, padding: padding) // BAD
|
||||
let ab1 = AES(key: keyString, iv: ivString) // $ Alert
|
||||
let ab2 = AES(key: keyString, iv: ivString, padding: padding) // $ Alert
|
||||
let ag1 = AES(key: keyString, iv: randomIvString) // GOOD
|
||||
let ag2 = AES(key: keyString, iv: randomIvString, padding: padding) // GOOD
|
||||
|
||||
// ChaCha20 test cases
|
||||
let cb1 = ChaCha20(key: keyString, iv: ivString) // BAD
|
||||
let cb1 = ChaCha20(key: keyString, iv: ivString) // $ Alert
|
||||
let cg1 = ChaCha20(key: keyString, iv: randomIvString) // GOOD
|
||||
|
||||
// Blowfish test cases
|
||||
let bb1 = Blowfish(key: keyString, iv: ivString) // BAD
|
||||
let bb2 = Blowfish(key: keyString, iv: ivString, padding: padding) // BAD
|
||||
let bb1 = Blowfish(key: keyString, iv: ivString) // $ Alert
|
||||
let bb2 = Blowfish(key: keyString, iv: ivString, padding: padding) // $ Alert
|
||||
let bg1 = Blowfish(key: keyString, iv: randomIvString) // GOOD
|
||||
let bg2 = Blowfish(key: keyString, iv: randomIvString, padding: padding) // GOOD
|
||||
|
||||
// Rabbit
|
||||
let rb1 = Rabbit(key: key, iv: iv) // BAD
|
||||
let rb2 = Rabbit(key: key, iv: iv2) // BAD
|
||||
let rb3 = Rabbit(key: keyString, iv: ivString) // BAD
|
||||
let rb1 = Rabbit(key: key, iv: iv) // $ Alert
|
||||
let rb2 = Rabbit(key: key, iv: iv2) // $ Alert
|
||||
let rb3 = Rabbit(key: keyString, iv: ivString) // $ Alert
|
||||
let rg1 = Rabbit(key: key, iv: randomIv) // GOOD
|
||||
let rg2 = Rabbit(key: keyString, iv: randomIvString) // GOOD
|
||||
|
||||
// CBC
|
||||
let cbcb1 = CBC(iv: iv) // BAD
|
||||
let cbcb1 = CBC(iv: iv) // $ Alert
|
||||
let cbcg1 = CBC(iv: randomIv) // GOOD
|
||||
|
||||
// CFB
|
||||
let cfbb1 = CFB(iv: iv) // BAD
|
||||
let cfbb2 = CFB(iv: iv, segmentSize: CFB.SegmentSize.cfb8) // BAD
|
||||
let cfbb1 = CFB(iv: iv) // $ Alert
|
||||
let cfbb2 = CFB(iv: iv, segmentSize: CFB.SegmentSize.cfb8) // $ Alert
|
||||
let cfbg1 = CFB(iv: randomIv) // GOOD
|
||||
let cfbg2 = CFB(iv: randomIv, segmentSize: CFB.SegmentSize.cfb8) // GOOD
|
||||
|
||||
// GCM
|
||||
let cgmb1 = GCM(iv: iv) // BAD
|
||||
let cgmb2 = GCM(iv: iv, additionalAuthenticatedData: randomArray, tagLength: 8, mode: GCM.Mode.combined) // BAD
|
||||
let cgmb3 = GCM(iv: iv, authenticationTag: randomArray, additionalAuthenticatedData: randomArray, mode: GCM.Mode.combined) // BAD
|
||||
let cgmb1 = GCM(iv: iv) // $ Alert
|
||||
let cgmb2 = GCM(iv: iv, additionalAuthenticatedData: randomArray, tagLength: 8, mode: GCM.Mode.combined) // $ Alert
|
||||
let cgmb3 = GCM(iv: iv, authenticationTag: randomArray, additionalAuthenticatedData: randomArray, mode: GCM.Mode.combined) // $ Alert
|
||||
let cgmg1 = GCM(iv: randomIv) // GOOD
|
||||
let cgmg2 = GCM(iv: randomIv, additionalAuthenticatedData: randomArray, tagLength: 8, mode: GCM.Mode.combined) // GOOD
|
||||
let cgmg3 = GCM(iv: randomIv, authenticationTag: randomArray, additionalAuthenticatedData: randomArray, mode: GCM.Mode.combined) // GOOD
|
||||
|
||||
// OFB
|
||||
let ofbb1 = OFB(iv: iv) // BAD
|
||||
let ofbb1 = OFB(iv: iv) // $ Alert
|
||||
let ofbg1 = OFB(iv: randomIv) // GOOD
|
||||
|
||||
// PCBC
|
||||
let pcbcb1 = PCBC(iv: iv) // BAD
|
||||
let pcbcb1 = PCBC(iv: iv) // $ Alert
|
||||
let pcbcg1 = PCBC(iv: randomIv) // GOOD
|
||||
|
||||
// CCM
|
||||
let ccmb1 = CCM(iv: iv, tagLength: 0, messageLength: 0, additionalAuthenticatedData: randomArray) // BAD
|
||||
let ccmb2 = CCM(iv: iv, tagLength: 0, messageLength: 0, authenticationTag: randomArray, additionalAuthenticatedData: randomArray) // BAD
|
||||
let ccmb1 = CCM(iv: iv, tagLength: 0, messageLength: 0, additionalAuthenticatedData: randomArray) // $ Alert
|
||||
let ccmb2 = CCM(iv: iv, tagLength: 0, messageLength: 0, authenticationTag: randomArray, additionalAuthenticatedData: randomArray) // $ Alert
|
||||
let ccmg1 = CCM(iv: randomIv, tagLength: 0, messageLength: 0, additionalAuthenticatedData: randomArray) // GOOD
|
||||
let ccmg2 = CCM(iv: randomIv, tagLength: 0, messageLength: 0, authenticationTag: randomArray, additionalAuthenticatedData: randomArray) // GOOD
|
||||
|
||||
// CTR
|
||||
let ctrb1 = CTR(iv: iv) // BAD
|
||||
let ctrb2 = CTR(iv: iv, counter: 0) // BAD
|
||||
let ctrb1 = CTR(iv: iv) // $ Alert
|
||||
let ctrb2 = CTR(iv: iv, counter: 0) // $ Alert
|
||||
let ctrg1 = CTR(iv: randomIv) // GOOD
|
||||
let ctrg2 = CTR(iv: randomIv, counter: 0) // GOOD
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-1333/ReDoS.ql
|
||||
query: queries/Security/CWE-1333/ReDoS.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -61,25 +61,25 @@ func myRegexpTests(myUrl: URL) throws {
|
||||
// Regex
|
||||
|
||||
_ = "((a*)*b)" // GOOD (never used)
|
||||
_ = try Regex("((a*)*b)") // DUBIOUS (never used) [FLAGGED]
|
||||
_ = try Regex("((a*)*b)").firstMatch(in: untainted) // DUBIOUS (never used on tainted input) [FLAGGED]
|
||||
_ = try Regex("((a*)*b)").firstMatch(in: tainted) // BAD
|
||||
_ = try Regex("((a*)*b)") // $ Alert // DUBIOUS (never used) [FLAGGED]
|
||||
_ = try Regex("((a*)*b)").firstMatch(in: untainted) // $ Alert // DUBIOUS (never used on tainted input) [FLAGGED]
|
||||
_ = try Regex("((a*)*b)").firstMatch(in: tainted) // $ Alert
|
||||
_ = try Regex(".*").firstMatch(in: tainted) // GOOD (safe regex)
|
||||
|
||||
let str = "((a*)*b)" // BAD
|
||||
let str = "((a*)*b)" // $ Alert
|
||||
let regex = try Regex(str)
|
||||
_ = try regex.firstMatch(in: tainted)
|
||||
|
||||
_ = try Regex(#"(?is)X(?:.|\n)*Y"#) // BAD - suggested attack should begin with 'x' or 'X', *not* 'isx' or 'isX'
|
||||
_ = try Regex(#"(?is)X(?:.|\n)*Y"#) // $ Alert // BAD - suggested attack should begin with 'x' or 'X', *not* 'isx' or 'isX'
|
||||
|
||||
// NSRegularExpression
|
||||
|
||||
_ = try? NSRegularExpression(pattern: "((a*)*b)") // DUBIOUS (never used) [FLAGGED]
|
||||
_ = try? NSRegularExpression(pattern: "((a*)*b)") // $ Alert // DUBIOUS (never used) [FLAGGED]
|
||||
|
||||
let nsregex1 = try? NSRegularExpression(pattern: "((a*)*b)") // DUBIOUS (never used on tainted input) [FLAGGED]
|
||||
let nsregex1 = try? NSRegularExpression(pattern: "((a*)*b)") // $ Alert // DUBIOUS (never used on tainted input) [FLAGGED]
|
||||
_ = nsregex1?.stringByReplacingMatches(in: untainted, range: NSRange(location: 0, length: untainted.utf16.count), withTemplate: "")
|
||||
|
||||
let nsregex2 = try? NSRegularExpression(pattern: "((a*)*b)") // BAD
|
||||
let nsregex2 = try? NSRegularExpression(pattern: "((a*)*b)") // $ Alert
|
||||
_ = nsregex2?.stringByReplacingMatches(in: tainted, range: NSRange(location: 0, length: tainted.utf16.count), withTemplate: "")
|
||||
|
||||
let nsregex3 = try? NSRegularExpression(pattern: ".*") // GOOD (safe regex)
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-134/UncontrolledFormatString.ql
|
||||
query: queries/Security/CWE-134/UncontrolledFormatString.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -76,7 +76,7 @@ func vasprintf_l(_ ret: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?, _ l
|
||||
|
||||
func MyLog(_ format: String, _ args: CVarArg...) {
|
||||
withVaList(args) { arglist in
|
||||
NSLogv(format, arglist) // BAD
|
||||
NSLogv(format, arglist) // $ Alert
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,34 +88,34 @@ class MyString {
|
||||
}
|
||||
|
||||
func tests() throws {
|
||||
let tainted = try! String(contentsOf: URL(string: "http://example.com")!)
|
||||
let tainted = try! String(contentsOf: URL(string: "http://example.com")!) // $ Source
|
||||
|
||||
_ = String("abc") // GOOD: not a format string
|
||||
_ = String(tainted) // GOOD: not a format string
|
||||
|
||||
_ = String(format: "abc") // GOOD: not tainted
|
||||
_ = String(format: tainted) // BAD
|
||||
_ = String(format: tainted) // $ Alert
|
||||
_ = String(format: "%s", "abc") // GOOD: not tainted
|
||||
_ = String(format: "%s", tainted) // GOOD: format string itself is not tainted
|
||||
_ = String(format: tainted, "abc") // BAD
|
||||
_ = String(format: tainted, tainted) // BAD
|
||||
_ = String(format: tainted, "abc") // $ Alert
|
||||
_ = String(format: tainted, tainted) // $ Alert
|
||||
|
||||
_ = String(format: tainted, arguments: []) // BAD
|
||||
_ = String(format: tainted, locale: nil) // BAD
|
||||
_ = String(format: tainted, locale: nil, arguments: []) // BAD
|
||||
_ = String.localizedStringWithFormat(tainted) // BAD
|
||||
_ = String(format: tainted, arguments: []) // $ Alert
|
||||
_ = String(format: tainted, locale: nil) // $ Alert
|
||||
_ = String(format: tainted, locale: nil, arguments: []) // $ Alert
|
||||
_ = String.localizedStringWithFormat(tainted) // $ Alert
|
||||
|
||||
_ = NSString(format: NSString(string: tainted), "abc") // BAD
|
||||
NSString.localizedStringWithFormat(NSString(string: tainted)) // BAD
|
||||
_ = NSString(format: NSString(string: tainted), "abc") // $ Alert
|
||||
NSString.localizedStringWithFormat(NSString(string: tainted)) // $ Alert
|
||||
|
||||
_ = NSMutableString(format: NSString(string: tainted), "abc") // BAD
|
||||
NSMutableString.localizedStringWithFormat(NSString(string: tainted)) // BAD
|
||||
_ = NSMutableString(format: NSString(string: tainted), "abc") // $ Alert
|
||||
NSMutableString.localizedStringWithFormat(NSString(string: tainted)) // $ Alert
|
||||
|
||||
NSLog("abc") // GOOD: not tainted
|
||||
NSLog(tainted) // BAD
|
||||
MyLog(tainted) // BAD
|
||||
NSLog(tainted) // $ Alert
|
||||
MyLog(tainted) // $ Alert
|
||||
|
||||
NSException.raise(NSExceptionName("exception"), format: tainted, arguments: getVaList([])) // BAD
|
||||
NSException.raise(NSExceptionName("exception"), format: tainted, arguments: getVaList([])) // $ Alert
|
||||
|
||||
let taintedVal = Int(tainted)!
|
||||
let taintedSan = "\(taintedVal)"
|
||||
@@ -127,32 +127,32 @@ func tests() throws {
|
||||
|
||||
_ = String("abc").appendingFormat("%s", "abc") // GOOD: not tainted
|
||||
_ = String("abc").appendingFormat("%s", tainted) // GOOD: format not tainted
|
||||
_ = String("abc").appendingFormat(tainted, "abc") // BAD
|
||||
_ = String("abc").appendingFormat(tainted, "abc") // $ Alert
|
||||
_ = String(tainted).appendingFormat("%s", "abc") // GOOD: format not tainted
|
||||
|
||||
let s = NSMutableString(string: "foo")
|
||||
s.appendFormat(NSString(string: "%s"), "abc") // GOOD: not tainted
|
||||
s.appendFormat(NSString(string: tainted), "abc") // BAD
|
||||
s.appendFormat(NSString(string: tainted), "abc") // $ Alert
|
||||
|
||||
_ = NSPredicate(format: tainted) // GOOD: this should be flagged by `swift/predicate-injection`, not `swift/uncontrolled-format-string`
|
||||
|
||||
tainted.withCString({
|
||||
cstr in
|
||||
_ = dprintf(0, cstr, "abc") // BAD
|
||||
_ = dprintf(0, cstr, "abc") // $ Alert
|
||||
_ = dprintf(0, "%s", cstr) // GOOD: format not tainted
|
||||
_ = vprintf(cstr, getVaList(["abc"])) // BAD
|
||||
_ = vprintf(cstr, getVaList(["abc"])) // $ Alert
|
||||
_ = vprintf("%s", getVaList([cstr])) // GOOD: format not tainted
|
||||
_ = vfprintf(nil, cstr, getVaList(["abc"])) // BAD
|
||||
_ = vfprintf(nil, cstr, getVaList(["abc"])) // $ Alert
|
||||
_ = vfprintf(nil, "%s", getVaList([cstr])) // GOOD: format not tainted
|
||||
_ = vasprintf_l(nil, nil, cstr, getVaList(["abc"])) // BAD
|
||||
_ = vasprintf_l(nil, nil, cstr, getVaList(["abc"])) // $ Alert
|
||||
_ = vasprintf_l(nil, nil, "%s", getVaList([cstr])) // GOOD: format not tainted
|
||||
})
|
||||
|
||||
myFormatMessage(string: tainted, "abc") // BAD [NOT DETECTED]
|
||||
myFormatMessage(string: "%s", tainted) // GOOD: format not tainted
|
||||
|
||||
_ = MyString(format: tainted, "abc") // BAD
|
||||
_ = MyString(format: tainted, "abc") // $ Alert
|
||||
_ = MyString(format: "%s", tainted) // GOOD: format not tainted
|
||||
_ = MyString(formatString: tainted, "abc") // BAD
|
||||
_ = MyString(formatString: tainted, "abc") // $ Alert
|
||||
_ = MyString(formatString: "%s", tainted) // GOOD: format not tainted
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-259/ConstantPassword.ql
|
||||
query: queries/Security/CWE-259/ConstantPassword.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -66,7 +66,7 @@ func test(cond: Bool) {
|
||||
let myData = Data(0)
|
||||
|
||||
let myRandomPassword = getARandomPassword()
|
||||
let myConstPassword = "abc123"
|
||||
let myConstPassword = "abc123" // $ Source
|
||||
let myMaybePassword = cond ? myRandomPassword : myConstPassword
|
||||
|
||||
// reasonable usage
|
||||
@@ -74,11 +74,11 @@ func test(cond: Bool) {
|
||||
let a = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myRandomPassword) // GOOD
|
||||
let _ = try? myDecryptor.decryptData(a, withPassword: myRandomPassword) // GOOD
|
||||
|
||||
let b = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // BAD
|
||||
let _ = try? myDecryptor.decryptData(b, withPassword: myConstPassword) // BAD
|
||||
let b = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // $ Alert
|
||||
let _ = try? myDecryptor.decryptData(b, withPassword: myConstPassword) // $ Alert
|
||||
|
||||
let c = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myMaybePassword) // BAD
|
||||
let _ = try? myDecryptor.decryptData(c, withPassword: myMaybePassword) // BAD
|
||||
let c = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myMaybePassword) // $ Alert
|
||||
let _ = try? myDecryptor.decryptData(c, withPassword: myMaybePassword) // $ Alert
|
||||
|
||||
// all methods
|
||||
|
||||
@@ -88,22 +88,22 @@ func test(cond: Bool) {
|
||||
let mySalt = Data(0)
|
||||
let mySalt2 = Data(0)
|
||||
|
||||
let _ = myEncryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myEncryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myDecryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myDecryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myEncryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // $ Alert
|
||||
let _ = myEncryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // $ Alert
|
||||
let _ = myDecryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // $ Alert
|
||||
let _ = myDecryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // $ Alert
|
||||
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // $ Alert
|
||||
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2) // $ Alert
|
||||
|
||||
let _ = RNDecryptor(password: myConstPassword, handler: myHandler) // BAD
|
||||
let _ = RNDecryptor(password: myConstPassword, handler: myHandler) // $ Alert
|
||||
|
||||
let _ = try? myDecryptor.decryptData(myData, withPassword: myConstPassword) // BAD
|
||||
let _ = try? myDecryptor.decryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // BAD
|
||||
let _ = try? myDecryptor.decryptData(myData, withPassword: myConstPassword) // $ Alert
|
||||
let _ = try? myDecryptor.decryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // $ Alert
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ final class Scrypt {
|
||||
|
||||
// Helper functions
|
||||
func getConstantString() -> String {
|
||||
"this string is constant"
|
||||
"this string is constant" // $ Source
|
||||
}
|
||||
|
||||
func getConstantArray() -> Array<UInt8> {
|
||||
@@ -40,7 +40,7 @@ func getRandomArray() -> Array<UInt8> {
|
||||
// --- tests ---
|
||||
|
||||
func test() {
|
||||
let constantPassword: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f]
|
||||
let constantPassword: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f] // $ Source
|
||||
let constantStringPassword = getConstantArray()
|
||||
let randomPassword = getRandomArray()
|
||||
let randomArray = getRandomArray()
|
||||
@@ -48,23 +48,23 @@ func test() {
|
||||
let iterations = 120120
|
||||
|
||||
// HKDF test cases
|
||||
let hkdfb1 = HKDF(password: constantPassword, salt: randomArray, info: randomArray, keyLength: 0, variant: variant) // BAD
|
||||
let hkdfb2 = HKDF(password: constantStringPassword, salt: randomArray, info: randomArray, keyLength: 0, variant: variant) // BAD
|
||||
let hkdfb1 = HKDF(password: constantPassword, salt: randomArray, info: randomArray, keyLength: 0, variant: variant) // $ Alert
|
||||
let hkdfb2 = HKDF(password: constantStringPassword, salt: randomArray, info: randomArray, keyLength: 0, variant: variant) // $ Alert
|
||||
let hkdfg1 = HKDF(password: randomPassword, salt: randomArray, info: randomArray, keyLength: 0, variant: variant) // GOOD
|
||||
|
||||
// PBKDF1 test cases
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: constantPassword, salt: randomArray, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: constantStringPassword, salt: randomArray, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: constantPassword, salt: randomArray, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: constantStringPassword, salt: randomArray, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf1g1 = PKCS5.PBKDF1(password: randomPassword, salt: randomArray, iterations: iterations, keyLength: 0) // GOOD
|
||||
|
||||
|
||||
// PBKDF2 test cases
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: constantPassword, salt: randomArray, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: constantStringPassword, salt: randomArray, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: constantPassword, salt: randomArray, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: constantStringPassword, salt: randomArray, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf2g1 = PKCS5.PBKDF2(password: randomPassword, salt: randomArray, iterations: iterations, keyLength: 0) // GOOD
|
||||
|
||||
// Scrypt test cases
|
||||
let scryptb1 = Scrypt(password: constantPassword, salt: randomArray, dkLen: 64, N: 16384, r: 8, p: 1) // BAD
|
||||
let scryptb2 = Scrypt(password: constantStringPassword, salt: randomArray, dkLen: 64, N: 16384, r: 8, p: 1) // BAD
|
||||
let scryptb1 = Scrypt(password: constantPassword, salt: randomArray, dkLen: 64, N: 16384, r: 8, p: 1) // $ Alert
|
||||
let scryptb2 = Scrypt(password: constantStringPassword, salt: randomArray, dkLen: 64, N: 16384, r: 8, p: 1) // $ Alert
|
||||
let scryptg1 = Scrypt(password: randomPassword, salt: randomArray, dkLen: 64, N: 16384, r: 8, p: 1) // GOOD
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-311/CleartextStorageDatabase.ql
|
||||
query: queries/Security/CWE-311/CleartextStorageDatabase.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-311/CleartextTransmission.ql
|
||||
query: queries/Security/CWE-311/CleartextTransmission.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -116,64 +116,64 @@ func ==<V>(lhs: Expression<V>, rhs: V) -> Expression<Bool> { return Expression<B
|
||||
func test_sqlite_swift_api(db: Connection, id: Int, mobilePhoneNumber: String) throws {
|
||||
// --- sensitive data in SQL (in practice these cases may also be SQL injection) ---
|
||||
|
||||
let insertQuery = "INSERT INTO CONTACTS(ID, NUMBER) VALUES(\(id), \(mobilePhoneNumber));"
|
||||
let updateQuery = "UPDATE CONTACTS SET NUMBER=\(mobilePhoneNumber) WHERE ID=\(id);"
|
||||
let insertQuery = "INSERT INTO CONTACTS(ID, NUMBER) VALUES(\(id), \(mobilePhoneNumber));" // $ Source
|
||||
let updateQuery = "UPDATE CONTACTS SET NUMBER=\(mobilePhoneNumber) WHERE ID=\(id);" // $ Source
|
||||
let deleteQuery = "DELETE FROM CONTACTS WHERE ID=\(id);"
|
||||
|
||||
try db.execute(insertQuery) // BAD (sensitive data)
|
||||
try db.execute(updateQuery) // BAD (sensitive data)
|
||||
try db.execute(insertQuery) // $ Alert // BAD (sensitive data)
|
||||
try db.execute(updateQuery) // $ Alert // BAD (sensitive data)
|
||||
try db.execute(deleteQuery) // GOOD
|
||||
|
||||
_ = try db.prepare(insertQuery).run() // BAD (sensitive data)
|
||||
_ = try db.prepare(updateQuery).run() // BAD (sensitive data)
|
||||
_ = try db.prepare(insertQuery).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try db.prepare(updateQuery).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try db.prepare(deleteQuery).run() // GOOD
|
||||
|
||||
_ = try db.run(insertQuery) // BAD (sensitive data)
|
||||
_ = try db.run(updateQuery) // BAD (sensitive data)
|
||||
_ = try db.run(insertQuery) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.run(updateQuery) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.run(deleteQuery) // GOOD
|
||||
|
||||
_ = try db.scalar(insertQuery) // BAD (sensitive data)
|
||||
_ = try db.scalar(updateQuery) // BAD (sensitive data)
|
||||
_ = try db.scalar(insertQuery) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.scalar(updateQuery) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.scalar(deleteQuery) // GOOD
|
||||
|
||||
_ = try Statement(db, insertQuery).run() // BAD (sensitive data)
|
||||
_ = try Statement(db, updateQuery).run() // BAD (sensitive data)
|
||||
_ = try Statement(db, insertQuery).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try Statement(db, updateQuery).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try Statement(db, deleteQuery).run() // GOOD
|
||||
|
||||
// --- sensitive data in bindings ---
|
||||
|
||||
let varQuery1 = "UPDATE CONTACTS SET NUMBER=?;"
|
||||
|
||||
_ = try db.prepare(varQuery1, mobilePhoneNumber).run() // BAD (sensitive data)
|
||||
_ = try db.run(varQuery1, mobilePhoneNumber) // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery1, mobilePhoneNumber) // BAD (sensitive data)
|
||||
_ = try db.prepare(varQuery1, mobilePhoneNumber).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try db.run(varQuery1, mobilePhoneNumber) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery1, mobilePhoneNumber) // $ Alert // BAD (sensitive data)
|
||||
|
||||
let stmt1 = try db.prepare(varQuery1) // GOOD
|
||||
_ = try stmt1.bind(mobilePhoneNumber).run() // BAD (sensitive data)
|
||||
_ = try stmt1.run(mobilePhoneNumber) // BAD (sensitive data)
|
||||
_ = try stmt1.scalar(mobilePhoneNumber) // BAD (sensitive data)
|
||||
_ = try stmt1.bind(mobilePhoneNumber).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt1.run(mobilePhoneNumber) // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt1.scalar(mobilePhoneNumber) // $ Alert // BAD (sensitive data)
|
||||
|
||||
let varQuery2 = "UPDATE CONTACTS SET NUMBER=? WHERE ID=?;"
|
||||
|
||||
_ = try db.prepare(varQuery2, [mobilePhoneNumber, id]).run() // BAD (sensitive data)
|
||||
_ = try db.run(varQuery2, [mobilePhoneNumber, id]) // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery2, [mobilePhoneNumber, id]) // BAD (sensitive data)
|
||||
_ = try db.prepare(varQuery2, [mobilePhoneNumber, id]).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try db.run(varQuery2, [mobilePhoneNumber, id]) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery2, [mobilePhoneNumber, id]) // $ Alert // BAD (sensitive data)
|
||||
|
||||
let stmt2 = try db.prepare(varQuery2) // GOOD
|
||||
_ = try stmt2.bind([mobilePhoneNumber, id]).run() // BAD (sensitive data)
|
||||
_ = try stmt2.run([mobilePhoneNumber, id]) // BAD (sensitive data)
|
||||
_ = try stmt2.scalar([mobilePhoneNumber, id]) // BAD (sensitive data)
|
||||
_ = try stmt2.bind([mobilePhoneNumber, id]).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt2.run([mobilePhoneNumber, id]) // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt2.scalar([mobilePhoneNumber, id]) // $ Alert // BAD (sensitive data)
|
||||
|
||||
let varQuery3 = "UPDATE CONTACTS SET NUMBER=$number WHERE ID=$id;"
|
||||
|
||||
_ = try db.prepare(varQuery3, ["id": id, "number": mobilePhoneNumber]).run() // BAD (sensitive data)
|
||||
_ = try db.run(varQuery3, ["id": id, "number": mobilePhoneNumber]) // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery3, ["id": id, "number": mobilePhoneNumber]) // BAD (sensitive data)
|
||||
_ = try db.prepare(varQuery3, ["id": id, "number": mobilePhoneNumber]).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try db.run(varQuery3, ["id": id, "number": mobilePhoneNumber]) // $ Alert // BAD (sensitive data)
|
||||
_ = try db.scalar(varQuery3, ["id": id, "number": mobilePhoneNumber]) // $ Alert // BAD (sensitive data)
|
||||
|
||||
let stmt3 = try db.prepare(varQuery3) // GOOD
|
||||
_ = try stmt3.bind(["id": id, "number": mobilePhoneNumber]).run() // BAD (sensitive data)
|
||||
_ = try stmt3.run(["id": id, "number": mobilePhoneNumber]) // BAD (sensitive data)
|
||||
_ = try stmt3.scalar(["id": id, "number": mobilePhoneNumber]) // BAD (sensitive data)
|
||||
_ = try stmt3.bind(["id": id, "number": mobilePhoneNumber]).run() // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt3.run(["id": id, "number": mobilePhoneNumber]) // $ Alert // BAD (sensitive data)
|
||||
_ = try stmt3.scalar(["id": id, "number": mobilePhoneNumber]) // $ Alert // BAD (sensitive data)
|
||||
|
||||
// --- higher level insert / update ---
|
||||
|
||||
@@ -183,20 +183,20 @@ func test_sqlite_swift_api(db: Connection, id: Int, mobilePhoneNumber: String) t
|
||||
let filter = table.filter(idExpr == id) // GOOD
|
||||
|
||||
try db.run(table.insert(idExpr <- id, numberExpr <- "123")) // GOOD
|
||||
try db.run(table.insert(idExpr <- id, numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
|
||||
try db.run(table.insert(idExpr <- id, numberExpr <- mobilePhoneNumber)) // $ Alert // BAD (sensitive data)
|
||||
|
||||
try db.run(table.update(numberExpr <- "123")) // GOOD
|
||||
try db.run(table.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
|
||||
try db.run(table.update(numberExpr <- mobilePhoneNumber)) // $ Alert // BAD (sensitive data)
|
||||
try db.run(filter.update(numberExpr <- "123")) // GOOD
|
||||
try db.run(filter.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
|
||||
try db.run(filter.update(numberExpr <- mobilePhoneNumber)) // $ Alert // BAD (sensitive data)
|
||||
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: "456"))) // GOOD
|
||||
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: mobilePhoneNumber))) // BAD (sensitive data)
|
||||
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: mobilePhoneNumber))) // $ Alert // BAD (sensitive data)
|
||||
// (much more complex query construction is possible in SQLite.swift)
|
||||
|
||||
let goodMany = [[numberExpr <- "456"]]
|
||||
let badMany = [[numberExpr <- mobilePhoneNumber]]
|
||||
let badMany = [[numberExpr <- mobilePhoneNumber]] // $ Source
|
||||
try db.run(table.insertMany(goodMany)) // GOOD
|
||||
try db.run(table.insertMany(badMany)) // BAD (sensitive data)
|
||||
try db.run(table.insertMany(badMany)) // $ Alert // BAD (sensitive data)
|
||||
try db.run(table.insertMany(or: OnConflict.replace, goodMany)) // GOOD
|
||||
try db.run(table.insertMany(or: OnConflict.replace, badMany)) // BAD (sensitive data)
|
||||
try db.run(table.insertMany(or: OnConflict.replace, badMany)) // $ Alert // BAD (sensitive data)
|
||||
}
|
||||
|
||||
@@ -39,12 +39,12 @@ func sqlite3_bind_text(
|
||||
func test_sqlite3_c_api(db: OpaquePointer?, id: Int32, medicalNotes: String) {
|
||||
// --- sensitive data in SQL (in practice these cases may also be SQL injection) ---
|
||||
|
||||
let insertQuery = "INSERT INTO PATIENTS(ID, NOTES) VALUES(\(id), \(medicalNotes));"
|
||||
let updateQuery = "UPDATE PATIENTS SET NOTES=\(medicalNotes) WHERE ID=\(id);"
|
||||
let insertQuery = "INSERT INTO PATIENTS(ID, NOTES) VALUES(\(id), \(medicalNotes));" // $ Source
|
||||
let updateQuery = "UPDATE PATIENTS SET NOTES=\(medicalNotes) WHERE ID=\(id);" // $ Source
|
||||
let deleteQuery = "DELETE FROM PATIENTS WHERE ID=\(id);"
|
||||
|
||||
let _ = sqlite3_exec(db, insertQuery, nil, nil, nil) // BAD (sensitive data)
|
||||
let _ = sqlite3_exec(db, updateQuery, nil, nil, nil) // BAD (sensitive data)
|
||||
let _ = sqlite3_exec(db, insertQuery, nil, nil, nil) // $ Alert // BAD (sensitive data)
|
||||
let _ = sqlite3_exec(db, updateQuery, nil, nil, nil) // $ Alert // BAD (sensitive data)
|
||||
let _ = sqlite3_exec(db, deleteQuery, nil, nil, nil) // GOOD
|
||||
|
||||
// --- sensitive data in bindings ---
|
||||
@@ -55,7 +55,7 @@ func test_sqlite3_c_api(db: OpaquePointer?, id: Int32, medicalNotes: String) {
|
||||
|
||||
if (sqlite3_prepare(db, varQuery, -1, &stmt1, nil) == SQLITE_OK) { // GOOD
|
||||
if (sqlite3_bind_int(stmt1, 1, id) == SQLITE_OK) { // GOOD
|
||||
if (sqlite3_bind_text(stmt1, 2, medicalNotes, -1, SQLITE_TRANSIENT) == SQLITE_OK) { // BAD (sensitive data)
|
||||
if (sqlite3_bind_text(stmt1, 2, medicalNotes, -1, SQLITE_TRANSIENT) == SQLITE_OK) { // $ Alert // BAD (sensitive data)
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,11 +147,11 @@ struct MyEncodable: Encodable {
|
||||
func test1(username: String, password: String, email: String, harmless: String) {
|
||||
// sensitive data in URL
|
||||
|
||||
AF.request("http://example.com/login?p=" + password) // BAD
|
||||
AF.request("http://example.com/login?p=" + password) // $ Alert
|
||||
AF.request("http://example.com/login?h=" + harmless) // GOOD (not sensitive)
|
||||
AF.streamRequest("http://example.com/login?p=" + password) // BAD
|
||||
AF.streamRequest("http://example.com/login?p=" + password) // $ Alert
|
||||
AF.streamRequest("http://example.com/login?h=" + harmless) // GOOD (not sensitive)
|
||||
AF.download("http://example.com/" + email + ".html") // BAD
|
||||
AF.download("http://example.com/" + email + ".html") // $ Alert
|
||||
AF.download("http://example.com/" + harmless + ".html") // GOOD (not sensitive)
|
||||
|
||||
// sensitive data in parameters
|
||||
|
||||
@@ -16,7 +16,7 @@ class NSManagedObject : NSObject
|
||||
class MyManagedObject : NSManagedObject
|
||||
{
|
||||
func setIndirect(value: String) {
|
||||
setValue(value, forKey: "myKey")
|
||||
setValue(value, forKey: "myKey") // $ Alert
|
||||
}
|
||||
|
||||
var myValue: String {
|
||||
@@ -29,7 +29,7 @@ class MyManagedObject : NSManagedObject
|
||||
}
|
||||
}
|
||||
set {
|
||||
setValue(newValue, forKey: "myKey") // [additional result reported here]
|
||||
setValue(newValue, forKey: "myKey") // $ Alert // [additional result reported here]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,23 +45,23 @@ func doSomething(password: String) { }
|
||||
func test1(obj : NSManagedObject, password : String, password_hash : String) {
|
||||
// NSManagedObject methods...
|
||||
|
||||
obj.setValue(password, forKey: "myKey") // BAD
|
||||
obj.setValue(password, forKey: "myKey") // $ Alert
|
||||
obj.setValue(password_hash, forKey: "myKey") // GOOD (not sensitive)
|
||||
|
||||
obj.setPrimitiveValue(password, forKey: "myKey") // BAD
|
||||
obj.setPrimitiveValue(password, forKey: "myKey") // $ Alert
|
||||
obj.setPrimitiveValue(password_hash, forKey: "myKey") // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
func test2(obj : MyManagedObject, password : String, password_file : String) {
|
||||
// MyManagedObject methods...
|
||||
|
||||
obj.setValue(password, forKey: "myKey") // BAD
|
||||
obj.setValue(password, forKey: "myKey") // $ Alert
|
||||
obj.setValue(password_file, forKey: "myKey") // GOOD (not sensitive)
|
||||
|
||||
obj.setIndirect(value: password) // BAD [reported on line 19]
|
||||
obj.setIndirect(value: password) // $ Source // BAD [reported on line 19]
|
||||
obj.setIndirect(value: password_file) // GOOD (not sensitive)
|
||||
|
||||
obj.myValue = password // BAD [also reported on line 32]
|
||||
obj.myValue = password // $ Alert Source // BAD [also reported on line 32]
|
||||
obj.myValue = password_file // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
@@ -74,27 +74,27 @@ func test3(obj : NSManagedObject, x : String) {
|
||||
// alternative evidence of sensitivity...
|
||||
|
||||
obj.setValue(x, forKey: "myKey") // BAD [NOT REPORTED]
|
||||
doSomething(password: x);
|
||||
obj.setValue(x, forKey: "myKey") // BAD
|
||||
doSomething(password: x); // $ Source
|
||||
obj.setValue(x, forKey: "myKey") // $ Alert
|
||||
|
||||
let y = getPassword();
|
||||
obj.setValue(y, forKey: "myKey") // BAD
|
||||
let y = getPassword(); // $ Source
|
||||
obj.setValue(y, forKey: "myKey") // $ Alert
|
||||
|
||||
let z = MyClass()
|
||||
obj.setValue(z.harmless, forKey: "myKey") // GOOD (not sensitive)
|
||||
obj.setValue(z.password, forKey: "myKey") // BAD
|
||||
obj.setValue(z.password, forKey: "myKey") // $ Alert
|
||||
}
|
||||
|
||||
func test4(obj : NSManagedObject, passwd : String) {
|
||||
// sanitizers...
|
||||
|
||||
var x = passwd;
|
||||
var y = passwd;
|
||||
var z = passwd;
|
||||
var x = passwd; // $ Source
|
||||
var y = passwd; // $ Source
|
||||
var z = passwd; // $ Source
|
||||
|
||||
obj.setValue(x, forKey: "myKey") // BAD
|
||||
obj.setValue(y, forKey: "myKey") // BAD
|
||||
obj.setValue(z, forKey: "myKey") // BAD
|
||||
obj.setValue(x, forKey: "myKey") // $ Alert
|
||||
obj.setValue(y, forKey: "myKey") // $ Alert
|
||||
obj.setValue(z, forKey: "myKey") // $ Alert
|
||||
|
||||
x = encrypt(x);
|
||||
hash(data: &y);
|
||||
@@ -125,8 +125,8 @@ func test5(obj : NSManagedObject) {
|
||||
// more variants...
|
||||
|
||||
obj.setValue(createSecureKey(), forKey: "myKey") // BAD [NOT DETECTED]
|
||||
obj.setValue(generateSecretKey(), forKey: "myKey") // BAD
|
||||
obj.setValue(getCertificate(), forKey: "myKey") // BAD
|
||||
obj.setValue(generateSecretKey(), forKey: "myKey") // $ Alert
|
||||
obj.setValue(getCertificate(), forKey: "myKey") // $ Alert
|
||||
|
||||
let gen = KeyGen()
|
||||
let v = gen.generate()
|
||||
|
||||
@@ -34,35 +34,35 @@ func testCoreData2_1(obj: MyManagedObject2, maybeObj: MyManagedObject2?, value:
|
||||
{
|
||||
// @NSManaged fields of an NSManagedObject...
|
||||
obj.myValue = value // GOOD (not sensitive)
|
||||
obj.myValue = bankAccountNo // BAD
|
||||
obj.myValue = bankAccountNo // $ Alert
|
||||
obj.myBankAccountNumber = value // BAD [NOT DETECTED]
|
||||
obj.myBankAccountNumber = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
obj.myBankAccountNumber2 = value // BAD [NOT DETECTED]
|
||||
obj.myBankAccountNumber2 = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber2 = bankAccountNo // $ Alert
|
||||
obj.notStoredBankAccountNumber = value // GOOD (not stored in the database)
|
||||
obj.notStoredBankAccountNumber = bankAccountNo // GOOD (not stored in the datbase) [FALSE POSITIVE]
|
||||
obj.notStoredBankAccountNumber = bankAccountNo // $ Alert // GOOD (not stored in the datbase) [FALSE POSITIVE]
|
||||
|
||||
maybeObj?.myValue = value // GOOD (not sensitive)
|
||||
maybeObj?.myValue = bankAccountNo // BAD
|
||||
maybeObj?.myValue = bankAccountNo // $ Alert
|
||||
maybeObj?.myBankAccountNumber = value // BAD [NOT DETECTED]
|
||||
maybeObj?.myBankAccountNumber = bankAccountNo // BAD
|
||||
maybeObj?.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
maybeObj?.myBankAccountNumber2 = value // BAD [NOT DETECTED]
|
||||
maybeObj?.myBankAccountNumber2 = bankAccountNo // BAD
|
||||
maybeObj?.myBankAccountNumber2 = bankAccountNo // $ Alert
|
||||
maybeObj?.notStoredBankAccountNumber = value // GOOD (not stored in the database)
|
||||
maybeObj?.notStoredBankAccountNumber = bankAccountNo // GOOD (not stored in the datbase) [FALSE POSITIVE]
|
||||
maybeObj?.notStoredBankAccountNumber = bankAccountNo // $ Alert // GOOD (not stored in the datbase) [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
class testCoreData2_2 {
|
||||
func myFunc(obj: MyManagedObject2, bankAccountNo: Int) {
|
||||
obj.myBankAccountNumber = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
obj.myBankAccountNumber = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
} else {
|
||||
obj.myBankAccountNumber = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
}
|
||||
|
||||
obj.myBankAccountNumber = bankAccountNo // BAD
|
||||
obj.myBankAccountNumber = bankAccountNo // $ Alert
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,31 +76,31 @@ class MyContainer {
|
||||
func testCoreData2_3(dbObj: MyManagedObject2, maybeObj: MyManagedObject2?, container: MyContainer, bankAccountNo: MyContainer, bankAccountNo2: MyContainer!) {
|
||||
dbObj.myValue = container.value // GOOD (not sensitive)
|
||||
dbObj.myValue = container.value2 // GOOD (not sensitive)
|
||||
dbObj.myValue = container.bankAccountNo // BAD
|
||||
dbObj.myValue = container.bankAccountNo2 // BAD
|
||||
dbObj.myValue = container.bankAccountNo // $ Alert
|
||||
dbObj.myValue = container.bankAccountNo2 // $ Alert
|
||||
|
||||
dbObj.myValue = bankAccountNo.value // BAD
|
||||
dbObj.myValue = bankAccountNo.value2 // BAD
|
||||
dbObj.myValue = bankAccountNo2.value // BAD
|
||||
dbObj.myValue = bankAccountNo2.value2 // BAD
|
||||
dbObj.myValue = bankAccountNo.value // $ Alert
|
||||
dbObj.myValue = bankAccountNo.value2 // $ Alert
|
||||
dbObj.myValue = bankAccountNo2.value // $ Alert
|
||||
dbObj.myValue = bankAccountNo2.value2 // $ Alert
|
||||
|
||||
maybeObj?.myValue = container.bankAccountNo // BAD
|
||||
maybeObj?.myValue = bankAccountNo.value // BAD
|
||||
maybeObj?.myValue = bankAccountNo2.value2 // BAD
|
||||
maybeObj?.myValue = container.bankAccountNo // $ Alert
|
||||
maybeObj?.myValue = bankAccountNo.value // $ Alert
|
||||
maybeObj?.myValue = bankAccountNo2.value2 // $ Alert
|
||||
|
||||
var a = bankAccountNo // sensitive
|
||||
var a = bankAccountNo // $ Source // sensitive
|
||||
var b = a.value
|
||||
dbObj.myValue = b // BAD
|
||||
dbObj.myValue = b // $ Alert
|
||||
|
||||
let c = bankAccountNo // sensitive
|
||||
let c = bankAccountNo // $ Source // sensitive
|
||||
var d: MyContainer = MyContainer()
|
||||
d.value = c.value
|
||||
dbObj.myValue = d.value // BAD
|
||||
dbObj.myValue = d.value // $ Alert
|
||||
dbObj.myValue = d.value2 // GOOD
|
||||
|
||||
let e = bankAccountNo // sensitive
|
||||
let e = bankAccountNo // $ Source // sensitive
|
||||
var f: MyContainer?
|
||||
f?.value = e.value
|
||||
dbObj.myValue = e.value // BAD
|
||||
dbObj.myValue = e.value2 // GOOD [FALSE POSITIVE]
|
||||
dbObj.myValue = e.value // $ Alert
|
||||
dbObj.myValue = e.value2 // $ Alert // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
@@ -70,145 +70,145 @@ class CommonTableExpression {
|
||||
// --- tests ---
|
||||
|
||||
func test(database: Database, password: String, harmless: String) {
|
||||
let _ = database.allStatements(sql: "", arguments: [password]) // BAD
|
||||
let _ = database.allStatements(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = database.allStatements(sql: "", arguments: [harmless]) // GOOD
|
||||
|
||||
database.execute(sql: "", arguments: [password]) // BAD
|
||||
database.execute(sql: "", arguments: [password]) // $ Alert
|
||||
database.execute(sql: "", arguments: [harmless]) // GOOD
|
||||
}
|
||||
|
||||
func testSqlRequest(password: String, harmless: String) {
|
||||
let _ = SQLRequest(sql: "", arguments: [password]) // BAD
|
||||
let _ = SQLRequest(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = SQLRequest(sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], adapter: nil) // BAD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
let _ = SQLRequest(sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], cached: false) // BAD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: "", arguments: [harmless], cached: false) // GOOD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], adapter: nil, cached: false) // BAD
|
||||
let _ = SQLRequest(sql: "", arguments: [password], adapter: nil, cached: false) // $ Alert
|
||||
let _ = SQLRequest(sql: "", arguments: [harmless], adapter: nil, cached: false) // GOOD
|
||||
}
|
||||
|
||||
func test(sql: SQL, password: String, harmless: String) {
|
||||
let _ = SQL(sql: "", arguments: [password]) // BAD
|
||||
let _ = SQL(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = SQL(sql: "", arguments: [harmless]) // GOOD
|
||||
|
||||
sql.append(sql: "", arguments: [password]) // BAD
|
||||
sql.append(sql: "", arguments: [password]) // $ Alert
|
||||
sql.append(sql: "", arguments: [harmless]) // GOOD
|
||||
}
|
||||
|
||||
func testSqlStatementCursor(database: Database, password: String, harmless: String) {
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [password]) // BAD
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [password], prepFlags: 0) // BAD
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [password]) // $ Alert
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [password], prepFlags: 0) // $ Alert
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = SQLStatementCursor(database: database, sql: "", arguments: [harmless], prepFlags: 0) // GOOD
|
||||
}
|
||||
|
||||
func testTableRecord(password: String, harmless: String) {
|
||||
let _ = TableRecord.select(sql: "", arguments: [password]) // BAD
|
||||
let _ = TableRecord.select(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = TableRecord.select(sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = TableRecord.filter(sql: "", arguments: [password]) // BAD
|
||||
let _ = TableRecord.filter(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = TableRecord.filter(sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = TableRecord.order(sql: "", arguments: [password]) // BAD
|
||||
let _ = TableRecord.order(sql: "", arguments: [password]) // $ Alert
|
||||
let _ = TableRecord.order(sql: "", arguments: [harmless]) // GOOD
|
||||
}
|
||||
|
||||
func test(row: Row, stmt: Statement, password: String, harmless: String) {
|
||||
row.fetchCursor(stmt, sql: "", arguments: [password]) // BAD
|
||||
row.fetchCursor(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
row.fetchCursor(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
row.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
row.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
row.fetchCursor(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
row.fetchAll(stmt, sql: "", arguments: [password]) // BAD
|
||||
row.fetchAll(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
row.fetchAll(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
row.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
row.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
row.fetchAll(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
row.fetchSet(stmt, sql: "", arguments: [password]) // BAD
|
||||
row.fetchSet(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
row.fetchSet(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
row.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
row.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
row.fetchSet(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
row.fetchOne(stmt, sql: "", arguments: [password]) // BAD
|
||||
row.fetchOne(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
row.fetchOne(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
row.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
row.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
row.fetchOne(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
}
|
||||
|
||||
func test(databaseValueConvertible: DatabaseValueConvertible, stmt: Statement, password: String, harmless: String) {
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [password]) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchCursor(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [password]) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchAll(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [password]) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchSet(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [password]) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
databaseValueConvertible.fetchOne(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
}
|
||||
|
||||
func test(fetchableRecord: FetchableRecord, stmt: Statement, password: String, harmless: String) {
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [password]) // BAD
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [password]) // BAD
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchCursor(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
fetchableRecord.fetchCursor(stmt, arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [password]) // BAD
|
||||
fetchableRecord.fetchAll(stmt, arguments: [password]) // BAD
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchAll(stmt, arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchAll(stmt, arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchAll(stmt, arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchAll(stmt, arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchAll(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
fetchableRecord.fetchAll(stmt, arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [password]) // BAD
|
||||
fetchableRecord.fetchSet(stmt, arguments: [password]) // BAD
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchSet(stmt, arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchSet(stmt, arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchSet(stmt, arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchSet(stmt, arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchSet(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
fetchableRecord.fetchSet(stmt, arguments: [harmless], adapter: nil) // GOOD
|
||||
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [password]) // BAD
|
||||
fetchableRecord.fetchOne(stmt, arguments: [password]) // BAD
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchOne(stmt, arguments: [password]) // $ Alert
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchOne(stmt, arguments: [harmless]) // GOOD
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchOne(stmt, arguments: [password], adapter: nil) // BAD
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchOne(stmt, arguments: [password], adapter: nil) // $ Alert
|
||||
fetchableRecord.fetchOne(stmt, sql: "", arguments: [harmless], adapter: nil) // GOOD
|
||||
fetchableRecord.fetchOne(stmt, arguments: [harmless], adapter: nil) // GOOD
|
||||
}
|
||||
|
||||
func test(stmt: Statement, password: String, harmless: String) {
|
||||
stmt.execute(arguments: [password]) // BAD
|
||||
stmt.execute(arguments: [password]) // $ Alert
|
||||
stmt.execute(arguments: [harmless]) // GOOD
|
||||
|
||||
stmt.setArguments([password]) // BAD
|
||||
stmt.setArguments([password]) // $ Alert
|
||||
stmt.setArguments([harmless]) // GOOD
|
||||
}
|
||||
|
||||
func testCommonTableExpression(password: String, harmless: String) {
|
||||
let _ = CommonTableExpression(named: "", sql: "", arguments: [password]) // BAD
|
||||
let _ = CommonTableExpression(named: "", sql: "", arguments: [password]) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = CommonTableExpression(named: "", columns: nil, sql: "", arguments: [password]) // BAD
|
||||
let _ = CommonTableExpression(named: "", columns: nil, sql: "", arguments: [password]) // $ Alert
|
||||
let _ = CommonTableExpression(named: "", columns: nil, sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: "", arguments: [password]) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: "", arguments: [password]) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", sql: "", arguments: [harmless]) // GOOD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: nil, sql: "", arguments: [password]) // BAD
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: nil, sql: "", arguments: [password]) // $ Alert
|
||||
let _ = CommonTableExpression(recursive: false, named: "", columns: nil, sql: "", arguments: [harmless]) // GOOD
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func test1(realm : Realm, myHarmless: String, myPassword : String, myHashedPassw
|
||||
// add objects (within a transaction) ...
|
||||
|
||||
let a = MyRealmSwiftObject()
|
||||
a.data = myPassword // BAD
|
||||
a.data = myPassword // $ Alert
|
||||
realm.add(a)
|
||||
|
||||
let b = MyRealmSwiftObject()
|
||||
@@ -46,7 +46,7 @@ func test1(realm : Realm, myHarmless: String, myPassword : String, myHashedPassw
|
||||
realm.add(b) // GOOD (not sensitive)
|
||||
|
||||
let c = MyRealmSwiftObject()
|
||||
c.data = myPassword // BAD
|
||||
c.data = myPassword // $ Alert
|
||||
realm.create(MyRealmSwiftObject.self, value: c)
|
||||
|
||||
let d = MyRealmSwiftObject()
|
||||
@@ -56,21 +56,21 @@ func test1(realm : Realm, myHarmless: String, myPassword : String, myHashedPassw
|
||||
// retrieve objects ...
|
||||
|
||||
var e = realm.object(ofType: MyRealmSwiftObject.self, forPrimaryKey: "key")
|
||||
e!.data = myPassword // BAD
|
||||
e!.data = myPassword // $ Alert
|
||||
|
||||
var f = realm.object(ofType: MyRealmSwiftObject.self, forPrimaryKey: "key")
|
||||
f!.data = myHashedPassword // GOOD (not sensitive)
|
||||
|
||||
let g = MyRealmSwiftObject()
|
||||
g.data = "" // GOOD (not sensitive)
|
||||
g.data = myPassword // BAD
|
||||
g.data = myPassword // $ Alert
|
||||
g.data = "" // GOOD (not sensitive)
|
||||
|
||||
// MyRealmSwiftObject2...
|
||||
|
||||
let h = MyRealmSwiftObject2()
|
||||
h.harmless = myHarmless // GOOD (not sensitive)
|
||||
h.password = myPassword // BAD
|
||||
h.password = myPassword // $ Alert
|
||||
realm.add(h)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,23 +15,23 @@ class MyRealmSwiftObject3 : Object {
|
||||
|
||||
func test1(o: MyRealmSwiftObject3, myHarmless: String, myPassword: String) {
|
||||
// ...
|
||||
o.data = myPassword // BAD
|
||||
o.data = myPassword // $ Alert
|
||||
o.data = myHarmless
|
||||
// ...
|
||||
}
|
||||
|
||||
func test2(o: MyRealmSwiftObject3, ccn: String, socialSecurityNumber: String, ssn: String, ssn_int: Int, userSSN: String, classno: String) {
|
||||
o.data = socialSecurityNumber // BAD
|
||||
o.data = ssn // BAD
|
||||
o.data = String(ssn_int) // BAD
|
||||
o.data = socialSecurityNumber // $ Alert
|
||||
o.data = ssn // $ Alert
|
||||
o.data = String(ssn_int) // $ Alert
|
||||
o.data = userSSN // BAD [NOT DETECTED]
|
||||
o.data = classno // GOOD
|
||||
}
|
||||
|
||||
func test3(o: MyRealmSwiftObject3, ccn: String, creditCardNumber: String, CCN: String, int_ccn: Int, userCcn: String, succnode: String) {
|
||||
o.data = creditCardNumber // BAD
|
||||
o.data = CCN // BAD
|
||||
o.data = String(int_ccn) // BAD
|
||||
o.data = creditCardNumber // $ Alert
|
||||
o.data = CCN // $ Alert
|
||||
o.data = String(int_ccn) // $ Alert
|
||||
o.data = userCcn // BAD [NOT DETECTED]
|
||||
o.data = succnode // GOOD
|
||||
}
|
||||
|
||||
@@ -26,15 +26,15 @@ func test1(passwordPlain : String, passwordHash : String) {
|
||||
// ...
|
||||
|
||||
nw.send(content: "123456", completion: .idempotent) // GOOD (not sensitive)
|
||||
nw.send(content: passwordPlain, completion: .idempotent) // BAD
|
||||
nw.send(content: passwordPlain, completion: .idempotent) // $ Alert
|
||||
nw.send(content: passwordHash, completion: .idempotent) // GOOD (not sensitive)
|
||||
|
||||
let data1 = Data("123456")
|
||||
let data2 = Data(passwordPlain)
|
||||
let data2 = Data(passwordPlain) // $ Source
|
||||
let data3 = Data(passwordHash)
|
||||
|
||||
nw.send(content: data1, completion: .idempotent) // GOOD (not sensitive)
|
||||
nw.send(content: data2, completion: .idempotent) // BAD
|
||||
nw.send(content: data2, completion: .idempotent) // $ Alert
|
||||
nw.send(content: data3, completion: .idempotent) // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
@@ -55,30 +55,30 @@ struct MyStruct {
|
||||
}
|
||||
|
||||
func test2(password : String, license_key: String, ms: MyStruct, connection : NWConnection) {
|
||||
let str1 = password
|
||||
let str2 = password + " "
|
||||
let str3 = pad(password)
|
||||
let str1 = password // $ Source
|
||||
let str2 = password + " " // $ Source
|
||||
let str3 = pad(password) // $ Source
|
||||
let str4 = aes_crypt(password)
|
||||
let str5 = pad(aes_crypt(password))
|
||||
let str6 = aes_crypt(pad(password))
|
||||
|
||||
connection.send(content: str1, completion: .idempotent) // BAD
|
||||
connection.send(content: str2, completion: .idempotent) // BAD
|
||||
connection.send(content: str3, completion: .idempotent) // BAD
|
||||
connection.send(content: str1, completion: .idempotent) // $ Alert
|
||||
connection.send(content: str2, completion: .idempotent) // $ Alert
|
||||
connection.send(content: str3, completion: .idempotent) // $ Alert
|
||||
connection.send(content: str4, completion: .idempotent) // GOOD (encrypted)
|
||||
connection.send(content: str5, completion: .idempotent) // GOOD (encrypted)
|
||||
connection.send(content: str6, completion: .idempotent) // GOOD (encrypted)
|
||||
connection.send(content: license_key, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD
|
||||
connection.send(content: license_key, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.mobileNumber, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive)
|
||||
connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive)
|
||||
connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive)
|
||||
connection.send(content: ms.Telephone, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.birth_day, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.CarePlanID, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.BankCardNo, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.MyCreditRating, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.OneTimeCode, completion: .idempotent) // BAD
|
||||
connection.send(content: ms.Telephone, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.birth_day, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.CarePlanID, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.BankCardNo, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.MyCreditRating, completion: .idempotent) // $ Alert
|
||||
connection.send(content: ms.OneTimeCode, completion: .idempotent) // $ Alert
|
||||
}
|
||||
|
||||
struct MyOuter {
|
||||
@@ -91,6 +91,6 @@ struct MyOuter {
|
||||
}
|
||||
|
||||
func test3(mo : MyOuter, connection : NWConnection) {
|
||||
connection.send(content: mo.password.value, completion: .idempotent) // BAD
|
||||
connection.send(content: mo.password.value, completion: .idempotent) // $ Alert
|
||||
connection.send(content: mo.harmless.value, completion: .idempotent) // GOOD
|
||||
}
|
||||
|
||||
@@ -36,22 +36,22 @@ func setMyString(str: String) { myString = str }
|
||||
func getMyString() -> String { return myString }
|
||||
|
||||
func test1(passwd : String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
_ = URL(string: "http://example.com/login?p=" + passwd); // BAD
|
||||
_ = URL(string: "http://example.com/login?p=" + passwd); // $ Alert
|
||||
_ = URL(string: "http://example.com/login?p=" + encrypted_passwd); // GOOD (not sensitive)
|
||||
_ = URL(string: "http://example.com/login?ac=" + account_no); // BAD
|
||||
_ = URL(string: "http://example.com/login?cc=" + credit_card_no); // BAD
|
||||
_ = URL(string: "http://example.com/login?ac=" + account_no); // $ Alert
|
||||
_ = URL(string: "http://example.com/login?cc=" + credit_card_no); // $ Alert
|
||||
|
||||
let base = URL(string: "http://example.com/"); // GOOD (not sensitive)
|
||||
_ = URL(string: "abc", relativeTo: base); // GOOD (not sensitive)
|
||||
let f = URL(string: passwd, relativeTo: base); // BAD
|
||||
let f = URL(string: passwd, relativeTo: base); // $ Alert
|
||||
_ = URL(string: "abc", relativeTo: f); // BAD (reported on line above)
|
||||
|
||||
let e_mail = myString
|
||||
_ = URL(string: "http://example.com/login?em=" + e_mail); // BAD
|
||||
_ = URL(string: "http://example.com/login?em=" + e_mail); // $ Alert
|
||||
let a_homeaddr_z = getMyString()
|
||||
_ = URL(string: "http://example.com/login?home=" + a_homeaddr_z); // BAD
|
||||
_ = URL(string: "http://example.com/login?home=" + a_homeaddr_z); // $ Alert
|
||||
let resident_ID = getMyString()
|
||||
_ = URL(string: "http://example.com/login?id=" + resident_ID); // BAD
|
||||
_ = URL(string: "http://example.com/login?id=" + resident_ID); // $ Alert
|
||||
}
|
||||
|
||||
func get_private_key() -> String { return "" }
|
||||
@@ -70,9 +70,9 @@ func test2() {
|
||||
_ = URL(string: "http://example.com/login?key=" + get_aes_key()); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?key=" + get_aws_key()); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?key=" + get_access_key()); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?key=" + get_secret_key()); // BAD
|
||||
_ = URL(string: "http://example.com/login?key=" + get_secret_key()); // $ Alert
|
||||
_ = URL(string: "http://example.com/login?key=" + get_key_press()); // GOOD (not sensitive)
|
||||
_ = URL(string: "http://example.com/login?cert=" + get_cert_string()); // BAD
|
||||
_ = URL(string: "http://example.com/login?cert=" + get_cert_string()); // $ Alert
|
||||
_ = URL(string: "http://example.com/login?certain=" + get_certain()); // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func test3() {
|
||||
_ = URL(string: "http://example.com/login?key=\(priv_key)"); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?key=\(private_key)"); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?key=\(pub_key)"); // GOOD (not sensitive)
|
||||
_ = URL(string: "http://example.com/login?cert=\(certificate)"); // BAD
|
||||
_ = URL(string: "http://example.com/login?cert=\(certificate)"); // $ Alert
|
||||
_ = URL(string: "http://example.com/login?tok=\(secure_token)"); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?tok=\(access_token)"); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "http://example.com/login?tok=\(auth_token)"); // BAD [NOT DETECTED]
|
||||
@@ -101,9 +101,9 @@ func test3() {
|
||||
}
|
||||
|
||||
func test4(key: SecKey) {
|
||||
if let data = SecKeyCopyExternalRepresentation(key, nil) as? Data {
|
||||
if let data = SecKeyCopyExternalRepresentation(key, nil) as? Data { // $ Source
|
||||
if let string = String(data: data, encoding: .utf8) {
|
||||
_ = URL(string: "http://example.com/login?tok=\(string)"); // BAD
|
||||
_ = URL(string: "http://example.com/login?tok=\(string)"); // $ Alert
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,14 +113,14 @@ func test5() {
|
||||
let email = get_string()
|
||||
let secret_key = get_string()
|
||||
|
||||
_ = URL(string: "http://example.com/login?email=\(email)"); // BAD
|
||||
_ = URL(string: "http://example.com/login?email=\(email)"); // $ Alert
|
||||
_ = URL(string: "mailto:\(email)"); // GOOD (revealing your e-amil address in an e-mail is expected)
|
||||
_ = URL(string: "mailto:info@example.com?subject=\(secret_key)"); // BAD [NOT DETECTED]
|
||||
_ = URL(string: "mailto:info@example.com?subject=foo&cc=\(email)"); // GOOD
|
||||
|
||||
let phone_number = get_string()
|
||||
|
||||
_ = URL(string: "http://example.com/profile?tel=\(phone_number)"); // BAD
|
||||
_ = URL(string: "http://example.com/profile?tel=\(phone_number)"); // $ Alert
|
||||
_ = URL(string: "tel:\(phone_number)") // GOOD
|
||||
_ = URL(string: "telprompt:\(phone_number)") // GOOD
|
||||
_ = URL(string: "callto:\(phone_number)") // GOOD
|
||||
@@ -129,5 +129,5 @@ func test5() {
|
||||
let account_no = get_string()
|
||||
|
||||
_ = URL(string: "file:///foo/bar/\(account_no).csv") // GOOD (local, so not transmitted)
|
||||
_ = URL(string: "ftp://example.com/\(account_no).csv") // BAD
|
||||
_ = URL(string: "ftp://example.com/\(account_no).csv") // $ Alert
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-312/CleartextStoragePreferences.ql
|
||||
query: queries/Security/CWE-312/CleartextStoragePreferences.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -25,7 +25,7 @@ func doSomething(password: String) { }
|
||||
func test1(password: String, passwordHash : String) {
|
||||
let store = NSUbiquitousKeyValueStore.default
|
||||
|
||||
store.set(password, forKey: "myKey") // BAD
|
||||
store.set(password, forKey: "myKey") // $ Alert
|
||||
store.set(passwordHash, forKey: "myKey") // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
@@ -38,27 +38,27 @@ func test3(x: String) {
|
||||
// alternative evidence of sensitivity...
|
||||
|
||||
NSUbiquitousKeyValueStore.default.set(x, forKey: "myKey") // BAD [NOT REPORTED]
|
||||
doSomething(password: x);
|
||||
NSUbiquitousKeyValueStore.default.set(x, forKey: "myKey") // BAD
|
||||
doSomething(password: x); // $ Source
|
||||
NSUbiquitousKeyValueStore.default.set(x, forKey: "myKey") // $ Alert
|
||||
|
||||
let y = getPassword();
|
||||
NSUbiquitousKeyValueStore.default.set(y, forKey: "myKey") // BAD
|
||||
let y = getPassword(); // $ Source
|
||||
NSUbiquitousKeyValueStore.default.set(y, forKey: "myKey") // $ Alert
|
||||
|
||||
let z = MyClass()
|
||||
NSUbiquitousKeyValueStore.default.set(z.harmless, forKey: "myKey") // GOOD (not sensitive)
|
||||
NSUbiquitousKeyValueStore.default.set(z.password, forKey: "myKey") // BAD
|
||||
NSUbiquitousKeyValueStore.default.set(z.password, forKey: "myKey") // $ Alert
|
||||
}
|
||||
|
||||
func test4(passwd: String) {
|
||||
// sanitizers...
|
||||
|
||||
var x = passwd;
|
||||
var y = passwd;
|
||||
var z = passwd;
|
||||
var x = passwd; // $ Source
|
||||
var y = passwd; // $ Source
|
||||
var z = passwd; // $ Source
|
||||
|
||||
NSUbiquitousKeyValueStore.default.set(x, forKey: "myKey") // BAD
|
||||
NSUbiquitousKeyValueStore.default.set(y, forKey: "myKey") // BAD
|
||||
NSUbiquitousKeyValueStore.default.set(z, forKey: "myKey") // BAD
|
||||
NSUbiquitousKeyValueStore.default.set(x, forKey: "myKey") // $ Alert
|
||||
NSUbiquitousKeyValueStore.default.set(y, forKey: "myKey") // $ Alert
|
||||
NSUbiquitousKeyValueStore.default.set(z, forKey: "myKey") // $ Alert
|
||||
|
||||
x = encrypt(x);
|
||||
hash(data: &y);
|
||||
|
||||
@@ -25,7 +25,7 @@ func doSomething(password: String) { }
|
||||
func test1(password: String, passwordHash : String) {
|
||||
let defaults = UserDefaults.standard
|
||||
|
||||
defaults.set(password, forKey: "myKey") // BAD
|
||||
defaults.set(password, forKey: "myKey") // $ Alert
|
||||
defaults.set(passwordHash, forKey: "myKey") // GOOD (not sensitive)
|
||||
}
|
||||
|
||||
@@ -38,27 +38,27 @@ func test3(x: String) {
|
||||
// alternative evidence of sensitivity...
|
||||
|
||||
UserDefaults.standard.set(x, forKey: "myKey") // BAD [NOT REPORTED]
|
||||
doSomething(password: x);
|
||||
UserDefaults.standard.set(x, forKey: "myKey") // BAD
|
||||
doSomething(password: x); // $ Source
|
||||
UserDefaults.standard.set(x, forKey: "myKey") // $ Alert
|
||||
|
||||
let y = getPassword();
|
||||
UserDefaults.standard.set(y, forKey: "myKey") // BAD
|
||||
let y = getPassword(); // $ Source
|
||||
UserDefaults.standard.set(y, forKey: "myKey") // $ Alert
|
||||
|
||||
let z = MyClass()
|
||||
UserDefaults.standard.set(z.harmless, forKey: "myKey") // GOOD (not sensitive)
|
||||
UserDefaults.standard.set(z.password, forKey: "myKey") // BAD
|
||||
UserDefaults.standard.set(z.password, forKey: "myKey") // $ Alert
|
||||
}
|
||||
|
||||
func test4(passwd: String) {
|
||||
// sanitizers...
|
||||
|
||||
var x = passwd;
|
||||
var y = passwd;
|
||||
var z = passwd;
|
||||
var x = passwd; // $ Source
|
||||
var y = passwd; // $ Source
|
||||
var z = passwd; // $ Source
|
||||
|
||||
UserDefaults.standard.set(x, forKey: "myKey") // BAD
|
||||
UserDefaults.standard.set(y, forKey: "myKey") // BAD
|
||||
UserDefaults.standard.set(z, forKey: "myKey") // BAD
|
||||
UserDefaults.standard.set(x, forKey: "myKey") // $ Alert
|
||||
UserDefaults.standard.set(y, forKey: "myKey") // $ Alert
|
||||
UserDefaults.standard.set(z, forKey: "myKey") // $ Alert
|
||||
|
||||
x = encrypt(x);
|
||||
hash(data: &y);
|
||||
@@ -79,6 +79,6 @@ struct MyOuter {
|
||||
}
|
||||
|
||||
func test5(mo : MyOuter) {
|
||||
UserDefaults.standard.set(mo.password.value, forKey: "myKey") // BAD
|
||||
UserDefaults.standard.set(mo.password.value, forKey: "myKey") // $ Alert
|
||||
UserDefaults.standard.set(mo.harmless.value, forKey: "myKey") // GOOD
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-327/ECBEncryption.ql
|
||||
query: queries/Security/CWE-327/ECBEncryption.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -36,7 +36,7 @@ func getRandomArray() -> Array<UInt8> {
|
||||
}
|
||||
|
||||
func getECBBlockMode() -> BlockMode {
|
||||
return ECB()
|
||||
return ECB() // $ Source
|
||||
}
|
||||
|
||||
func getCBCBlockMode() -> BlockMode {
|
||||
@@ -47,18 +47,18 @@ func getCBCBlockMode() -> BlockMode {
|
||||
|
||||
func test1() {
|
||||
let key: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f]
|
||||
let ecb = ECB()
|
||||
let ecb = ECB() // $ Source
|
||||
let iv = getRandomArray()
|
||||
let cbc = CBC(iv: iv)
|
||||
let padding = Padding.noPadding
|
||||
|
||||
// AES test cases
|
||||
let ab1 = AES(key: key, blockMode: ecb, padding: padding) // BAD
|
||||
let ab2 = AES(key: key, blockMode: ecb) // BAD
|
||||
let ab3 = AES(key: key, blockMode: ECB(), padding: padding) // BAD
|
||||
let ab4 = AES(key: key, blockMode: ECB()) // BAD
|
||||
let ab5 = AES(key: key, blockMode: getECBBlockMode(), padding: padding) // BAD
|
||||
let ab6 = AES(key: key, blockMode: getECBBlockMode()) // BAD
|
||||
let ab1 = AES(key: key, blockMode: ecb, padding: padding) // $ Alert
|
||||
let ab2 = AES(key: key, blockMode: ecb) // $ Alert
|
||||
let ab3 = AES(key: key, blockMode: ECB(), padding: padding) // $ Alert
|
||||
let ab4 = AES(key: key, blockMode: ECB()) // $ Alert
|
||||
let ab5 = AES(key: key, blockMode: getECBBlockMode(), padding: padding) // $ Alert
|
||||
let ab6 = AES(key: key, blockMode: getECBBlockMode()) // $ Alert
|
||||
|
||||
let ag1 = AES(key: key, blockMode: cbc, padding: padding) // GOOD
|
||||
let ag2 = AES(key: key, blockMode: cbc) // GOOD
|
||||
@@ -68,9 +68,9 @@ func test1() {
|
||||
let ag6 = AES(key: key, blockMode: getCBCBlockMode()) // GOOD
|
||||
|
||||
// Blowfish test cases
|
||||
let bb1 = Blowfish(key: key, blockMode: ecb, padding: padding) // BAD
|
||||
let bb2 = Blowfish(key: key, blockMode: ECB(), padding: padding) // BAD
|
||||
let bb3 = Blowfish(key: key, blockMode: getECBBlockMode(), padding: padding) // BAD
|
||||
let bb1 = Blowfish(key: key, blockMode: ecb, padding: padding) // $ Alert
|
||||
let bb2 = Blowfish(key: key, blockMode: ECB(), padding: padding) // $ Alert
|
||||
let bb3 = Blowfish(key: key, blockMode: getECBBlockMode(), padding: padding) // $ Alert
|
||||
|
||||
let bg1 = Blowfish(key: key, blockMode: cbc, padding: padding) // GOOD
|
||||
let bg2 = Blowfish(key: key, blockMode: CBC(iv: iv), padding: padding) // GOOD
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-328/WeakPasswordHashing.ql
|
||||
query: queries/Security/CWE-328/WeakPasswordHashing.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-328/WeakSensitiveDataHashing.ql
|
||||
query: queries/Security/CWE-328/WeakSensitiveDataHashing.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -81,43 +81,43 @@ enum Insecure {
|
||||
// --- tests ---
|
||||
|
||||
func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.Insecure.MD5.hash(data: passwd) // BAD
|
||||
hash = Crypto.Insecure.MD5.hash(bufferPointer: passwd) // BAD
|
||||
hash = Crypto.Insecure.MD5.hash(data: cert) // BAD
|
||||
var hash = Crypto.Insecure.MD5.hash(data: passwd) // $ Alert
|
||||
hash = Crypto.Insecure.MD5.hash(bufferPointer: passwd) // $ Alert
|
||||
hash = Crypto.Insecure.MD5.hash(data: cert) // $ Alert
|
||||
hash = Crypto.Insecure.MD5.hash(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash = Crypto.Insecure.MD5.hash(data: account_no) // BAD
|
||||
hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // BAD
|
||||
hash = Crypto.Insecure.MD5.hash(data: account_no) // $ Alert
|
||||
hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // $ Alert
|
||||
|
||||
hash = Insecure.MD5.hash(data: passwd) // BAD
|
||||
hash = Insecure.MD5.hash(bufferPointer: passwd) // BAD
|
||||
hash = Insecure.MD5.hash(data: cert) // BAD
|
||||
hash = Insecure.MD5.hash(data: passwd) // $ Alert
|
||||
hash = Insecure.MD5.hash(bufferPointer: passwd) // $ Alert
|
||||
hash = Insecure.MD5.hash(data: cert) // $ Alert
|
||||
hash = Insecure.MD5.hash(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash = Insecure.MD5.hash(data: account_no) // BAD
|
||||
hash = Insecure.MD5.hash(data: credit_card_no) // BAD
|
||||
hash = Insecure.MD5.hash(data: account_no) // $ Alert
|
||||
hash = Insecure.MD5.hash(data: credit_card_no) // $ Alert
|
||||
|
||||
hash = Crypto.Insecure.SHA1.hash(data: passwd) // BAD
|
||||
hash = Crypto.Insecure.SHA1.hash(bufferPointer: passwd) // BAD
|
||||
hash = Crypto.Insecure.SHA1.hash(data: cert) // BAD
|
||||
hash = Crypto.Insecure.SHA1.hash(data: passwd) // $ Alert
|
||||
hash = Crypto.Insecure.SHA1.hash(bufferPointer: passwd) // $ Alert
|
||||
hash = Crypto.Insecure.SHA1.hash(data: cert) // $ Alert
|
||||
hash = Crypto.Insecure.SHA1.hash(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash = Crypto.Insecure.SHA1.hash(data: account_no) // BAD
|
||||
hash = Crypto.Insecure.SHA1.hash(data: credit_card_no) // BAD
|
||||
hash = Crypto.Insecure.SHA1.hash(data: account_no) // $ Alert
|
||||
hash = Crypto.Insecure.SHA1.hash(data: credit_card_no) // $ Alert
|
||||
|
||||
hash = Crypto.SHA256.hash(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA256.hash(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA256.hash(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA256.hash(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA256.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||
hash = Crypto.SHA256.hash(data: encrypted_passwd) // GOOD, not sensitive
|
||||
hash = Crypto.SHA256.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||
hash = Crypto.SHA256.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||
|
||||
hash = Crypto.SHA384.hash(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA384.hash(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA384.hash(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA384.hash(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA384.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||
hash = Crypto.SHA384.hash(data: encrypted_passwd) // GOOD, not sensitive
|
||||
hash = Crypto.SHA384.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||
hash = Crypto.SHA384.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
|
||||
|
||||
hash = Crypto.SHA512.hash(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA512.hash(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA512.hash(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA512.hash(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash = Crypto.SHA512.hash(data: cert) // GOOD, computationally expensive hash not required
|
||||
hash = Crypto.SHA512.hash(data: encrypted_passwd) // GOOD, not sensitive
|
||||
hash = Crypto.SHA512.hash(data: account_no) // GOOD, computationally expensive hash not required
|
||||
@@ -126,25 +126,25 @@ func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_pa
|
||||
|
||||
func testMD5UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.Insecure.MD5()
|
||||
hash.update(data: passwd) // BAD
|
||||
hash.update(data: cert) // BAD
|
||||
hash.update(data: passwd) // $ Alert
|
||||
hash.update(data: cert) // $ Alert
|
||||
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(data: account_no) // BAD
|
||||
hash.update(data: credit_card_no) // BAD
|
||||
hash.update(data: account_no) // $ Alert
|
||||
hash.update(data: credit_card_no) // $ Alert
|
||||
}
|
||||
|
||||
func testSHA1UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.Insecure.SHA1()
|
||||
hash.update(data: passwd) // BAD
|
||||
hash.update(data: cert) // BAD
|
||||
hash.update(data: passwd) // $ Alert
|
||||
hash.update(data: cert) // $ Alert
|
||||
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(data: account_no) // BAD
|
||||
hash.update(data: credit_card_no) // BAD
|
||||
hash.update(data: account_no) // $ Alert
|
||||
hash.update(data: credit_card_no) // $ Alert
|
||||
}
|
||||
|
||||
func testSHA256UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.SHA256()
|
||||
hash.update(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(data: cert) // GOOD
|
||||
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(data: account_no) // GOOD
|
||||
@@ -153,7 +153,7 @@ func testSHA256UpdateWithData(passwd : String, cert: String, encrypted_passwd :
|
||||
|
||||
func testSHA384UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.SHA384()
|
||||
hash.update(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(data: cert) // GOOD
|
||||
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(data: account_no) // GOOD
|
||||
@@ -162,7 +162,7 @@ func testSHA384UpdateWithData(passwd : String, cert: String, encrypted_passwd :
|
||||
|
||||
func testSHA512UpdateWithData(passwd : String, cert: String, encrypted_passwd : String, account_no : String, credit_card_no : String) {
|
||||
var hash = Crypto.SHA512()
|
||||
hash.update(data: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(data: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(data: cert) // GOOD
|
||||
hash.update(data: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(data: account_no) // GOOD
|
||||
@@ -171,25 +171,25 @@ func testSHA512UpdateWithData(passwd : String, cert: String, encrypted_passwd :
|
||||
|
||||
func testMD5UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||
var hash = Crypto.Insecure.MD5()
|
||||
hash.update(bufferPointer: passwd) // BAD
|
||||
hash.update(bufferPointer: cert) // BAD
|
||||
hash.update(bufferPointer: passwd) // $ Alert
|
||||
hash.update(bufferPointer: cert) // $ Alert
|
||||
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(bufferPointer: account_no) // BAD
|
||||
hash.update(bufferPointer: credit_card_no) // BAD
|
||||
hash.update(bufferPointer: account_no) // $ Alert
|
||||
hash.update(bufferPointer: credit_card_no) // $ Alert
|
||||
}
|
||||
|
||||
func testSHA1UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||
var hash = Crypto.Insecure.SHA1()
|
||||
hash.update(bufferPointer: passwd) // BAD
|
||||
hash.update(bufferPointer: cert) // BAD
|
||||
hash.update(bufferPointer: passwd) // $ Alert
|
||||
hash.update(bufferPointer: cert) // $ Alert
|
||||
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(bufferPointer: account_no) // BAD
|
||||
hash.update(bufferPointer: credit_card_no) // BAD
|
||||
hash.update(bufferPointer: account_no) // $ Alert
|
||||
hash.update(bufferPointer: credit_card_no) // $ Alert
|
||||
}
|
||||
|
||||
func testSHA256UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||
var hash = Crypto.SHA256()
|
||||
hash.update(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: cert) // GOOD
|
||||
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(bufferPointer: account_no) // GOOD
|
||||
@@ -198,7 +198,7 @@ func testSHA256UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer,
|
||||
|
||||
func testSHA384UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||
var hash = Crypto.SHA384()
|
||||
hash.update(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: cert) // GOOD
|
||||
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(bufferPointer: account_no) // GOOD
|
||||
@@ -207,7 +207,7 @@ func testSHA384UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer,
|
||||
|
||||
func testSHA512UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer, cert: UnsafeRawBufferPointer, encrypted_passwd : UnsafeRawBufferPointer, account_no : UnsafeRawBufferPointer, credit_card_no : UnsafeRawBufferPointer) {
|
||||
var hash = Crypto.SHA512()
|
||||
hash.update(bufferPointer: passwd) // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: passwd) // $ Alert // BAD, not a computationally expensive hash
|
||||
hash.update(bufferPointer: cert) // GOOD
|
||||
hash.update(bufferPointer: encrypted_passwd) // GOOD (not sensitive)
|
||||
hash.update(bufferPointer: account_no) // GOOD
|
||||
@@ -217,30 +217,30 @@ func testSHA512UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer,
|
||||
func testBadExample(passwordString: String) {
|
||||
// this is the "bad" example from the .qhelp
|
||||
let passwordData = Data(passwordString.utf8)
|
||||
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD, not a computationally expensive hash
|
||||
let passwordHash = Crypto.SHA512.hash(data: passwordData) // $ Alert // BAD, not a computationally expensive hash
|
||||
|
||||
// ...
|
||||
|
||||
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // BAD, not a computationally expensive hash
|
||||
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // $ Alert // BAD, not a computationally expensive hash
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
func testWithFlowAndMetatypes(cardNumber: String) {
|
||||
let value1 = Data(cardNumber.utf8);
|
||||
let _digest1 = Insecure.MD5.hash(data: value1); // BAD
|
||||
let value1 = Data(cardNumber.utf8); // $ Source
|
||||
let _digest1 = Insecure.MD5.hash(data: value1); // $ Alert
|
||||
|
||||
let value2 = Data(cardNumber.utf8);
|
||||
let value2 = Data(cardNumber.utf8); // $ Source
|
||||
let hasher2 = Insecure.MD5.self; // metatype
|
||||
let _digest2 = hasher2.hash(data: value2); // BAD
|
||||
let _digest2 = hasher2.hash(data: value2); // $ Alert
|
||||
|
||||
let value3 = Data(cardNumber.utf8);
|
||||
let _digest3 = (Insecure.MD5.self).hash(data: value3); // BAD
|
||||
let value3 = Data(cardNumber.utf8); // $ Source
|
||||
let _digest3 = (Insecure.MD5.self).hash(data: value3); // $ Alert
|
||||
|
||||
let value4 = Data(cardNumber.utf8);
|
||||
let value4 = Data(cardNumber.utf8); // $ Source
|
||||
testReceiver1(value: value4);
|
||||
|
||||
let value5 = Data(cardNumber.utf8);
|
||||
let value5 = Data(cardNumber.utf8); // $ Source
|
||||
testReceiver2(hasher: Insecure.MD5.self, value: value5);
|
||||
|
||||
let value6 = Data(cardNumber.utf8);
|
||||
@@ -248,11 +248,11 @@ func testWithFlowAndMetatypes(cardNumber: String) {
|
||||
}
|
||||
|
||||
func testReceiver1(value: Data) {
|
||||
let _digest = Insecure.MD5.hash(data: value); // BAD
|
||||
let _digest = Insecure.MD5.hash(data: value); // $ Alert
|
||||
}
|
||||
|
||||
func testReceiver2(hasher: Insecure.MD5.Type, value: Data) {
|
||||
let _digest = hasher.hash(data: value); // BAD
|
||||
let _digest = hasher.hash(data: value); // $ Alert
|
||||
}
|
||||
|
||||
func testReceiver3<H: HashFunction>(hasher: H.Type, value: Data) {
|
||||
|
||||
@@ -150,83 +150,83 @@ extension String {
|
||||
|
||||
func testArrays(harmlessArray: Array<UInt8>, phoneNumberArray: Array<UInt8>, passwdArray: Array<UInt8>) {
|
||||
_ = MD5().calculate(for: harmlessArray) // GOOD (not sensitive)
|
||||
_ = MD5().calculate(for: phoneNumberArray) // BAD
|
||||
_ = MD5().calculate(for: passwdArray) // BAD
|
||||
_ = MD5().calculate(for: phoneNumberArray) // $ Alert
|
||||
_ = MD5().calculate(for: passwdArray) // $ Alert
|
||||
_ = SHA1().calculate(for: harmlessArray) // GOOD (not sensitive)
|
||||
_ = SHA1().calculate(for: phoneNumberArray) // BAD
|
||||
_ = SHA1().calculate(for: passwdArray) // BAD
|
||||
_ = SHA1().calculate(for: phoneNumberArray) // $ Alert
|
||||
_ = SHA1().calculate(for: passwdArray) // $ Alert
|
||||
_ = SHA2(variant: .sha512).calculate(for: harmlessArray) // GOOD
|
||||
_ = SHA2(variant: .sha512).calculate(for: phoneNumberArray) // GOOD
|
||||
_ = SHA2(variant: .sha512).calculate(for: passwdArray) // BAD
|
||||
_ = SHA2(variant: .sha512).calculate(for: passwdArray) // $ Alert
|
||||
_ = SHA3(variant: .sha512).calculate(for: harmlessArray) // GOOD
|
||||
_ = SHA3(variant: .sha512).calculate(for: phoneNumberArray) // GOOD
|
||||
_ = SHA3(variant: .sha512).calculate(for: passwdArray) // BAD
|
||||
_ = SHA3(variant: .sha512).calculate(for: passwdArray) // $ Alert
|
||||
|
||||
_ = Digest.md5(harmlessArray) // GOOD (not sensitive)
|
||||
_ = Digest.md5(phoneNumberArray) // BAD
|
||||
_ = Digest.md5(passwdArray) // BAD
|
||||
_ = Digest.md5(phoneNumberArray) // $ Alert
|
||||
_ = Digest.md5(passwdArray) // $ Alert
|
||||
_ = Digest.sha1(harmlessArray) // GOOD (not sensitive)
|
||||
_ = Digest.sha1(phoneNumberArray) // BAD
|
||||
_ = Digest.sha1(passwdArray) // BAD
|
||||
_ = Digest.sha1(phoneNumberArray) // $ Alert
|
||||
_ = Digest.sha1(passwdArray) // $ Alert
|
||||
_ = Digest.sha512(harmlessArray) // GOOD (not sensitive)
|
||||
_ = Digest.sha512(phoneNumberArray) // GOOD
|
||||
_ = Digest.sha512(passwdArray) // BAD
|
||||
_ = Digest.sha512(passwdArray) // $ Alert
|
||||
_ = Digest.sha2(harmlessArray, variant: .sha512) // GOOD (not sensitive)
|
||||
_ = Digest.sha2(phoneNumberArray, variant: .sha512) // GOOD
|
||||
_ = Digest.sha2(passwdArray, variant: .sha512) // BAD
|
||||
_ = Digest.sha2(passwdArray, variant: .sha512) // $ Alert
|
||||
_ = Digest.sha3(harmlessArray, variant: .sha512) // GOOD (not sensitive)
|
||||
_ = Digest.sha3(phoneNumberArray, variant: .sha512) // GOOD
|
||||
_ = Digest.sha3(passwdArray, variant: .sha512) // BAD
|
||||
_ = Digest.sha3(passwdArray, variant: .sha512) // $ Alert
|
||||
|
||||
_ = harmlessArray.md5() // GOOD (not sensitive)
|
||||
_ = phoneNumberArray.md5() // BAD
|
||||
_ = passwdArray.md5() // BAD
|
||||
_ = phoneNumberArray.md5() // $ Alert
|
||||
_ = passwdArray.md5() // $ Alert
|
||||
_ = harmlessArray.sha1() // GOOD (not sensitive)
|
||||
_ = phoneNumberArray.sha1() // BAD
|
||||
_ = passwdArray.sha1() // BAD
|
||||
_ = phoneNumberArray.sha1() // $ Alert
|
||||
_ = passwdArray.sha1() // $ Alert
|
||||
_ = harmlessArray.sha512() // GOOD
|
||||
_ = phoneNumberArray.sha512() // GOOD
|
||||
_ = passwdArray.sha512() // BAD
|
||||
_ = passwdArray.sha512() // $ Alert
|
||||
_ = harmlessArray.sha2(.sha512) // GOOD
|
||||
_ = phoneNumberArray.sha2(.sha512) // GOOD
|
||||
_ = passwdArray.sha2(.sha512) // BAD
|
||||
_ = passwdArray.sha2(.sha512) // $ Alert
|
||||
_ = harmlessArray.sha3(.sha512) // GOOD
|
||||
_ = phoneNumberArray.sha3(.sha512) // GOOD
|
||||
_ = passwdArray.sha3(.sha512) // BAD
|
||||
_ = passwdArray.sha3(.sha512) // $ Alert
|
||||
}
|
||||
|
||||
func testData(harmlessData: Data, medicalData: Data, passwdData: Data) {
|
||||
_ = harmlessData.md5() // GOOD (not sensitive)
|
||||
_ = medicalData.md5() // BAD
|
||||
_ = passwdData.md5() // BAD
|
||||
_ = medicalData.md5() // $ Alert
|
||||
_ = passwdData.md5() // $ Alert
|
||||
_ = harmlessData.sha1() // GOOD (not sensitive)
|
||||
_ = medicalData.sha1() // BAD
|
||||
_ = passwdData.sha1() // BAD
|
||||
_ = medicalData.sha1() // $ Alert
|
||||
_ = passwdData.sha1() // $ Alert
|
||||
_ = harmlessData.sha512() // GOOD
|
||||
_ = medicalData.sha512() // GOOD
|
||||
_ = passwdData.sha512() // BAD
|
||||
_ = passwdData.sha512() // $ Alert
|
||||
_ = harmlessData.sha2(.sha512) // GOOD
|
||||
_ = medicalData.sha2(.sha512) // GOOD
|
||||
_ = passwdData.sha2(.sha512) // BAD
|
||||
_ = passwdData.sha2(.sha512) // $ Alert
|
||||
_ = harmlessData.sha3(.sha512) // GOOD
|
||||
_ = medicalData.sha3(.sha512) // GOOD
|
||||
_ = passwdData.sha3(.sha512) // BAD
|
||||
_ = passwdData.sha3(.sha512) // $ Alert
|
||||
}
|
||||
|
||||
func testStrings(creditCardNumber: String, passwd: String) {
|
||||
_ = "harmless".md5() // GOOD (not sensitive)
|
||||
_ = creditCardNumber.md5() // BAD
|
||||
_ = passwd.md5() // BAD
|
||||
_ = creditCardNumber.md5() // $ Alert
|
||||
_ = passwd.md5() // $ Alert
|
||||
_ = "harmless".sha1() // GOOD (not sensitive)
|
||||
_ = creditCardNumber.sha1() // BAD
|
||||
_ = passwd.sha1() // BAD
|
||||
_ = creditCardNumber.sha1() // $ Alert
|
||||
_ = passwd.sha1() // $ Alert
|
||||
_ = "harmless".sha512() // GOOD
|
||||
_ = creditCardNumber.sha512() // GOOD
|
||||
_ = passwd.sha512() // BAD
|
||||
_ = passwd.sha512() // $ Alert
|
||||
_ = "harmless".sha2(.sha512) // GOOD
|
||||
_ = creditCardNumber.sha2(.sha512) // GOOD
|
||||
_ = passwd.sha2(.sha512) // BAD
|
||||
_ = passwd.sha2(.sha512) // $ Alert
|
||||
_ = "harmless".sha3(.sha512) // GOOD
|
||||
_ = creditCardNumber.sha3(.sha512) // GOOD
|
||||
_ = passwd.sha3(.sha512) // BAD
|
||||
_ = passwd.sha3(.sha512) // $ Alert
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-730/RegexInjection.ql
|
||||
query: queries/Security/CWE-730/RegexInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -92,59 +92,59 @@ extension String {
|
||||
|
||||
func regexInjectionTests(cond: Bool, varString: String, myUrl: URL) throws {
|
||||
let constString = ".*"
|
||||
let taintedString = String(contentsOf: myUrl) // tainted
|
||||
let taintedString = String(contentsOf: myUrl) // $ Source // tainted
|
||||
|
||||
// --- Regex ---
|
||||
|
||||
_ = try Regex(constString).firstMatch(in: varString)
|
||||
_ = try Regex(varString).firstMatch(in: varString)
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert
|
||||
|
||||
_ = try Regex("(a|" + constString + ")").firstMatch(in: varString)
|
||||
_ = try Regex("(a|" + taintedString + ")").firstMatch(in: varString) // BAD
|
||||
_ = try Regex("(a|" + taintedString + ")").firstMatch(in: varString) // $ Alert
|
||||
_ = try Regex("(a|\(constString))").firstMatch(in: varString)
|
||||
_ = try Regex("(a|\(taintedString))").firstMatch(in: varString) // BAD
|
||||
_ = try Regex("(a|\(taintedString))").firstMatch(in: varString) // $ Alert
|
||||
|
||||
_ = try Regex(cond ? constString : constString).firstMatch(in: varString)
|
||||
_ = try Regex(cond ? taintedString : constString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(cond ? constString : taintedString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(cond ? taintedString : constString).firstMatch(in: varString) // $ Alert
|
||||
_ = try Regex(cond ? constString : taintedString).firstMatch(in: varString) // $ Alert
|
||||
|
||||
_ = try (cond ? Regex(constString) : Regex(constString)).firstMatch(in: varString)
|
||||
_ = try (cond ? Regex(taintedString) : Regex(constString)).firstMatch(in: varString) // BAD
|
||||
_ = try (cond ? Regex(constString) : Regex(taintedString)).firstMatch(in: varString) // BAD
|
||||
_ = try (cond ? Regex(taintedString) : Regex(constString)).firstMatch(in: varString) // $ Alert
|
||||
_ = try (cond ? Regex(constString) : Regex(taintedString)).firstMatch(in: varString) // $ Alert
|
||||
|
||||
// --- RangeReplaceableCollection ---
|
||||
|
||||
var inputVar = varString
|
||||
inputVar.replace(constString, with: "")
|
||||
inputVar.replace(taintedString, with: "") // BAD
|
||||
inputVar.replace(taintedString, with: "") // $ Alert
|
||||
inputVar.replace(constString, with: taintedString)
|
||||
|
||||
// --- StringProtocol ---
|
||||
|
||||
_ = inputVar.replacingOccurrences(of: constString, with: "", options: .regularExpression)
|
||||
_ = inputVar.replacingOccurrences(of: taintedString, with: "", options: .regularExpression) // BAD
|
||||
_ = inputVar.replacingOccurrences(of: taintedString, with: "", options: .regularExpression) // $ Alert
|
||||
|
||||
// --- NSRegularExpression ---
|
||||
|
||||
_ = try NSRegularExpression(pattern: constString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count))
|
||||
_ = try NSRegularExpression(pattern: taintedString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count)) // BAD
|
||||
_ = try NSRegularExpression(pattern: taintedString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count)) // $ Alert
|
||||
|
||||
// --- NSString ---
|
||||
|
||||
let nsString = NSString(string: varString)
|
||||
_ = nsString.replacingOccurrences(of: constString, with: "", options: .regularExpression, range: NSMakeRange(0, nsString.length))
|
||||
_ = nsString.replacingOccurrences(of: taintedString, with: "", options: .regularExpression, range: NSMakeRange(0, nsString.length)) // BAD
|
||||
_ = nsString.replacingOccurrences(of: taintedString, with: "", options: .regularExpression, range: NSMakeRange(0, nsString.length)) // $ Alert
|
||||
|
||||
// --- from the qhelp ---
|
||||
|
||||
let remoteInput = taintedString
|
||||
let myRegex = ".*"
|
||||
|
||||
_ = try Regex(remoteInput) // BAD
|
||||
_ = try Regex(remoteInput) // $ Alert
|
||||
|
||||
let regexStr = "abc|\(remoteInput)"
|
||||
_ = try NSRegularExpression(pattern: regexStr) // BAD
|
||||
_ = try NSRegularExpression(pattern: regexStr) // $ Alert
|
||||
|
||||
_ = try Regex(myRegex)
|
||||
|
||||
@@ -159,35 +159,35 @@ func regexInjectionTests(cond: Bool, varString: String, myUrl: URL) throws {
|
||||
let okSet: Set = ["abc", "def"]
|
||||
|
||||
if (taintedString == okInput) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
} else {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert
|
||||
}
|
||||
if (taintedString != okInput) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert
|
||||
}
|
||||
if (varString == okInput) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // BAD
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert
|
||||
}
|
||||
if (okInputs.contains(taintedString)) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
}
|
||||
if (okInputs.firstIndex(of: taintedString) != nil) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
}
|
||||
if let index = okInputs.firstIndex(of: taintedString) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
}
|
||||
if let index = okInputs.index(of: taintedString) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
}
|
||||
if (okSet.contains(taintedString)) {
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
_ = try Regex(taintedString).firstMatch(in: varString) // $ Alert // GOOD (effectively sanitized by the check) [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
// --- multiple evaluations ---
|
||||
|
||||
let re = try Regex(taintedString) // BAD
|
||||
let re = try Regex(taintedString) // $ Alert
|
||||
_ = try re.firstMatch(in: varString) // (we only want to flag one location total)
|
||||
_ = try re.firstMatch(in: varString)
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-760/ConstantSalt.ql
|
||||
query: queries/Security/CWE-760/ConstantSalt.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -56,27 +56,27 @@ func test(myPassword: String) {
|
||||
let myIV = Data(0)
|
||||
let myRandomSalt1 = Data(getARandomString())
|
||||
let myRandomSalt2 = Data(getARandomString())
|
||||
let myConstantSalt1 = Data("abcdef123456")
|
||||
let myConstantSalt2 = Data(0)
|
||||
let myConstantSalt1 = Data("abcdef123456") // $ Source
|
||||
let myConstantSalt2 = Data(0) // $ Source
|
||||
|
||||
let _ = myEncryptor.key(forPassword: myPassword, salt: myRandomSalt1, settings: myKeyDerivationSettings) // GOOD
|
||||
let _ = myEncryptor.key(forPassword: myPassword, salt: myConstantSalt1, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myEncryptor.key(forPassword: myPassword, salt: myConstantSalt1, settings: myKeyDerivationSettings) // $ Alert
|
||||
let _ = myEncryptor.keyForPassword(myPassword, salt: myRandomSalt2, settings: myKeyDerivationSettings) // GOOD
|
||||
let _ = myEncryptor.keyForPassword(myPassword, salt: myConstantSalt2, settings: myKeyDerivationSettings) // BAD
|
||||
let _ = myEncryptor.keyForPassword(myPassword, salt: myConstantSalt2, settings: myKeyDerivationSettings) // $ Alert
|
||||
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myRandomSalt2, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myConstantSalt1, hmacSalt: myRandomSalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myConstantSalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myConstantSalt1, hmacSalt: myRandomSalt2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myConstantSalt2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myRandomSalt2, handler: myHandler) // GOOD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myConstantSalt1, HMACSalt: myRandomSalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myConstantSalt2, handler: myHandler) // BAD
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myConstantSalt1, HMACSalt: myRandomSalt2, handler: myHandler) // $ Alert
|
||||
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myConstantSalt2, handler: myHandler) // $ Alert
|
||||
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myRandomSalt2) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myConstantSalt1, hmacSalt: myRandomSalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myConstantSalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myConstantSalt1, hmacSalt: myRandomSalt2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myPassword, iv: myIV, encryptionSalt: myRandomSalt1, hmacSalt: myConstantSalt2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myRandomSalt2) // GOOD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myConstantSalt1, HMACSalt: myRandomSalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myConstantSalt2) // BAD
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myConstantSalt1, HMACSalt: myRandomSalt2) // $ Alert
|
||||
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myPassword, IV: myIV, encryptionSalt: myRandomSalt1, HMACSalt: myConstantSalt2) // $ Alert
|
||||
|
||||
// appending constants
|
||||
let _ = myEncryptor.key(forPassword: myPassword, salt: Data(getARandomString() + getARandomString()), settings: myKeyDerivationSettings) // GOOD
|
||||
|
||||
@@ -26,7 +26,7 @@ final class Scrypt {
|
||||
|
||||
// Helper functions
|
||||
func getConstantString() -> String {
|
||||
"this string is constant"
|
||||
"this string is constant" // $ Source
|
||||
}
|
||||
|
||||
func getConstantArray() -> Array<UInt8> {
|
||||
@@ -40,7 +40,7 @@ func getRandomArray() -> Array<UInt8> {
|
||||
// --- tests ---
|
||||
|
||||
func test() {
|
||||
let constantSalt: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f]
|
||||
let constantSalt: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f] // $ Source
|
||||
let constantStringSalt = getConstantArray()
|
||||
let randomSalt = getRandomArray()
|
||||
let randomArray = getRandomArray()
|
||||
@@ -48,23 +48,23 @@ func test() {
|
||||
let iterations = 120120
|
||||
|
||||
// HKDF test cases
|
||||
let hkdfb1 = HKDF(password: randomArray, salt: constantSalt, info: randomArray, keyLength: 0, variant: variant) // BAD
|
||||
let hkdfb2 = HKDF(password: randomArray, salt: constantStringSalt, info: randomArray, keyLength: 0, variant: variant) // BAD
|
||||
let hkdfb1 = HKDF(password: randomArray, salt: constantSalt, info: randomArray, keyLength: 0, variant: variant) // $ Alert
|
||||
let hkdfb2 = HKDF(password: randomArray, salt: constantStringSalt, info: randomArray, keyLength: 0, variant: variant) // $ Alert
|
||||
let hkdfg1 = HKDF(password: randomArray, salt: randomSalt, info: randomArray, keyLength: 0, variant: variant) // GOOD
|
||||
|
||||
// PBKDF1 test cases
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: randomArray, salt: constantSalt, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: randomArray, salt: constantStringSalt, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: randomArray, salt: constantSalt, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: randomArray, salt: constantStringSalt, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf1g1 = PKCS5.PBKDF1(password: randomArray, salt: randomSalt, iterations: iterations, keyLength: 0) // GOOD
|
||||
|
||||
|
||||
// PBKDF2 test cases
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: randomArray, salt: constantSalt, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: randomArray, salt: constantStringSalt, iterations: iterations, keyLength: 0) // BAD
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: randomArray, salt: constantSalt, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: randomArray, salt: constantStringSalt, iterations: iterations, keyLength: 0) // $ Alert
|
||||
let pbkdf2g1 = PKCS5.PBKDF2(password: randomArray, salt: randomSalt, iterations: iterations, keyLength: 0) // GOOD
|
||||
|
||||
// Scrypt test cases
|
||||
let scryptb1 = Scrypt(password: randomArray, salt: constantSalt, dkLen: 64, N: 16384, r: 8, p: 1) // BAD
|
||||
let scryptb2 = Scrypt(password: randomArray, salt: constantStringSalt, dkLen: 64, N: 16384, r: 8, p: 1) // BAD
|
||||
let scryptb1 = Scrypt(password: randomArray, salt: constantSalt, dkLen: 64, N: 16384, r: 8, p: 1) // $ Alert
|
||||
let scryptb2 = Scrypt(password: randomArray, salt: constantStringSalt, dkLen: 64, N: 16384, r: 8, p: 1) // $ Alert
|
||||
let scryptg1 = Scrypt(password: randomArray, salt: randomSalt, dkLen: 64, N: 16384, r: 8, p: 1) // GOOD
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
queries/Security/CWE-916/InsufficientHashIterations.ql
|
||||
query: queries/Security/CWE-916/InsufficientHashIterations.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -17,7 +17,7 @@ extension PKCS5 {
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
func getLowIterationCount() -> Int { return 99999 }
|
||||
func getLowIterationCount() -> Int { return 99999 } // $ Source
|
||||
|
||||
func getEnoughIterationCount() -> Int { return 120120 }
|
||||
|
||||
@@ -34,15 +34,15 @@ func test() {
|
||||
let enoughIterations = getEnoughIterationCount()
|
||||
|
||||
// PBKDF1 test cases
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: lowIterations, keyLength: 0) // BAD
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: 80000, keyLength: 0) // BAD
|
||||
let pbkdf1b1 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: lowIterations, keyLength: 0) // $ Alert
|
||||
let pbkdf1b2 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: 80000, keyLength: 0) // $ Alert
|
||||
let pbkdf1g1 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: enoughIterations, keyLength: 0) // GOOD
|
||||
let pbkdf1g2 = PKCS5.PBKDF1(password: randomArray, salt: randomArray, iterations: 120120, keyLength: 0) // GOOD
|
||||
|
||||
|
||||
// PBKDF2 test cases
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: lowIterations, keyLength: 0) // BAD
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: 80000, keyLength: 0) // BAD
|
||||
let pbkdf2b1 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: lowIterations, keyLength: 0) // $ Alert
|
||||
let pbkdf2b2 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: 80000, keyLength: 0) // $ Alert
|
||||
let pbkdf2g1 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: enoughIterations, keyLength: 0) // GOOD
|
||||
let pbkdf2g2 = PKCS5.PBKDF2(password: randomArray, salt: randomArray, iterations: 120120, keyLength: 0) // GOOD
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user