The speed of AI-assisted development comes with a familiar tradeoff. When you ask Claude, GitHub Copilot, or Cursor to scaffold an authentication system, the code appears in seconds. What also appears, quietly, are CORS configurations set to accept any origin, JWT secrets hardcoded in environment files committed to git, and database connections without parameterized queries.
The Thoughtworks team’s findings from building marketing applications reveal a pattern worth examining closely. Their solution centers on four mechanisms: security context files, careful permission management, daily intelligence feeds, and secure-by-default harnesses. The context file approach is the most immediately actionable.
What Goes in a Security Context File
A security context file sits in your project root, typically as .cursorrules, CLAUDE.md, or .github/copilot-instructions.md depending on your tool. The file guides the AI’s behavior for that specific codebase. The Thoughtworks approach structures these files around explicit constraints rather than general best practices.
Here’s what a minimal security context looks like for a Node.js API:
# Security Requirements
## Authentication
- Always use httpOnly cookies for session tokens
- JWT secrets must be loaded from process.env, never hardcoded
- Implement rate limiting on all auth endpoints (express-rate-limit, 5 requests per 15 minutes)
- Use bcrypt with cost factor 12 for password hashing
## Database
- All queries must use parameterized statements (pg library's $1, $2 syntax)
- Never construct SQL with string concatenation or template literals
- Connection strings must come from environment variables
## Dependencies
- Pin exact versions in package.json
- Run npm audit before suggesting new dependencies
- Prefer well-maintained packages (updates within 6 months, > 100k weekly downloads)
## CORS
- Origin must be an explicit whitelist from ALLOWED_ORIGINS env var
- credentials: true requires specific origin, not wildcard
The specificity matters. Saying “use parameterized queries” is less effective than “pg library’s $1, $2 syntax” because the AI can pattern-match against actual code. When Claude Sonnet 4.6 or GPT-4.1 generates a database query, it has concrete syntax to follow.
Permission Boundaries
AI coding assistants increasingly request file system access, shell execution, and network capabilities. The Thoughtworks team recommends a skeptical default posture. When an AI agent asks to install a package, the request should surface what’s being installed and why.
Cursor and Claude Code both implement permission models. Claude Code’s approach uses a settings.json file:
{
"allow": [
{"tool": "Read", "pattern": "src/**/*.ts"},
{"tool": "Write", "pattern": "src/**/*.ts"},
{"tool": "Bash", "command": "npm test"},
{"tool": "Bash", "command": "npm run build"}
],
"deny": [
{"tool": "Bash", "command": "npm install *"},
{"tool": "Write", "pattern": ".env*"}
]
}
This blocks the AI from installing arbitrary packages or modifying environment files without explicit approval. The pattern forces a decision point. When the AI needs to add a dependency, you see the package name, can check npm for recent vulnerabilities, and approve or reject.
The Intelligence Feed Problem
The “daily security intelligence feed” recommendation addresses a timing gap. AI models have knowledge cutoffs. Claude Sonnet 4.6 was trained on data through early 2025. A critical vulnerability in a popular library discovered in March 2026 won’t appear in its training data.
The Thoughtworks solution involves a feed of recent CVEs and security advisories that gets appended to the AI’s context. In practice, this could be a GitHub Action that runs daily:
name: Security Feed Update
on:
schedule:
- cron: '0 9 * * *'
jobs:
update-feed:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch CVEs for dependencies
run: |
npm audit --json > audit-results.json
node scripts/format-security-feed.js
- name: Update context file
run: |
cat SECURITY_FEED.md >> CLAUDE.md
- name: Commit if changed
run: |
git config user.name "Security Bot"
git add CLAUDE.md
git commit -m "Update security feed" || true
git push
The format-security-feed.js script converts npm audit output into natural language that the AI can parse. Instead of JSON, you get:
## Current Vulnerabilities (Updated 2026-05-27)
- axios < 1.7.8: SSRF vulnerability (CVE-2026-12345), upgrade to 1.7.8+
- express < 5.0.2: Prototype pollution (CVE-2026-23456), upgrade to 5.0.2+
When the AI suggests adding axios, it sees this context and will recommend version 1.7.8 or newer.
Secure-by-Default Harnesses
The harness concept provides known-good starting points. Rather than asking an AI to build an Express API from scratch, you maintain a template repository with security measures already configured.
A typical harness includes:
- Helmet.js configured with strict CSP headers
- CORS with environment-based origin whitelisting
- Rate limiting on all routes by default
- Request logging with PII filtering
- Error handling that doesn’t leak stack traces to clients
- Environment variable validation on startup (using something like envalid)
- Dependabot or Renovate configured for automated dependency updates
The AI starts from this baseline rather than making security decisions from first principles. You ask it to add a new endpoint, and it inherits the rate limiting and logging middleware already in place.
Where This Breaks Down
Context files have limits. They work well for policy enforcement (“always do X, never do Y”) but poorly for threat modeling. An AI won’t notice that your authentication flow is vulnerable to timing attacks unless you’ve explicitly documented timing attack prevention in your context file.
The permission model creates friction. Every package installation becomes a decision point. For exploratory prototyping, this friction has costs. The Thoughtworks team used this approach for production marketing tools, where the security bar justified the overhead. For throwaway experiments, the calculus differs.
The intelligence feed requires maintenance. Someone has to write the script that formats CVEs into AI-readable prose. The feed needs regular updates or it becomes stale, and a stale feed is worse than no feed because it creates false confidence.
Implementation Path
Start with a security context file. Even a 20-line file covering your most critical concerns (authentication, database queries, secrets management) provides value. Add to it when you notice the AI making specific mistakes.
Add permission constraints next if your tool supports them. Begin with denying writes to .env files and requiring approval for package installations. Expand from there based on what feels risky in your context.
Consider the intelligence feed and harness templates if you’re building production systems with AI assistance regularly. These have higher setup costs but pay off over time.
The broader lesson is that AI coding assistants are tools with predictable failure modes. They optimize for code that runs, not code that’s secure. The security layer has to come from somewhere else. Context files, permissions, and templates are three places to put it.