Communitygithub.com

seguranca-django

Melhores práticas de segurança para Django: autenticação, autorização, proteção CSRF, prevenção de SQL injection e XSS, além de configurações seguras de deployment. Use ao revisar autenticação, autorização, tratamento de entrada ou configurações de implantação no Django.

O que é seguranca-django?

A skill seguranca-django oferece um guia abrangente para proteger aplicações Django contra vulnerabilidades comuns, cobrindo desde configurações básicas de produção até tópicos avançados como prevenção de ataques. Suporta plataformas como Claude Code, Cursor e Codex, sendo ativada durante a configuração de autenticação/autorização, deploy em produção ou revisão de segurança. Inclui práticas essenciais: desabilitar DEBUG, configurar cabeçalhos de segurança (HSTS, XSS, clickjacking), validar senhas com Argon2, usar modelos de usuário personalizados, prevenir SQL injection via ORM (com advertências contra interpolação direta), sanitizar saída em templates contra XSS, proteger CSRF com cookies seguros, validar uploads por bytes mágicos (usando python-magic ou filetype) e limitar taxas em APIs. A documentação é rica em exemplos de código Python e Django Templates, com seções detalhadas sobre RBAC, permissões personalizadas e armazenamento seguro de arquivos. O conteúdo é prático, direto e focado em mitigar riscos reais, sendo ideal para desenvolvedores que querem implementar segurança desde o início ou auditar aplicações existentes.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/django-security

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Melhores Práticas de Segurança no Django

Diretrizes abrangentes de segurança para aplicações Django, protegendo contra vulnerabilidades comuns.

Quando Ativar

  • Configurando autenticação e autorização no Django
  • Implementando permissões e papéis de usuário
  • Configurando definições de segurança em produção
  • Revisando aplicações Django em busca de problemas de segurança
  • Implantando aplicações Django em produção

Configurações Principais de Segurança

Configuração de Produção

# settings/production.py
import os

DEBUG = False  # CRÍTICO: Nunca usar True em produção

ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')

# Cabeçalhos de segurança
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000  # 1 ano
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'

# HTTPS e Cookies
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'

# Chave secreta (deve ser definida via variável de ambiente)
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
if not SECRET_KEY:
    raise ImproperlyConfigured('A variável de ambiente DJANGO_SECRET_KEY é obrigatória')

# Validação de senhas
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 12,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

Autenticação

Modelo de Usuário Personalizado

# apps/users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    """Modelo de usuário personalizado para maior segurança."""

    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=20, blank=True)

    USERNAME_FIELD = 'email'  # Usar email como nome de usuário
    REQUIRED_FIELDS = ['username']

    class Meta:
        db_table = 'users'
        verbose_name = 'Usuário'
        verbose_name_plural = 'Usuários'

    def __str__(self):
        return self.email

# settings/base.py
AUTH_USER_MODEL = 'users.User'

Hash de Senhas

# Django usa PBKDF2 por padrão. Para maior segurança:
PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]

Gerenciamento de Sessão

# Configuração de sessão
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # Ou 'db'
SESSION_CACHE_ALIAS = 'default'
SESSION_COOKIE_AGE = 3600 * 24 * 7  # 1 semana
SESSION_SAVE_EVERY_REQUEST = False
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # Melhor UX, mas menos seguro

Autorização

Permissões

# models.py
from django.db import models
from django.contrib.auth.models import Permission

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        permissions = [
            ('can_publish', 'Pode publicar posts'),
            ('can_edit_others', 'Pode editar posts de outros'),
        ]

    def user_can_edit(self, user):
        """Verifica se o usuário pode editar este post."""
        return self.author == user or user.has_perm('app.can_edit_others')

# views.py
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import UpdateView

class PostUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    model = Post
    permission_required = 'app.can_edit_others'
    raise_exception = True  # Retornar 403 em vez de redirecionar

    def get_queryset(self):
        """Permite apenas que usuários editem seus próprios posts."""
        return Post.objects.filter(author=self.request.user)

