Files
pos-system/.agent/rules/security.md

8.9 KiB

trigger
trigger
always_on

Security Patterns for GoodGo Microservices

When to Use This Skill

Use this skill when:

  • Implementing authentication and authorization in any service
  • Protecting sensitive data (PII, credentials, tokens)
  • Validating user inputs and file uploads
  • Implementing rate limiting and DDoS protection
  • Setting up audit logging and security monitoring
  • Encrypting data at rest and in transit
  • Managing secrets and credentials
  • Implementing security testing
  • Handling security incidents
  • Designing secure API endpoints

Core Security Principles

  1. Defense in Depth: Multiple layers of security controls
  2. Least Privilege: Grant minimum required permissions
  3. Fail Secure: Default to deny access
  4. Separation of Duties: Critical operations require multiple approvals
  5. Audit Everything: Log all security-relevant events
  6. Encrypt Sensitive Data: PII, tokens, credentials must be encrypted
  7. Validate All Inputs: Never trust user input
  8. Principle of Least Exposure: Minimize attack surface
  9. Secure by Default: Security built-in, not bolted on
  10. Assume Breach: Design for detection and response

Authentication & Authorization

JWT Token Validation

Extract tokens from Authorization header or cookies, verify with jwtService.verifyAccessToken(), and attach user payload to request. Return 401 for missing/invalid tokens.

// Key pattern - see references/REFERENCE.md for full implementation
const authHeader = req.headers.authorization;
const token = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : req.cookies?.access_token;
const payload = await jwtService.verifyAccessToken(token);
req.user = { id: payload.sub, roles: payload.roles || [], permissions: payload.permissions || [] };

Role-Based Authorization (RBAC)

Use requireRole() middleware for role checks and requirePermission() for fine-grained access control with resource:action format.

// Usage pattern
router.post('/api/v1/users', authenticate(), requirePermission('users', 'create'), userController.create);
router.delete('/api/v1/admin', authenticate(), requireRole('admin', 'superadmin'), adminController.delete);

Resource Ownership

Validate users can only access their own resources using requireOwnership() middleware.

Data Protection

Encryption

  • Use AES-256-GCM for encrypting PII at rest
  • Store encrypted data as iv:tag:ciphertext format
  • Require 32+ character ENCRYPTION_KEY

Password Hashing

  • Always use bcrypt with cost factor 12 in production
  • Never log passwords - sanitize before logging

Token Storage

  • Hash tokens with SHA-256 before database storage
  • Use crypto.randomBytes(32) for secure token generation

Input Validation

Zod Schema Validation

Always validate inputs with Zod schemas before processing:

const CreateUserDto = z.object({
  email: z.string().email(),
  password: z.string().min(8).regex(/[A-Z]/).regex(/[a-z]/).regex(/[0-9]/).regex(/[^A-Za-z0-9]/),
  phone: z.string().regex(/^\+[1-9]\d{1,14}$/).optional(),
  name: z.string().min(1).max(255)
});

// In controller
const dto = CreateUserDto.parse(req.body);

File Upload Validation

  • Check file size (max 10MB default)
  • Validate MIME type against whitelist
  • Verify content with file-type library to prevent MIME spoofing

SQL Injection Prevention

Always use Prisma parameterized queries - never string concatenation for queries.

Rate Limiting

Configure Redis-backed rate limiting for all endpoints:

Limiter Type Window Max Requests Use Case
Standard 15 min 100 General API endpoints
Strict 1 hour 10 Sensitive operations
Login 15 min 5 Authentication endpoints
router.post('/api/v1/auth/login', loginLimiter, authController.login);

Security Headers

Use Helmet middleware with CSP, HSTS, and additional headers:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Referrer-Policy: strict-origin-when-cross-origin

CORS Configuration

  • Whitelist allowed origins from environment variables
  • Enable credentials for authenticated requests
  • Set maxAge: 86400 (24 hours) for preflight caching

