Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flake8-bandit]: Implement S610 rule #10316

Merged

Conversation

mkniewallner
Copy link
Contributor

@mkniewallner mkniewallner commented Mar 9, 2024

Part of #1646.

Summary

Implement S610 rule from flake8-bandit.

Upstream references:

The implementation in bandit targets additional arguments (params, order_by and select_params) but doesn't seem to do anything with them in the end, so I did not include them in the implementation.

Note that this rule could be prone to false positives, as ideally we would want to check if extra() is tied to a Django queryset, but AFAIK Ruff is not able to resolve classes outside of the current module.

Test Plan

Snapshot tests

Copy link

github-actions bot commented Mar 9, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+22 -0 violations, +0 -0 fixes in 1 projects; 42 projects unchanged)

zulip/zulip (+22 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview --select ALL

+ zerver/actions/message_flags.py:108:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/actions/message_flags.py:160:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/actions/message_flags.py:232:15: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/actions/message_flags.py:42:15: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/actions/message_flags.py:56:23: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/lib/message.py:536:15: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/lib/message.py:576:36: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/lib/push_notifications.py:1076:15: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/lib/query_helpers.py:26:24: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/lib/users.py:200:89: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/models/streams.py:265:47: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_flags.py:267:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_flags.py:300:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_flags.py:577:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_flags.py:681:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_flags.py:692:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_move_topic.py:1505:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_move_topic.py:1512:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_move_topic.py:1577:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/tests/test_message_move_topic.py:1584:19: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/views/read_receipts.py:80:15: S610 Use of Django `extra` can lead to SQL injection vulnerabilities
+ zerver/worker/queue_processors.py:1079:93: S610 Use of Django `extra` can lead to SQL injection vulnerabilities

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
S610 22 22 0 0 0

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

Comment on lines 38 to 40
if !checker.semantic().seen_module(Modules::DJANGO) {
return;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also done for django_raw_sql, but I'm wondering if this should also be done for this rule.

In django_raw_sql, RawSQL import comes from django module, so this is reliable, but in our case, extra can be used even if no django imports occurs, if for instance a model defined in another file in a codebase is used, so this could skip the check for several valid cases.

On the other hand, the entire rule has the potential of having several false positives, so this could be seen as a way to know if a file belongs to a project using Django. But if I'm not mistaken, seen_module only applies to the current file, not the whole codebase, and in this specific case the latter would probably be preferable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case in point, the ecosystem checks detects 18 errors while bandit detects 22. That's because there are 4 things that would have been flagged in https://github.com/zulip/zulip/blob/29ca4ba6620f16598e1171be7495356f56b84328/zerver/tests/test_message_move_topic.py, but are skipped because there is no import from django in this file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm okay with leaving this in for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could go either way though. extra isn't a common method name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that the combination of extra and select/where/tables arguments should not be that common outside of Django. Worst case, for the few times it would get triggered, it's always possible for users to ignore the false positives, while skipping the check entirely if Ruff does not find a django import would leave the user with no clue that the check was not run because of that. So I think it might be best in the end to not check if Django was seen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and removed the check in 4e88142. Also updated the error message so that in case of false positives, the user at least knows that this is related to Django.

match argument_name {
"select" => match argument {
Expr::Dict(ExprDict { keys, values, .. }) => {
if !keys.iter().flatten().all(Expr::is_string_literal_expr) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flatten() is used to remove optional keys here. Not sure that this is really a clean way to do this, let me know if not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to flag on select(**kwargs)? It seems like this wouldn't, but it probably should, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I misread.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to consider allowing: select(**{"foo": "bar"})

@mkniewallner mkniewallner marked this pull request as ready for review March 9, 2024 19:40
@charliermarsh charliermarsh added rule Implementing or modifying a lint rule preview Related to preview mode features labels Mar 11, 2024
@charliermarsh charliermarsh self-requested a review March 11, 2024 22:21
@charliermarsh charliermarsh merged commit fc7139d into astral-sh:main Mar 12, 2024
17 checks passed
Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preview Related to preview mode features rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants