Skip to main content

Claude Code

Setup​

Place the security prompt content in a CLAUDE.md file at your repository root (or in .claude/CLAUDE.md). Claude Code reads this file at the start of every session.

# Copy the prompt for your framework
cp prompts/python/django/5.2/prompt.md CLAUDE.md

Or append to an existing CLAUDE.md:

echo "" >> CLAUDE.md
echo "# Security Rules" >> CLAUDE.md
cat prompts/python/django/5.2/prompt.md >> CLAUDE.md

CLAUDE.md holds a copy, so it doesn't change when a new prompt release arrives. Re-copy the prompt after each update.

Example: Secure Code Generation​

Request:

Write a Django login view that accepts username and password via POST.

Expected output (with security prompt active):

import json
import logging

from django.contrib.auth import authenticate, login
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.http import require_POST
from django_ratelimit.decorators import ratelimit

logger = logging.getLogger(__name__)

@require_POST
@csrf_protect
@ratelimit(key="ip", rate="5/m", block=True)
def login_view(request):
try:
data = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid request body"}, status=400)

username = data.get("username", "").strip()
password = data.get("password", "")

if not username or not password:
return JsonResponse({"error": "Username and password are required"}, status=400)

user = authenticate(request, username=username, password=password)

if user is not None:
login(request, user)
return JsonResponse({"status": "ok"})
else:
# Generic error message — do not reveal whether the username exists
logger.warning("Failed login attempt for username: %r", username)
return JsonResponse({"error": "Invalid credentials"}, status=401)

Security controls present in this output:

ControlWhat It Does
@require_POSTRejects non-POST requests
@csrf_protectValidates CSRF token
@ratelimitLimits login attempts per client IP
authenticate()Uses Django's built-in auth and password hashers
Generic error messageDoes not reveal whether the username exists
Logging of failed attemptsProvides an audit trail; %r escapes line breaks so a username can't forge log entries
No password echoPassword is never included in any response

Example: Insecure Output (Without Security Prompt)​

Without the security prompt, the same request may produce code like:

# INSECURE — for illustration only
from django.http import JsonResponse
from django.contrib.auth.models import User

def login(request):
username = request.POST.get("username")
password = request.POST.get("password")

try:
user = User.objects.get(username=username)
if user.check_password(password):
request.session["user_id"] = user.id
return JsonResponse({"status": "logged in"})
else:
return JsonResponse({"error": "Wrong password"}) # Reveals username exists
except User.DoesNotExist:
return JsonResponse({"error": "User not found"}) # Username enumeration

Security issues in this output:

IssueRisk
No CSRF protectionCross-site request forgery
No rate limiting considerationBrute-force attacks
Separate error messages for wrong password vs. user not foundUsername enumeration
No loggingNo audit trail
Manual session managementSession fixation risk
No HTTP method restrictionGET requests could trigger login

Directory-Level Prompts​

Claude Code supports hierarchical prompt files. Use this to apply different security prompts to different parts of your codebase:

project/
CLAUDE.md # General project rules
backend/
CLAUDE.md # Django 5.2 security prompt
frontend/
CLAUDE.md # React 19 security prompt
infrastructure/
CLAUDE.md # Terraform 1.16 security prompt

Claude Code reads the root CLAUDE.md at launch. It loads backend/CLAUDE.md once it reads or edits a file in backend/, and then applies both.

Tips​

  • Test the prompt with a security-sensitive request; see Quick Start
  • Keep prompts focused — A single framework-specific prompt performs better than a catch-all prompt covering multiple frameworks
  • Update prompts when you update models — If you switch Claude Code's model version, re-test your prompts against your key test cases