AppSec

Secure Coding Practices

Build Security Into Your Code

16 min read

Table of Contents
  1. Security Principles
  2. Input Validation
  3. Output Encoding
  4. Authentication & Sessions
  5. Cryptography
  6. Error Handling

Security Principles

Input Validation

SQL Injection Prevention

❌ Vulnerable
query = f"SELECT * FROM users WHERE id = {user_input}"
✅ Secure (Parameterized)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_input,))

XSS Prevention

❌ Vulnerable
<p>Hello, {{ user_name }}</p>
✅ Secure (Escaped)
<p>Hello, {{ user_name | escape }}</p>

Path Traversal Prevention

❌ Vulnerable
file_path = f"/uploads/{filename}"  # ../../../etc/passwd
✅ Secure
import os
safe_name = os.path.basename(filename)
file_path = os.path.join("/uploads", safe_name)

Output Encoding

HTML ContextHTML entity encoding
JavaScriptJavaScript encoding
URLURL/percent encoding
CSSCSS encoding
SQLParameterized queries

Authentication & Sessions

Password Storage

❌ Never
password_hash = md5(password)  # Weak!
password_hash = sha256(password)  # No salt!
✅ Correct
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())

Session Security

// Secure session cookie settings
app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
        secure: true,      // HTTPS only
        httpOnly: true,    // No JavaScript access
        sameSite: 'strict',// CSRF protection
        maxAge: 3600000    // 1 hour
    }
}));

Cryptography

Dos and Don'ts

Error Handling

❌ Leaks Information
except Exception as e:
    return f"Error: {str(e)}"  # Exposes stack trace!
✅ Generic Error
except Exception as e:
    logger.error(f"Database error: {e}")
    return "An error occurred. Please try again."

Updated: December 2024