Secrets Management

  • Never hardcode secrets - use environment variables
  • Validate secrets with Zod schema at startup
  • Use secret managers in production (AWS Secrets Manager, Vault, etc.)
  • Rotate secrets quarterly
const secretsSchema = z.object({
  JWT_SECRET: z.string().min(32),
  DATABASE_URL: z.string().url(),
  ENCRYPTION_KEY: z.string().min(32).optional()
});

Audit Logging

Log all security-relevant events with sanitized details:

await auditService.logSecurityEvent('LOGIN_SUCCESS', user.id, { email: user.email }, req);
await auditService.logSecurityEvent('PERMISSION_DENIED', user.id, { resource, action }, req);

Sanitize sensitive fields: password, token, secret, ssn, creditCard.

Error Handling

  • Log full errors internally
  • Never expose user existence (use generic "Invalid credentials")
  • Show stack traces only in development
  • Return sanitized error codes in production

Security Testing

Write tests for:

  • SQL injection prevention
  • XSS attack prevention
  • Authentication enforcement
  • Authorization enforcement
  • Rate limiting effectiveness

Best Practices

  • All endpoints require authentication (except public)
  • Authorization checks at every protected route
  • Input validation with Zod on all user input
  • Rate limiting on all endpoints
  • Error messages sanitized in production
  • PII encrypted at rest with AES-256-GCM
  • Passwords hashed with bcrypt (cost 12+)
  • Tokens hashed before database storage
  • HTTPS enforced (TLS 1.2+)
  • Security headers via Helmet
  • Audit logging for security events
  • Dependencies scanned for vulnerabilities
  • File uploads validated (size, type, content)

Common Mistakes

1. Weak Password Hashing

// BAD: Low cost factor
const hash = await bcrypt.hash(password, 8);

// GOOD: Use cost 12
const hash = await bcrypt.hash(password, 12);

2. Hardcoded Secrets

// BAD
const JWT_SECRET = "my-secret-key";

// GOOD
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) throw new Error('JWT_SECRET required');

3. Missing Input Validation

// BAD
const user = await prisma.user.findUnique({ where: { id: req.params.id } });

// GOOD
const { id } = z.object({ id: z.string().cuid() }).parse(req.params);
const user = await prisma.user.findUnique({ where: { id } });

4. Logging Sensitive Data

// BAD
logger.info('User login', { email, password });

// GOOD
logger.info('User login', { email, password: '[REDACTED]' });

5. Exposing User Existence

// BAD
if (!user) throw new Error('User not found');

// GOOD
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
  throw new Error('Invalid credentials');
}

Quick Reference

Security Area Implementation
Password hashing bcrypt.hash(password, 12)
JWT Access Token 15 minutes expiry
JWT Refresh Token 7 days expiry
Rate limiting Standard: 100/15min, Strict: 10/hour, Login: 5/15min
Encryption AES-256-GCM for PII
Input validation Zod schemas, always parse before use
SQL injection Use Prisma (parameterized by default)
Security headers helmet middleware
CORS Whitelist origins, credentials: true

Essential Imports:

import bcrypt from 'bcrypt';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { z } from 'zod';
import { jwtService } from '@goodgo/auth-sdk';

Security Checklist

Before deploying any service:

  • All endpoints require authentication (except public)
  • Authorization checks implemented (RBAC/ABAC)
  • Input validation with Zod schemas
  • Rate limiting configured
  • Error messages sanitized (no info disclosure)
  • PII encrypted at rest
  • Passwords hashed with bcrypt (cost 12+)
  • Tokens hashed before storing
  • Secrets in environment variables (never hardcoded)
  • HTTPS enforced (TLS 1.2+)
  • CORS configured correctly
  • Security headers set (helmet)
  • Audit logging enabled
  • SQL injection prevented (use Prisma)
  • XSS prevention (input sanitization)
  • File upload validation
  • Security tests passing
  • Dependencies scanned for vulnerabilities
  • Secrets rotation plan in place

Resources