# DJG101

This check looks for ways that Django SQL Injection protection is being bypassed, by using quoted parameters.

The check looks at the following use cases:

* Use of `RawSQL()` constructor directly
* Use of `cursor.execute()`
* Use of `raw()` on a `Manager` instance

Whilst the methods support parametrized queries, if the `%s` value is quoted with single-quotes, the value is still vulnerable to SQL injection.

This also applies to parametrized arguments,  where it includes a substitute reference, e.g. `'%(variable)s'`.

## Example

The first example is using the RawSQL constructor directly and annotating a query set:

```python
from django.db.models.expressions import RawSQL

qs.annotate(val=RawSQL("select col from sometable where othercol = '%s'", (someparam,)))  # this is bad!
```

Another example is using the `raw()` method on a manager to filter results, exposing SQL injection:

```python
from django import things
from .models import User

def my_view(self):
    User.objects.raw("SELECT * FROM myapp_person WHERE last_name = '%s'", [lname])  # this is also bad!
```

Cursors can also be exploited using the same technique:

```python
from django.db import connection

def my_custom_sql(self):
    with connection.cursor() as cursor:
        cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
        cursor.execute("SELECT foo FROM bar WHERE baz = '%s'", [self.baz])
        row = cursor.fetchone()
    return row
```

## Fixes

Remove the quotations from the string values:

```python
("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz]) # good
("UPDATE bar SET foo = 1 WHERE baz = '%s'", [self.baz]) # bad!
```

## See Also

* [Official Documentation](https://docs.djangoproject.com/en/3.0/ref/models/expressions/#django.db.models.expressions.RawSQL)