Skip to content

Commit e6b748a

Browse files
authored
Merge pull request #1875 from esben-semmle/js/blacklist-more-hardcoded-passwords
Approved by xiemaisi
2 parents 526c123 + a5645e1 commit e6b748a

11 files changed

Lines changed: 164 additions & 93 deletions

File tree

change-notes/1.23/analysis-javascript.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. |
2424
| Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. |
2525
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. |
26+
| Hard-coded credentials (`js/hardcoded-credentials`) | Fewer false-positive results | This rule now flags fewer password examples. |
27+
| Password in configuration file (`js/password-in-configuration-file`) | Fewer false-positive results | This rule now flags fewer password examples. |
2628
| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. |
2729
| Incorrect suffix check (`js/incorrect-suffix-check`) | Fewer false-positive results | The query recognizes valid checks in more cases. |
2830

javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import javascript
1515
import semmle.javascript.RestrictedLocations
16+
import semmle.javascript.security.SensitiveActions
1617

1718
/**
1819
* Holds if some JSON or YAML file contains a property with name `key`
@@ -56,7 +57,8 @@ where
5657
key.toLowerCase() = "password" and
5758
pwd = val and
5859
// exclude interpolations of environment variables
59-
not val.regexpMatch("\\$.*|%.*%")
60+
not val.regexpMatch("\\$.*|%.*%") and
61+
not PasswordHeuristics::isDummyPassword(val)
6062
or
6163
key.toLowerCase() != "readme" and
6264
// look for `password=...`, but exclude `password=;`, `password="$(...)"`,

javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ where
2222
// use source value in message if it's available
2323
if source.getNode().asExpr() instanceof ConstantString
2424
then
25-
value = "The hard-coded value \"" + source.getNode().getStringValue() +
26-
"\""
25+
exists(string val | val = source.getNode().getStringValue() |
26+
// exclude dummy passwords
27+
not (
28+
sink.getNode().(Sink).(DefaultCredentialsSink).getKind() = "password" and
29+
PasswordHeuristics::isDummyPassword(val)
30+
) and
31+
value = "The hard-coded value \"" + val + "\""
32+
)
2733
else value = "This hard-coded value"
2834
select source.getNode(), source, sink, value + " is used as $@.", sink.getNode(),
2935
sink.getNode().(Sink).getKind()

javascript/ql/src/semmle/javascript/security/SensitiveActions.qll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,21 @@ class CleartextPasswordExpr extends SensitiveExpr {
245245

246246
override SensitiveExpr::Classification getClassification() { none() }
247247
}
248+
249+
/**
250+
* Provides heuristics for classifying passwords.
251+
*/
252+
module PasswordHeuristics {
253+
/**
254+
* Holds if `password` looks like a deliberately weak password that the user should change.
255+
*/
256+
bindingset[password]
257+
predicate isDummyPassword(string password) {
258+
password.length() < 4
259+
or
260+
exists(string normalized | normalized = password.toLowerCase() |
261+
count(normalized.charAt(_)) = 1 or
262+
normalized.regexpMatch(".*(pass|test|sample|example|secret|root|admin|user|change|auth).*")
263+
)
264+
}
265+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
| | true |
2+
| XXXXXXXX | true |
3+
| abcdefgh | false |
4+
| admin | true |
5+
| change_me | true |
6+
| example_password | true |
7+
| insert-auth-from-gui | true |
8+
| root | true |
9+
| sOKY6ccizpmvF*32so%Q | false |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import javascript
2+
import semmle.javascript.security.SensitiveActions
3+
4+
string getASamplePassword() {
5+
result = "abcdefgh" or
6+
result = "sOKY6ccizpmvF*32so%Q" or
7+
result = "XXXXXXXX" or
8+
result = "example_password" or
9+
result = "change_me" or
10+
result = "" or
11+
result = "insert-auth-from-gui" or
12+
result = "admin" or
13+
result = "root"
14+
}
15+
16+
from string password, boolean isDummy
17+
where
18+
password = getASamplePassword() and
19+
if PasswordHeuristics::isDummyPassword(password) then isDummy = true else isDummy = false
20+
select password, isDummy
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| mysql-config.json:4:16:4:23 | "secret" | Hard-coded password 'secret' in configuration file. |
1+
| mysql-config.json:4:16:4:25 | "abcdefgh" | Hard-coded password 'abcdefgh' in configuration file. |
22
| tst4.json:2:10:2:38 | "script ... ecret'" | Hard-coded password ''secret'' in configuration file. |
33
| tst7.yml:2:9:2:6 | \| | Hard-coded password 'abc' in configuration file. |
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"host" : "localhost",
33
"user" : "me",
4-
"password" : "secret",
4+
"password" : "abcdefgh",
55
"database" : "my_db"
6-
}
6+
}

javascript/ql/test/query-tests/Security/CWE-313/tst.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ steps:
44
OTHER_PASSWORD=`get password` yarn install
55
username: <%= ENV['USERNAME'] %>
66
password: <%= ENV['PASSWORD'] %>
7+
password: change_me

javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected

Lines changed: 62 additions & 57 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)