Skip to content

Commit

Permalink
Check for hardcoded passwords in class attributes (#766)
Browse files Browse the repository at this point in the history
* Check for hardcoded passwords in class attributes

B105:hardcoded_password_string currently throws an error for string
literal variables, dictionary keys, and comparisons which look like
passwords, but does not create an error for class attributes which look
like passwords.

For example password = "mypassword" and password == "mypassword"
would create an error, but my_object.password = "mypassword",
and my_object.password == "mypassword" would not.
This behavior is unintuitive.

Resolves #759

* Add tests for hardcoded passwords in classes

* Update general_hardcoded_password.py

Co-authored-by: Eric Brown <ericwb@users.noreply.github.com>
  • Loading branch information
noliverio and ericwb committed Feb 8, 2022
1 parent d1622bf commit a9eaafa
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
9 changes: 9 additions & 0 deletions bandit/plugins/general_hardcoded_password.py
Expand Up @@ -36,6 +36,7 @@ def hardcoded_password_string(context):
- assigned to a variable that looks like a password
- assigned to a dict key that looks like a password
- assigned to a class attribute that looks like a password
- used in a comparison with a variable that looks like a password
Variables are considered to look like a password if they have match any one
Expand Down Expand Up @@ -84,6 +85,10 @@ def hardcoded_password_string(context):
for targ in node._bandit_parent.targets:
if isinstance(targ, ast.Name) and RE_CANDIDATES.search(targ.id):
return _report(node.s)
elif isinstance(targ, ast.Attribute) and RE_CANDIDATES.search(
targ.attr
):
return _report(node.s)

elif isinstance(
node._bandit_parent, ast.Subscript
Expand Down Expand Up @@ -114,6 +119,10 @@ def hardcoded_password_string(context):
if RE_CANDIDATES.search(comp.left.id):
if isinstance(comp.comparators[0], ast.Str):
return _report(comp.comparators[0].s)
elif isinstance(comp.left, ast.Attribute):
if RE_CANDIDATES.search(comp.left.attr):
if isinstance(comp.comparators[0], ast.Str):
return _report(comp.comparators[0].s)


@test.checks("Call")
Expand Down
12 changes: 12 additions & 0 deletions examples/hardcoded-passwords.py
@@ -1,3 +1,8 @@
# Possible hardcoded password: 'class_password'
# Severity: Low Confidence: Medium
class SomeClass:
password = "class_password"

# Possible hardcoded password: 'Admin'
# Severity: Low Confidence: Medium
def someFunction(user, password="Admin"):
Expand All @@ -21,6 +26,13 @@ def NoMatch2(password):
if password == "ajklawejrkl42348swfgkg":
print("Nice password!")

def noMatchObject():
obj = SomeClass()
# Possible hardcoded password: 'this cool password'
# Severity: Low Confidence: Medium
if obj.password == "this cool password":
print(obj.password)

# Possible hardcoded password: 'blerg'
# Severity: Low Confidence: Medium
def doLogin(password="blerg"):
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/test_functional.py
Expand Up @@ -157,8 +157,8 @@ def test_exec(self):
def test_hardcoded_passwords(self):
"""Test for hard-coded passwords."""
expect = {
"SEVERITY": {"UNDEFINED": 0, "LOW": 12, "MEDIUM": 0, "HIGH": 0},
"CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 12, "HIGH": 0},
"SEVERITY": {"UNDEFINED": 0, "LOW": 14, "MEDIUM": 0, "HIGH": 0},
"CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 14, "HIGH": 0},
}
self.check_example("hardcoded-passwords.py", expect)

Expand Down

0 comments on commit a9eaafa

Please sign in to comment.