Docs
21.2-Secure-Coding
21.2 Secure Coding Practices
Overview
Secure coding is about writing code that is resistant to attacks by design. This section covers techniques for input validation, output encoding, and secure handling of sensitive data.
Input Validation Principles
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Input Validation Pyramid β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββ β
β β Business β β Business rules validation β
β β Logic β β
β βββββββββ¬ββββββββ β
β ββββββββββββββ΄βββββββββββββ β
β β Semantic β β Value range, format β
β β Validation β β
β ββββββββββββββ¬βββββββββββββ β
β βββββββββββββββββββββββ΄ββββββββββββββββββββββ β
β β Syntactic Validation β β Type, length β
β βββββββββββββββββββββββ¬ββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββ β
β β Sanitization Layer β β Clean β
β β (trim, normalize, encode) β input β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Validation Strategies
Whitelist vs Blacklist
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Whitelist vs Blacklist Validation β
βββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ€
β Whitelist (Recommended) β Blacklist (Avoid) β
βββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ€
β β Explicitly allow known good β β Try to block known bad β
β β Secure by default β β Insecure by default β
β β Easy to maintain β β Constantly needs updating β
β β Handles unknown attacks β β New attacks bypass filters β
βββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ€
β Example: β Example: β
β const allowed = ['jpg', 'png']; β const blocked = ['exe', 'js']; β
β if (allowed.includes(ext)) β if (!blocked.includes(ext)) β
βββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββ
Input Validation Patterns
// β Blacklist approach - can be bypassed
function validateBlacklist(input) {
const dangerous = ['<script>', 'javascript:', 'onerror'];
return !dangerous.some((d) => input.includes(d));
}
// β Whitelist approach - only allow known good
function validateWhitelist(input, pattern) {
return pattern.test(input);
}
// β Schema validation - define exactly what's allowed
const userSchema = {
username: {
type: 'string',
pattern: /^[a-zA-Z0-9_]{3,20}$/,
required: true,
},
email: {
type: 'string',
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
required: true,
},
age: {
type: 'number',
min: 13,
max: 120,
},
};
Output Encoding
Context-Specific Encoding
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Context-Specific Encoding β
ββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Context β Encoding Required β
ββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β HTML Body β HTML Entity encoding (< > &) β
β HTML Attribute β HTML Attribute encoding + quote escape β
β JavaScript β JavaScript Unicode encoding (\uXXXX) β
β CSS β CSS escape sequences (\XX) β
β URL β URL encoding (%XX) β
β JSON β Proper JSON encoding + context encoding β
ββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// Different encoding for different contexts
const encoders = {
// HTML body context
html: (str) =>
str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'),
// HTML attribute context
htmlAttr: (str) =>
str
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>'),
// JavaScript string context
js: (str) =>
str
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r'),
// URL component
url: (str) => encodeURIComponent(str),
};
Secure Data Handling
Sensitive Data Flow
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Sensitive Data Lifecycle β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Collection Processing Storage Disposal β
β βββββββββββ βββββββββββ βββββββββββ βββββββββββ β
β β HTTPS βββββββββΊβ Memory ββββββββΊβEncryptedβββββββΊβ Secure β β
β β Only β β Only β β Storage β β Delete β β
β β β β No Logs β β β β β β
β βββββββββββ βββββββββββ βββββββββββ βββββββββββ β
β β β β β β
β βΌ βΌ βΌ βΌ β
β Validate Process Hash/Encrypt Zero Memory β
β Sanitize In Memory Key Management Delete Files β
β Minimize No Temp Files Access Control Clear Backups β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Password Handling
Secure Password Requirements
// Password security checklist
const passwordRequirements = {
minLength: 12, // Minimum 12 characters
maxLength: 128, // Reasonable maximum
requireUppercase: true, // At least one uppercase
requireLowercase: true, // At least one lowercase
requireNumbers: true, // At least one number
requireSpecial: true, // At least one special char
preventCommon: true, // Check against common passwords
preventUsername: true, // Can't contain username
preventReuse: 5, // Can't reuse last 5 passwords
};
// Never do this
const bad = {
storeInPlainText: true, // β
sendInEmail: true, // β
logPasswords: true, // β
useReversibleEncryption: true, // β
useMD5orSHA1: true, // β
};
// Always do this
const good = {
useModernHash: 'bcrypt/argon2', // β
useSalt: true, // β (automatic with bcrypt)
useHTTPS: true, // β
rateLimit: true, // β
implementLockout: true, // β
};
Error Handling Security
Secure Error Messages
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Error Message Security β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Development β β
β β Detailed errors Stack traces β β
β β Variable contents File paths β β
β β SQL queries Internal architecture β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Production β β
β β Generic messages only "An error occurred" β β
β β Log details server-side Use error IDs β β
β β Never expose internals Sanitize before display β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β Dangerous - reveals internal information
catch (error) {
return res.status(500).json({
error: error.message,
stack: error.stack,
query: sql.query
});
}
// β Secure - log internally, return generic message
catch (error) {
const errorId = generateErrorId();
logger.error({ errorId, error, userId });
return res.status(500).json({
error: 'An unexpected error occurred',
errorId: errorId
});
}
Secure Configuration
Environment-Based Configuration
// Configuration security patterns
const config = {
// β Use environment variables
dbPassword: process.env.DB_PASSWORD,
// β Different settings per environment
debug: process.env.NODE_ENV !== 'production',
// β Secure defaults
sessionTimeout: parseInt(process.env.SESSION_TIMEOUT) || 3600,
// β Validate configuration
validate() {
if (!this.dbPassword) {
throw new Error('DB_PASSWORD must be set');
}
},
};
// Never hardcode secrets
const NEVER = {
apiKey: 'sk_live_1234567890', // β
dbPassword: 'password123', // β
jwtSecret: 'mysecret', // β
};
Secure Communication
API Security
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Security Layers β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Layer 1: Transport β
β βββ HTTPS/TLS only β
β βββ Strong cipher suites β
β βββ Certificate validation β
β β
β Layer 2: Authentication β
β βββ API keys or tokens β
β βββ JWT with proper validation β
β βββ OAuth 2.0 for third-party β
β β
β Layer 3: Authorization β
β βββ Role-based access control β
β βββ Resource-level permissions β
β βββ Principle of least privilege β
β β
β Layer 4: Input Validation β
β βββ Schema validation β
β βββ Type checking β
β βββ Size limits β
β β
β Layer 5: Rate Limiting β
β βββ Per-user limits β
β βββ Per-endpoint limits β
β βββ Burst protection β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Dependency Security
Managing Third-Party Dependencies
// Security practices for dependencies
const dependencyPractices = {
// Audit regularly
audit: 'npm audit',
// Use lockfiles
lockfile: 'package-lock.json',
// Pin versions or use ranges carefully
versioning: {
pinned: '1.2.3', // Exact version
patch: '~1.2.3', // Patch updates only
minor: '^1.2.3', // Minor updates only
},
// Review before installing
review: [
'Check npm/GitHub for maintenance',
'Review source code for red flags',
'Check download counts and community',
'Verify package authenticity',
],
};
Security Checklist
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Secure Coding Checklist β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Input Handling: β
β β‘ Validate all input on server side β
β β‘ Use whitelist validation β
β β‘ Sanitize before processing β
β β‘ Set maximum input lengths β
β β
β Output Handling: β
β β‘ Encode output based on context β
β β‘ Use templating engines with auto-escaping β
β β‘ Set proper Content-Type headers β
β β
β Authentication: β
β β‘ Use strong password hashing (bcrypt/argon2) β
β β‘ Implement account lockout β
β β‘ Secure password reset flows β
β β‘ Use MFA where appropriate β
β β
β Session Management: β
β β‘ Use secure, HttpOnly cookies β
β β‘ Regenerate session ID on login β
β β‘ Implement session timeout β
β β
β Error Handling: β
β β‘ Log errors server-side β
β β‘ Return generic error messages β
β β‘ Don't expose stack traces β
β β
β Data Protection: β
β β‘ Encrypt sensitive data at rest β
β β‘ Use HTTPS for all traffic β
β β‘ Minimize data collection β
β β‘ Implement proper access controls β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Takeaways
- β’Validate all input - Never trust user input
- β’Encode all output - Context-aware encoding is essential
- β’Use strong cryptography - Modern algorithms, proper key management
- β’Secure by default - Fail closed, not open
- β’Minimize attack surface - Less code, fewer endpoints
- β’Defense in depth - Multiple security layers
- β’Keep secrets secret - Proper configuration management
Files in This Section
- β’
README.md- This documentation - β’
examples.js- Secure coding pattern examples - β’
exercises.js- Security implementation exercises