Permissões Personalizadas

# permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    """Permite que apenas proprietários editem objetos."""

    def has_object_permission(self, request, view, obj):
        # Permissões de leitura permitidas para qualquer requisição
        if request.method in permissions.SAFE_METHODS:
            return True

        # Permissões de escrita apenas para o proprietário
        return obj.author == request.user

class IsAdminOrReadOnly(permissions.BasePermission):
    """Permite que administradores façam qualquer coisa; outros, apenas leitura."""

    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True
        return request.user and request.user.is_staff

class IsVerifiedUser(permissions.BasePermission):
    """Permite apenas usuários verificados."""

    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_verified

Controle de Acesso Baseado em Papéis (RBAC)

# models.py
from django.contrib.auth.models import AbstractUser, Group

class User(AbstractUser):
    ROLE_CHOICES = [
        ('admin', 'Administrador'),
        ('moderator', 'Moderador'),
        ('user', 'Usuário Regular'),
    ]
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')

    def is_admin(self):
        return self.role == 'admin' or self.is_superuser

    def is_moderator(self):
        return self.role in ['admin', 'moderator']

# Mixins
class AdminRequiredMixin:
    """Mixin para exigir papel de administrador."""

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated or not request.user.is_admin():
            from django.core.exceptions import PermissionDenied
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

Prevenção de SQL Injection

Proteção com ORM do Django

# BOM: O ORM do Django escapa parâmetros automaticamente
def get_user(username):
    return User.objects.get(username=username)  # Seguro

# BOM: Usando parâmetros com raw()
def search_users(query):
    return User.objects.raw('SELECT * FROM users WHERE username = %s', [query])

# RUIM: Nunca interpolar diretamente entrada do usuário
def get_user_bad(username):
    return User.objects.raw(f'SELECT * FROM users WHERE username = {username}')  # VULNERÁVEL!

# BOM: Usando filter com escape adequado
def get_users_by_email(email):
    return User.objects.filter(email__iexact=email)  # Seguro

# BOM: Usando objetos Q para consultas complexas
from django.db.models import Q
def search_users_complex(query):
    return User.objects.filter(
        Q(username__icontains=query) |
        Q(email__icontains=query)
    )  # Seguro

Segurança Extra com raw()

# Se precisar usar SQL bruto, sempre use parâmetros
User.objects.raw(
    'SELECT * FROM users WHERE email = %s AND status = %s',
    [user_input_email, status]
)

Prevenção de XSS

Escape em Templates

