django-security — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited django-security (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill is the Django-specific layer on top of secure-coding. Use it when Django gets in its own way: defaults that invite misunderstanding, ORM paths that look safe but still allow SQLi, or settings that may go wrong per environment.
Triggers on:
manage.py, settings.py, urls.py, models.py, views.py, Django middleware class paths in MIDDLEWARE, DRF viewsets.py or serializers.py.@csrf_exempt, |safe, mark_safe, .raw(), .extra(), RawSQL, or HttpResponse(user_input).security-review where Django is in the stack.secure-coding.api-security: OAuth/JWT flow, OWASP API Top 10 belong there. Django-specific DRF foot-guns (e.g. HyperlinkedModelSerializer authorization bypass) stay here.p/django) → sast-orchestrator.cve-triage.container-hardening / iac-security.secrets-scanner.Six phases. Django defaults are reasonably safe; most issues arise where you deliberately override them.
python manage.py check --deploy is a Django-built-in checker. Always run it, fix every warning before production. Not sufficient, but necessary.
Critical settings:
DEBUG = True leaks stack traces, env vars, SQL queries: full app-internal exposure. No exceptions.['*'] in prod is a Host-header-injection vector.secrets-scanner.SECURE_HSTS_INCLUDE_SUBDOMAINS and SECURE_HSTS_PRELOAD, `SESSION_COOKIE_SECURE = True`, `CSRF_COOKIE_SECURE = True`. Only where TLS is guaranteed.'Strict'.django-argon2 package.ATOMIC_REQUESTS where appropriate, separate DB user with least privilege (no DROP/CREATE rights for the web user).Django's ORM parameterizes by default. SQLi arises in places where you step out of it:
Model.objects.raw('SELECT * FROM app_model WHERE name = %s', [name]). Not f'SELECT ... WHERE name = {name}'.where=, params=, select= can be abused. Prefer to replace with Func(), RawSQL() with params, or annotate() with ExpressionWrapper.RawSQL("select col from sometable where othercol = %s", (someparam,)). Follow that..order_by(request.GET.get('sort')) lets users pick columns. Allowlist permitted column names.Django CVE references (within a 3-year window, verify against release notes):
[verify against https://docs.djangoproject.com/en/dev/releases/security/] for the current window.Django templates have autoescape on by default. XSS arises when you turn it off.
|safe. If s contains user input or is composed of user input, you have XSS.javascript: URLs via href bypass HTML escaping. Validate user_url.startswith(('http:', 'https:')).Template(user_input).render(...)), you get SSTI with potential RCE. Never do this.render() or encode explicitly.Django's CsrfViewMiddleware is on by default for POST/PUT/PATCH/DELETE.
@csrf_exempt in a PR is a security-review moment.SessionAuthentication enforces CSRF, TokenAuthentication/JWT does not (stateless). Mixed auth modes: be explicit about which endpoints use which model.False, which is needed for JS to read the token. Do not change unless you have a custom CSRF setup./admin/ (security through obscurity + bot-traffic reduction)./admin/*.django-otp or django-allauth with TOTP.SESSION_COOKIE_AGE reasonably short, SESSION_EXPIRE_AT_BROWSER_CLOSE where appropriate, session rotation on privilege change (automatic on login since Django 2+).FileField does not validate content type. UploadedFile.content_type is set by the client. Validate magic bytes, whitelist extensions, store outside web root.redirect(request.GET.get('next')) without validation is an open redirect. Django has url_has_allowed_host_and_scheme(url, allowed_hosts=...) for this purpose.SecurityMiddleware belongs high, CsrfViewMiddleware before AuthenticationMiddleware, custom middleware with side effects close to the view. Wrong order can produce subtle bypasses.sast-orchestrator.Verification-loop: Layer 1 scope (settings file + urls + middleware stack all walked through?), assumptions (autoescape on everywhere, no |safe on user input?), gaps (DRF views included in the same review?). Layer 2 specifically on CVE IDs (verify against Django release notes, not memory), security-setting names (Django sometimes changes default values per major version), admin-hardening claims backed by concrete middleware/package.
Follow the security-review report format, with a Django-specific scan summary at the top:
Django security review — <app/project>
Django version: <x.y.z> (latest security release: <...>)
Deploy checklist (python manage.py check --deploy):
Warnings: N → resolved/open
DEBUG in prod: <False | FINDING>
ALLOWED_HOSTS: <explicit | wildcard — FINDING>
SECURE_* settings: <complete | gaps>
PASSWORD_HASHERS: <Argon2 first | PBKDF2 default>
Code patterns:
@csrf_exempt: <N, location, reason>
|safe / mark_safe: <N, on user input? FINDING>
.raw() / .extra(): <N, parameterized?>
order_by(user input): <list>
Admin:
URL not /admin/: <yes/no>
IP restriction: <yes/no>
2FA on staff: <yes/no>
Version check:
On latest security release: <yes | N months behind>
CVE relevance: <handoff to cve-triage>
Findings (severity-sorted, follow security-review format)
Verification-loop: ...manage.py check --deploy checks.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.