mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:53 +00:00

Part of https://github.com/astral-sh/ruff/issues/1646. ## Summary Implement `S610` rule from `flake8-bandit`. Upstream references: - Implementation: https://github.com/PyCQA/bandit/blob/1.7.8/bandit/plugins/django_sql_injection.py#L20-L97 - Test cases: https://github.com/PyCQA/bandit/blob/1.7.8/examples/django_sql_injection_extra.py - Test assertion: https://github.com/PyCQA/bandit/blob/1.7.8/tests/functional/test_functional.py#L517-L524 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](https://docs.djangoproject.com/en/5.0/ref/models/querysets/), but AFAIK Ruff is not able to resolve classes outside of the current module. ## Test Plan Snapshot tests
34 lines
1.4 KiB
Python
34 lines
1.4 KiB
Python
from django.contrib.auth.models import User
|
|
|
|
# Errors
|
|
User.objects.filter(username='admin').extra(dict(could_be='insecure'))
|
|
User.objects.filter(username='admin').extra(select=dict(could_be='insecure'))
|
|
User.objects.filter(username='admin').extra(select={'test': '%secure' % 'nos'})
|
|
User.objects.filter(username='admin').extra(select={'test': '{}secure'.format('nos')})
|
|
User.objects.filter(username='admin').extra(where=['%secure' % 'nos'])
|
|
User.objects.filter(username='admin').extra(where=['{}secure'.format('no')])
|
|
|
|
query = '"username") AS "username", * FROM "auth_user" WHERE 1=1 OR "username"=? --'
|
|
User.objects.filter(username='admin').extra(select={'test': query})
|
|
|
|
where_var = ['1=1) OR 1=1 AND (1=1']
|
|
User.objects.filter(username='admin').extra(where=where_var)
|
|
|
|
where_str = '1=1) OR 1=1 AND (1=1'
|
|
User.objects.filter(username='admin').extra(where=[where_str])
|
|
|
|
tables_var = ['django_content_type" WHERE "auth_user"."username"="admin']
|
|
User.objects.all().extra(tables=tables_var).distinct()
|
|
|
|
tables_str = 'django_content_type" WHERE "auth_user"."username"="admin'
|
|
User.objects.all().extra(tables=[tables_str]).distinct()
|
|
|
|
# OK
|
|
User.objects.filter(username='admin').extra(
|
|
select={'test': 'secure'},
|
|
where=['secure'],
|
|
tables=['secure']
|
|
)
|
|
User.objects.filter(username='admin').extra({'test': 'secure'})
|
|
User.objects.filter(username='admin').extra(select={'test': 'secure'})
|
|
User.objects.filter(username='admin').extra(where=['secure'])
|