Skip to content
This repository has been archived by the owner on Oct 6, 2020. It is now read-only.

DUO137 Itsdangerous false positive fix #40

Merged
merged 5 commits into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- `DUO137`: lint for insecure itsdangerous kwarg usage ([#36](https://github.com/duo-labs/dlint/issues/36))

### Fixed
- False positive for `DUO137`. ([#39](https://github.com/duo-labs/dlint/issues/39))

## [0.9.2] - 2019-11-21
### Fixed
- False negative with arbitrary depth from import alias in bad module attribute ([#32](https://github.com/duo-labs/dlint/issues/32))
Expand Down
7 changes: 1 addition & 6 deletions dlint/linters/bad_itsdangerous_kwarg_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@ def none_algorithm_predicate(call, kwarg_name):
])

def none_string_predicate(call, kwarg_name):
return functools.partial(
tree.kwarg_str,
call,
kwarg_name,
"none"
),
return tree.kwarg_str(call, kwarg_name, "none")

return [
{
Expand Down
50 changes: 50 additions & 0 deletions tests/test_bad_itsdangerous_kwarg_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,56 @@ def test_bad_itsdangerous_kwarg_usage(self):

assert result == expected

def test_false_positive_in_the_wild(self):
python_node = self.get_ast_node(
"""
from flask.ext.restful import fields, url_for
from itsdangerous import JSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature
from werkzeug.security import generate_password_hash, check_password_hash
from . import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(256), unique=True)
password_hash = db.Column(db.String(256))

def generate_api_token(self):
serializer = Serializer(app.config['SECRET_KEY'])
return serializer.dumps({'id': self.id})

@staticmethod
def verify_api_token(token):
serializer = Serializer(app.config['SECRET_KEY'])
try:
data = serializer.loads(token)
except BadSignature:
# invalid token
return None
return User.query.get(data['id'])

@property
def password(self):
raise AttributeError('password is not readable')

@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)

def verify_password(self, password):
return check_password_hash(self.password_hash, password)

def __repr__(self):
return '<User %r>' % self.email
"""
)
linter = dlint.linters.BadItsDangerousKwargUseLinter()
linter.visit(python_node)

result = linter.get_results()
expected = []
assert result == expected


if __name__ == "__main__":
unittest.main()