{# Django escapa variáveis por padrão - SEGURO #}
{{ user_input }}  {# HTML escapado #}

{# Marcar explicitamente como seguro apenas para conteúdo confiável #}
{{ trusted_html|safe }}  {# Não escapado #}

{# Usar filtros de template para HTML seguro #}
{{ user_input|escape }}  {# Mesmo que o padrão #}
{{ user_input|striptags }}  {# Remove todas as tags HTML #}

{# Escape para JavaScript #}
<script>
    var username = {{ username|escapejs }};
</script>

Manipulação Segura de Strings

from django.utils.safestring import mark_safe
from django.utils.html import escape

# RUIM: Nunca marcar entrada do usuário como segura sem escapar
def render_bad(user_input):
    return mark_safe(user_input)  # VULNERÁVEL!

# BOM: Escapar primeiro, depois marcar como seguro
def render_good(user_input):
    return mark_safe(escape(user_input))

# BOM: Usar format_html para HTML com variáveis
from django.utils.html import format_html

def greet_user(username):
    return format_html('<span class="user">{}</span>', escape(username))

Cabeçalhos HTTP

# settings.py
SECURE_CONTENT_TYPE_NOSNIFF = True  # Prevenir MIME sniffing
SECURE_BROWSER_XSS_FILTER = True  # Habilitar filtro XSS
X_FRAME_OPTIONS = 'DENY'  # Prevenir clickjacking

# Middleware personalizado
from django.conf import settings

class SecurityHeaderMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        response['X-Content-Type-Options'] = 'nosniff'
        response['X-Frame-Options'] = 'DENY'
        response['X-XSS-Protection'] = '1; mode=block'
        response['Content-Security-Policy'] = "default-src 'self'"
        return response

Proteção CSRF

Proteção CSRF Padrão

# settings.py - CSRF é habilitado por padrão
CSRF_COOKIE_SECURE = True  # Enviar apenas via HTTPS
CSRF_COOKIE_HTTPONLY = True  # Prevenir acesso via JavaScript
CSRF_COOKIE_SAMESITE = 'Lax'  # Prevenir CSRF em alguns casos
CSRF_TRUSTED_ORIGINS = ['https://example.com']  # Domínios confiáveis

# Uso em template
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Enviar</button>
</form>

# Requisições AJAX
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

fetch('/api/endpoint/', {
    method: 'POST',
    headers: {
        'X-CSRFToken': getCookie('csrftoken'),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
});

Isentando Views (Use com Cuidado)

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt  # Use apenas quando absolutamente necessário!
def webhook_view(request):
    # Webhook de serviço externo
    pass

Segurança em Upload de Arquivos

Validação de Arquivos

import os
import magic  # pip install python-magic
from django.core.exceptions import ValidationError

ALLOWED_MIMES = {
    'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}

MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
}

def validate_file_type(value):
    """Valida o tipo de arquivo usando bytes mágicos e verifica extensão."""
    mime = magic.from_buffer(value.read(2048), mime=True)
    value.seek(0)

    if mime not in ALLOWED_MIMES:
        raise ValidationError('Tipo de arquivo não suportado.')

    ext = os.path.splitext(value.name)[1].lower()
    if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
        raise ValidationError('A extensão do arquivo não corresponde ao conteúdo.')

def validate_file_size(value):
    """Valida o tamanho do arquivo (máx. 5MB)."""
    if value.size > 5 * 1024 * 1024:
        raise ValidationError('Arquivo muito grande. O tamanho máximo é 5MB.')

# models.py
class Document(models.Model):
    file = models.FileField(
        upload_to='documents/',
        validators=[validate_file_type, validate_file_size]
    )

Para ambientes onde instalar libmagic é difícil (ex.: contêineres mínimos), use o pacote Python puro filetype como alternativa:

import os
from django.core.exceptions import ValidationError

import filetype  # pip install filetype

ALLOWED_MIMES = {
    'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}

MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
}

def validate_file_type(value):
    """Valida o tipo de arquivo usando bytes mágicos."""
    kind = filetype.guess(value.read(2048))
    value.seek(0)

    if kind is None or kind.mime not in ALLOWED_MIMES:
        raise ValidationError('Tipo de arquivo não suportado.')

    ext = os.path.splitext(value.name)[1].lower()
    if ext not in MIME_TO_EXTENSIONS.get(kind.mime, set()):
        raise ValidationError('A extensão do arquivo não corresponde ao conteúdo.')

Armazenamento Seguro de Arquivos

# settings.py
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'

# Use um domínio separado para mídia em produção
MEDIA_DOMAIN = 'https://media.example.com'

# Não sirva uploads de usuário diretamente
# Use whitenoise ou um CDN para arquivos estáticos
# Use um servidor separado ou S3 para arquivos de mídia

Segurança em API

Limitação de Taxa

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day',
        'upload': '10/hour',
    }
}

# Limitador personalizado
from rest_framework.throttling import UserRateThrottle

class BurstRateThrottle(UserRateThrottle):
    scope = 'burst'
    rate = '60/min'

class SustainedRateThrottle(UserRateThrottle):
    scope = 'sustained'
    rate = '1000/day'

Autenticação para APIs

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def secure_api_view(request):
    pass

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Habilidades Relacionadas