# 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:

    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:

    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:

    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:

    ("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