.cursorrules (deprecated)
rules/security-best-practices/.cursorrules.cursorrules
Quality
80/100
Scores the file, not the repository.Length
1,179 words
28 headings · 7 code blocksRepository
16
— · pushed 109 days agoLast changed
2 days ago
First indexed 2 days ago.1# Security Best Practices — Cursor Rules2# Comprehensive rules for writing secure application code34## Project Context5You are working on an application where security is a top priority. The codebase must6protect against common vulnerabilities (OWASP Top 10), handle sensitive data carefully,7and follow the principle of least privilege. Every code change should be evaluated for8security implications.910## Core Principles11- Defense in depth — multiple layers of security12- Principle of least privilege — grant minimum necessary access13- Fail securely — errors should not expose sensitive information14- Never trust user input — validate and sanitize everything15- Secure by default — security should not require extra configuration1617## Input Validation1819### Rules20- Validate ALL input on the server side, regardless of client-side validation21- Use allowlists (valid values) over denylists (blocked values)22- Validate type, length, range, and format23- Use established validation libraries (Zod, Joi, Pydantic)24- Reject invalid input — don't try to clean or fix it2526### Patterns27```ts28// GOOD — strict validation with Zod29const createUserSchema = z.object({30 email: z.string().email().max(255),31 name: z.string().min(1).max(100).regex(/^[a-zA-Z\s'-]+$/),32 age: z.number().int().min(13).max(150),33 role: z.enum(['user', 'editor']), // Allowlist, not freeform string34});3536// BAD — trusting input37app.post('/users', (req, res) => {38 db.query(`INSERT INTO users (name) VALUES ('${req.body.name}')`); // SQL injection!39});40```4142## SQL Injection Prevention4344### ALWAYS Use Parameterized Queries45```ts46// GOOD — parameterized47const user = await db.query('SELECT * FROM users WHERE email = $1', [email]);4849// GOOD — ORM (Prisma handles parameterization)50const user = await prisma.user.findUnique({ where: { email } });5152// BAD — string concatenation53const user = await db.query(`SELECT * FROM users WHERE email = '${email}'`);5455// BAD — template literals56const user = await db.query(`SELECT * FROM users WHERE email = '${req.body.email}'`);57```5859### Rules60- Never concatenate user input into SQL strings61- Use ORM query builders or parameterized queries exclusively62- Validate and type-check input before passing to queries63- Use stored procedures for complex operations64- Limit database user permissions to only required operations6566## Cross-Site Scripting (XSS) Prevention6768### Rules69- Escape all user-generated content before rendering in HTML70- Use framework auto-escaping (React JSX, Vue templates escape by default)71- Never use `dangerouslySetInnerHTML` (React) or `v-html` (Vue) with user content72- Set `Content-Security-Policy` headers to restrict script sources73- Sanitize HTML if rich text is required (use DOMPurify)7475```tsx76// SAFE — React auto-escapes77<p>{userInput}</p>7879// DANGEROUS — raw HTML injection80<div dangerouslySetInnerHTML={{ __html: userInput }} />8182// If you must render HTML, sanitize first83import DOMPurify from 'dompurify';84<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />85```8687### Content Security Policy88```89Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none';90```9192## Authentication9394### Password Handling95- Hash passwords with bcrypt (cost factor 12+) or Argon2id96- Never store plain-text passwords97- Never log passwords, even in error messages98- Enforce minimum password length (8+ characters)99- Check passwords against breached password databases (Have I Been Pwned API)100- Implement account lockout after failed attempts (5 attempts, 15-minute lockout)101102```ts103import bcrypt from 'bcrypt';104105// Hashing106const SALT_ROUNDS = 12;107const passwordHash = await bcrypt.hash(password, SALT_ROUNDS);108109// Verification (constant-time comparison built in)110const isValid = await bcrypt.compare(inputPassword, storedHash);111```112113### JWT Best Practices114- Use short expiry times (15 minutes for access tokens)115- Use refresh tokens (stored in httpOnly cookies) for session extension116- Include minimal claims — don't put sensitive data in JWTs117- Validate `iss`, `aud`, and `exp` claims on every request118- Use RS256 (asymmetric) for distributed systems, HS256 for single-service119- Store the signing secret in environment variables, never in code120- Implement token revocation (blacklist or versioned tokens)121122### Session Security123- Use httpOnly, Secure, SameSite=Strict cookies for session tokens124- Regenerate session ID after login (prevent session fixation)125- Set appropriate session timeout (idle and absolute)126- Invalidate sessions on password change and logout127128## Authorization129130### Rules131- Check authorization on EVERY request, not just the UI layer132- Verify resource ownership — don't just check authentication133- Use role-based access control (RBAC) or attribute-based (ABAC)134- Implement authorization in middleware, not scattered through handlers135- Log authorization failures for security monitoring136137```ts138// GOOD — check ownership139async function getOrder(req, res) {140 const order = await Order.findById(req.params.id);141 if (!order) return res.status(404).json({ error: 'Not found' });142 if (order.userId !== req.user.id && req.user.role !== 'admin') {143 return res.status(403).json({ error: 'Forbidden' });144 }145 res.json(order);146}147148// BAD — only checks authentication, not authorization149async function getOrder(req, res) {150 const order = await Order.findById(req.params.id);151 res.json(order); // Any authenticated user can access any order!152}153```154155## Sensitive Data Handling156157### Environment Variables and Secrets158- Never commit secrets to version control159- Use `.env` files for local development, secret managers for production160- Add `.env` to `.gitignore`161- Rotate secrets regularly162- Use different secrets per environment (dev, staging, production)163164### Data at Rest165- Encrypt sensitive data in the database (PII, financial data)166- Use database-level encryption (TDE) or application-level encryption167- Hash data that only needs verification (passwords, API keys)168- Mask sensitive data in logs: `email: a****@example.com`169170### Data in Transit171- Use HTTPS everywhere — no exceptions172- Use TLS 1.2+ for all service-to-service communication173- Validate SSL certificates — don't disable verification174- Use HSTS headers to enforce HTTPS175176## HTTP Security Headers177```ts178// Use helmet.js (Express) or set manually179app.use(helmet());180181// Or set individually:182// Prevent clickjacking183res.setHeader('X-Frame-Options', 'DENY');184// Prevent MIME sniffing185res.setHeader('X-Content-Type-Options', 'nosniff');186// Control referrer information187res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');188// Enforce HTTPS189res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');190// Control permissions191res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');192```193194## Rate Limiting195- Implement rate limiting on all public endpoints196- Stricter limits on authentication endpoints (login, password reset)197- Use sliding window or token bucket algorithms198- Return `429 Too Many Requests` with `Retry-After` header199- Consider per-user and per-IP rate limits200201## Logging and Monitoring202- Log all authentication events (login, logout, failures)203- Log authorization failures204- Log input validation failures (potential attack probing)205- Never log passwords, tokens, credit card numbers, or full SSN206- Include request ID, user ID, IP address, and timestamp in logs207- Set up alerts for anomalous patterns (brute force, unusual access)208209## Dependency Security210- Keep dependencies updated — check for known vulnerabilities211- Run `npm audit` / `pip audit` regularly212- Use lockfiles (`package-lock.json`, `poetry.lock`) for reproducible builds213- Review new dependencies before adding (check maintenance, popularity, security record)214- Pin major versions to avoid unexpected breaking changes215216## Common Pitfalls217- Trusting client-side validation as the only validation218- Using MD5 or SHA256 for password hashing (use bcrypt/Argon2)219- Storing secrets in code or version control220- Returning detailed error messages in production (stack traces, SQL errors)221- Not implementing rate limiting on authentication endpoints222- Using `*` for CORS origins in production223- Not checking resource ownership after authentication224- Logging sensitive data (passwords, tokens, PII)225- Using outdated dependencies with known vulnerabilities226- Disabling HTTPS or SSL verification for "convenience"227
Also in survivorforge/cursor-rules
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/clean-code/.cursorrules · 16 | .cursorrules | styledo-notagent-behaviourdocs | 57/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 16 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-production/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+3 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/golang-api/.cursorrules · 16 | .cursorrules | buildteststylearch+6 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mcp-server/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+7 | 68/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 89/100 | 2 days ago |
Diff against rules/ai-ml-python/.cursorrules Diff against rules/api-design-rest/.cursorrules Diff against rules/api-microservices/.cursorrules Diff against rules/aws-serverless/.cursorrules Diff against rules/chrome-extension/.cursorrules Diff against rules/clean-code/.cursorrules Diff against rules/database-sql/.cursorrules Diff against rules/devops-docker/.cursorrules Diff against rules/devops-infrastructure/.cursorrules Diff against rules/django-rest/.cursorrules Diff against rules/docker-devops/.cursorrules Diff against rules/flutter-dart/.cursorrules Diff against rules/fullstack-nextjs-prisma/.cursorrules Diff against rules/go-gin/.cursorrules Diff against rules/go-production/.cursorrules Diff against rules/golang-api/.cursorrules Diff against rules/langchain-ai/.cursorrules Diff against rules/mcp-server/.cursorrules Diff against rules/mern-stack/.cursorrules Diff against rules/mobile-react-native/.cursorrules
