The Ultimate App Security Cheatsheet: Best Practices for Secure Development

Introduction

Application security encompasses the measures, practices, and tools implemented to protect software applications from threats throughout their lifecycle. As cyber threats continue to evolve in sophistication, securing applications has become a critical priority for organizations. This cheatsheet provides a comprehensive guide to app security best practices for developers, security teams, and organizations to build and maintain secure applications in today’s threat landscape.

Core Security Principles

Defense in Depth

Implement multiple layers of security controls throughout your application:

  • Input validation at client side
  • Server-side validation
  • API gateways
  • Web Application Firewalls (WAF)
  • Runtime Application Self-Protection (RASP)
  • Database security controls

Principle of Least Privilege

LayerImplementation
CodeMinimize the scope of variables and functions
ApplicationUse role-based access control (RBAC)
DatabaseCreate specific database users with minimal permissions
InfrastructureUse service accounts with limited scope
APIImplement granular API permissions

Secure by Default

  • Start with restrictive configurations
  • Require explicit opt-in for risky features
  • Disable unnecessary services and components
  • Use secure defaults for all configurable security parameters
  • Make secure choices the path of least resistance

Trust Nothing (Zero Trust)

  • Verify every request regardless of source
  • Authenticate and authorize all users and services
  • Validate all data inputs
  • Apply least privilege consistently
  • Enforce access controls at each layer

Secure Coding Practices

Input Validation

Validation TypeDescriptionExample (JavaScript)
Whitelist/Allow listAccept only known good inputsconst validStatus = ['active', 'pending', 'closed']; if (!validStatus.includes(status)) { throw new Error('Invalid status'); }
Type checkingEnsure inputs are of expected typesif (typeof userId !== 'number') { throw new Error('User ID must be a number'); }
Length/Range checksVerify inputs are within acceptable limits`if (password.length < 8
Format validationCheck inputs match expected patternsif (!/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(email)) { throw new Error('Invalid email format'); }
Context-specific validationValidate based on business rulesif (userAge < 18 && accountType === 'adult') { throw new Error('Must be 18+ for this account type'); }

Output Encoding

ContextEncoding MethodExample
HTMLHTML entity encodingfunction encodeHTML(text) { return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;'); }
JavaScriptJavaScript escapingfunction escapeJS(text) { return JSON.stringify(text).slice(1, -1); }
URLURL encodingencodeURIComponent(data)
SQLParameterized queriesdb.query('SELECT * FROM users WHERE id = ?', [userId])
XMLXML encodingfunction encodeXML(text) { return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;'); }

Common Vulnerabilities Prevention

SQL Injection Prevention

Do:

  • Use parameterized queries or prepared statements
    // Node.js with MySQLconnection.query('SELECT * FROM users WHERE id = ?', [userId]);// Java with JDBCPreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE id = ?");stmt.setInt(1, userId);ResultSet rs = stmt.executeQuery();
    
  • Use ORMs with security features
    // Sequelize (Node.js)User.findByPk(userId);
    

Don’t:

  • Concatenate strings to build SQL queries
    // VULNERABLE - DON'T DO THISconst query = "SELECT * FROM users WHERE id = '" + userId + "'";
    

Cross-Site Scripting (XSS) Prevention

Do:

  • Encode HTML output based on context
  • Implement Content Security Policy (CSP)
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    
  • Use modern frameworks with automatic escaping
    // React automatically escapes valuesreturn <div>{userProvidedText}</div>;
    

Don’t:

  • Insert raw user input into HTML
    // VULNERABLE - DON'T DO THISelement.innerHTML = userInput;
    
  • Use dangerous JavaScript functions with user input
    // VULNERABLE - DON'T DO THISeval(userInput);document.write(userInput);
    

CSRF (Cross-Site Request Forgery) Prevention

Do:

  • Use anti-CSRF tokens
    <form action="/transfer" method="post">  <input type="hidden" name="_csrf" value="random-token-here">  <!-- other form fields --></form>
    
  • Validate Origin/Referer headers
  • Implement SameSite cookie attribute
    Set-Cookie: sessionid=abc123; SameSite=Strict; Secure; HttpOnly
    

Don’t:

  • Rely solely on cookies for authentication
  • Allow state-changing operations via GET requests

Server-Side Request Forgery (SSRF) Prevention

Do:

  • Validate and sanitize URLs
  • Use allow lists for domains/IP ranges
  • Implement network-level blocks

Don’t:

  • Allow requests to internal resources
  • Blindly follow redirects

Authentication & Authorization

Authentication Best Practices

PracticeImplementation
Multi-factor Authentication (MFA)Require at least two verification factors:<br>- Something you know (password)<br>- Something you have (phone/token)<br>- Something you are (biometrics)
Password Policies– Minimum length (12+ characters)<br>- Complexity requirements<br>- Check against compromised passwords<br>- Regular password rotation for sensitive systems
Secure Credential Storage– Use strong, adaptive hashing algorithms (bcrypt, Argon2)<br>- Salt passwords<br>- Never store plaintext credentials
Account Lockout– Implement temporary lockouts after failed attempts<br>- Use exponential backoff for retry delays<br>- Alert on suspicious authentication patterns
Session Management– Generate strong session IDs<br>- Implement idle and absolute timeouts<br>- Invalidate sessions after password changes<br>- Allow users to view and terminate active sessions

Secure Password Hashing Examples

// Node.js with bcrypt
const bcrypt = require('bcrypt');
const saltRounds = 12;

// Hashing
const hashedPassword = await bcrypt.hash(password, saltRounds);

// Verification
const isMatch = await bcrypt.compare(password, hashedPassword);
# Python with Argon2
from argon2 import PasswordHasher

ph = PasswordHasher()

# Hashing
hash = ph.hash(password)

# Verification
try:
    ph.verify(hash, password)
    # Password is correct
except:
    # Password is incorrect

Authorization Best Practices

Role-Based Access Control (RBAC)

// Define roles and permissions
const roles = {
  admin: ['read', 'write', 'delete', 'manage_users'],
  editor: ['read', 'write'],
  viewer: ['read']
};

// Check permission
function hasPermission(user, permission) {
  const userRole = user.role;
  return roles[userRole] && roles[userRole].includes(permission);
}

// Use in routes/controllers
function deleteResource(user, resourceId) {
  if (!hasPermission(user, 'delete')) {
    throw new Error('Unauthorized');
  }
  // Proceed with deletion
}

Attribute-Based Access Control (ABAC)

// More complex policy check
function canAccessResource(user, resource, action) {
  // Resource ownership check
  if (resource.ownerId === user.id) {
    return true;
  }
  
  // Department-based check
  if (user.department === resource.department && hasPermission(user, action)) {
    return true;
  }
  
  // Time-based restriction
  const currentHour = new Date().getHours();
  if (currentHour < 9 || currentHour > 17) {
    return false;
  }
  
  return false;
}

OAuth 2.0 & OpenID Connect

Grant TypeUse CaseSecurity Considerations
Authorization CodeWeb applications– Use PKCE for public clients<br>- Validate redirect URIs
ImplicitLegacy browser-based apps– Being deprecated<br>- Use Authorization Code with PKCE instead
Client CredentialsService-to-service– Securely store client secret<br>- Limit scope
Resource Owner PasswordLegacy/migration– Avoid if possible<br>- Limit to first-party apps
Device CodeLimited input devices– Short verification codes<br>- Limited lifetime tokens

Secure Data Handling

Data Classification

ClassificationExamplesProtection Measures
PublicMarketing materials, public APIsBasic integrity controls
InternalEmployee directory, internal docsAccess controls, basic encryption
ConfidentialCustomer data, business plansStrong encryption, strict access controls
RestrictedPasswords, payment data, PIIHighest security, encryption at rest and in transit, audit trails

Encryption Best Practices

TypeImplementationExamples
Encryption at Rest– Encrypt databases, file systems<br>- Secure key management<br>- Consider hardware security modules (HSMs)– Transparent Data Encryption (TDE)<br>- File system encryption<br>- Encrypted backups
Encryption in Transit– TLS 1.2+ for all connections<br>- Strong cipher preferences<br>- Certificate validation– HTTPS everywhere<br>- TLS for database connections<br>- API encryption
End-to-End Encryption– Encrypt data at the source<br>- Decrypt only at intended destination– Signal Protocol<br>- PGP<br>- Customer-managed keys

Encryption Code Examples

// Node.js symmetric encryption with AES
const crypto = require('crypto');

function encrypt(text, key) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
  
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  
  const authTag = cipher.getAuthTag().toString('hex');
  
  // Return IV + Auth Tag + Encrypted Data
  return iv.toString('hex') + authTag + encrypted;
}

function decrypt(encryptedData, key) {
  const iv = Buffer.from(encryptedData.substring(0, 32), 'hex');
  const authTag = Buffer.from(encryptedData.substring(32, 64), 'hex');
  const encryptedText = encryptedData.substring(64);
  
  const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
  decipher.setAuthTag(authTag);
  
  let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}

Secure Key Management

  • Use key management services (KMS) provided by cloud providers
  • Implement key rotation policies
  • Separate storage for keys and encrypted data
  • Use hardware security modules for critical keys
  • Follow the principle of least privilege for key access

API Security

API Security Checklist

CategoryBest Practices
Authentication– Use OAuth 2.0 or API keys<br>- Implement token-based auth<br>- Consider certificate-based authentication for service-to-service
Authorization– Implement granular permissions<br>- Validate authority for each request<br>- Use scopes to limit token permissions
Rate Limiting– Set request rate thresholds<br>- Implement graduated response (delay → block)<br>- Use token bucket or leaky bucket algorithms
Input Validation– Validate request parameters and body<br>- Implement schema validation<br>- Sanitize all inputs
Output Control– Use clear error messages without sensitive details<br>- Implement response filtering/sanitization<br>- Apply output-specific encoding

REST API Security Headers

HeaderPurposeExample
AuthorizationProvide credentialsAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5...
Content-TypeSpecify request/response formatContent-Type: application/json
X-Content-Type-OptionsPrevent MIME-sniffingX-Content-Type-Options: nosniff
Strict-Transport-SecurityEnforce HTTPSStrict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-OptionsPrevent clickjackingX-Frame-Options: DENY
Cache-ControlControl caching behaviorCache-Control: no-store, max-age=0
X-Rate-LimitCommunicate rate limitsX-Rate-Limit-Limit: 100

GraphQL Security

  • Implement depth limiting to prevent nested query attacks
  • Use query cost analysis for complexity-based throttling
  • Leverage persisted queries for production environments
  • Apply field-level authorization
  • Avoid exposing error details that reveal schema information
// Apollo Server with depth limiting
const server = new ApolloServer({
  typeDefs,
  resolvers,
  validationRules: [
    depthLimit(5), // Limit query depth
    costAnalysis({
      maximumCost: 1000,
      variables: {},
      defaultCost: 1,
    }),
  ],
});

Mobile App Security

Android Security Best Practices

AreaRecommendations
Data Storage– Use Android Keystore for keys and credentials<br>- Implement file-level encryption<br>- Avoid storing sensitive data in SharedPreferences<br>- Securely delete temporary files
Network Communication– Implement certificate pinning<br>- Enforce TLS 1.2+<br>- Verify server certificates<br>- Detect and prevent proxy usage for sensitive operations
Authentication– Support biometric authentication<br>- Implement secure device attestation<br>- Use OAuth 2.0 with PKCE for API auth<br>- Implement app-level MFA
Code Protection– Obfuscate code with ProGuard/R8<br>- Implement anti-tamper checks<br>- Detect rooted devices<br>- Apply string encryption for sensitive values
WebView Security– Disable JavaScript if not needed<br>- Avoid addJavascriptInterface for Android < 4.2<br>- Verify URLs before loading<br>- Handle file access securely

Android Certificate Pinning Example

// OkHttp Certificate Pinning
val client = OkHttpClient.Builder()
    .certificatePinner(
        CertificatePinner.Builder()
            .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
            .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
            .build()
    )
    .build()

iOS Security Best Practices

AreaRecommendations
Data Storage– Use Keychain for sensitive data<br>- Implement Data Protection API (NSFileProtection)<br>- Avoid storing secrets in NSUserDefaults<br>- Use secure coding for serialization
Network Communication– Implement App Transport Security (ATS)<br>- Use certificate pinning<br>- Validate server certificates<br>- Protect against MITM attacks
Authentication– Leverage Face ID/Touch ID<br>- Implement secure device check<br>- Use secure enclave for biometric auth<br>- Support app-level MFA
Code Protection– Implement jailbreak detection<br>- Add runtime integrity checks<br>- Use code signing<br>- Apply binary obfuscation techniques
Privacy– Request minimum permissions<br>- Provide clear privacy descriptions<br>- Implement proper data deletion<br>- Support privacy management

iOS Keychain Usage Example

// Save to Keychain
func saveToKeychain(key: String, data: Data) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    
    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    return status == errSecSuccess
}

// Retrieve from Keychain
func loadFromKeychain(key: String) -> Data? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne
    ]
    
    var dataTypeRef: AnyObject?
    let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
    
    if status == errSecSuccess {
        return dataTypeRef as? Data
    } else {
        return nil
    }
}

Cloud & Infrastructure Security

Container Security

PhasePracticeImplementation
BuildMinimize image size– Use minimal base images (Alpine, distroless)<br>- Multi-stage builds<br>- Remove development tools
BuildScan images– Use tools like Trivy, Clair, Snyk<br>- Block images with critical CVEs<br>- Automate scanning in CI/CD
DeployUse immutable containers– Never modify running containers<br>- Redeploy for updates<br>- Use SHA-specific image references
RuntimeApply least privilege– Non-root users<br>- Read-only file systems<br>- Minimal capabilities
RuntimeImplement network policies– Pod-to-pod communication restrictions<br>- Default deny rules<br>- Use service meshes for mTLS

Docker Security Example

# Multi-stage build for minimal attack surface
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production image with minimal footprint
FROM node:18-alpine
RUN apk --no-cache add dumb-init
ENV NODE_ENV production
WORKDIR /app
COPY --from=build /app/dist /app/dist
COPY --from=build /app/node_modules /app/node_modules

# Create non-root user
RUN addgroup -g 1001 nodejs && adduser -u 1001 -G nodejs -s /bin/sh -D nodejs
USER nodejs

# Use dumb-init as entrypoint for proper signal handling
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]

# Apply security labels
LABEL org.opencontainers.image.vendor="Company Name"
LABEL org.opencontainers.image.source="https://github.com/company/repo"
LABEL org.opencontainers.image.revision="commit-sha"

Serverless Security

ConcernMitigation
Function permissions– Apply least privilege IAM roles<br>- Scope permissions to specific resources<br>- Regularly audit and prune permissions
Dependency security– Scan dependencies for vulnerabilities<br>- Use lockfiles to prevent dependency confusion<br>- Minimize third-party dependencies
Environment variables– Use secret management services<br>- Encrypt sensitive environment variables<br>- Rotate secrets regularly
Code injection– Validate and sanitize all event data<br>- Avoid dangerous functions (eval, exec)<br>- Implement strong input validation
DoS protection– Set appropriate timeouts<br>- Implement circuit breakers<br>- Use throttling and concurrency limits

Cloud Security Controls

Control TypeRecommendations
Identity & Access Management– Use managed identity services<br>- Implement just-in-time access<br>- Enable MFA for all users<br>- Apply service control policies
Network Security– Implement private endpoints<br>- Use security groups and NACLs<br>- Enable VPC flow logs<br>- Apply zero-trust network access
Data Protection– Enable default encryption<br>- Use customer-managed keys for sensitive data<br>- Apply object-level permissions<br>- Implement backup encryption
Monitoring & Auditing– Enable cloud trail/audit logs<br>- Set up anomaly detection<br>- Configure automated remediation<br>- Implement compliance reporting
Threat Detection– Deploy cloud security posture management<br>- Enable threat intelligence feeds<br>- Use behavior analytics<br>- Implement automated response

Security Testing

Testing Types and Tools

Test TypePurposeTools
Static Application Security Testing (SAST)Analyze source code for security flaws– SonarQube<br>- Checkmarx<br>- Semgrep<br>- ESLint Security Plugin
Dynamic Application Security Testing (DAST)Test running applications for vulnerabilities– OWASP ZAP<br>- Burp Suite<br>- Arachni<br>- Acunetix
Interactive Application Security Testing (IAST)Combines SAST and DAST for runtime analysis– Contrast Security<br>- Seeker<br>- InsightAppSec<br>- Hdiv
Software Composition Analysis (SCA)Identify vulnerable dependencies– Snyk<br>- OWASP Dependency-Check<br>- WhiteSource<br>- Black Duck
Penetration TestingSimulate attacks to find vulnerabilities– Metasploit<br>- Kali Linux tools<br>- Cobalt Strike<br>- Manual testing
FuzzingSend random/malformed inputs to find bugs– AFL++<br>- LibFuzzer<br>- Peach Fuzzer<br>- BooFuzz

Security Testing in CI/CD

# GitHub Actions security workflow
name: Security Scan

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run SAST scan
        uses: github/codeql-action/analyze@v2
        with:
          languages: javascript
      
      - name: Run dependency scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      
      - name: Run container scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'my-app:latest'
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      - name: Run OWASP ZAP scan
        uses: zaproxy/action-full-scan@v0.4.0
        with:
          target: 'https://staging-app.example.com'

Security Monitoring & Incident Response

Security Monitoring Components

ComponentPurposeImplementation
LoggingRecord security-relevant events– Centralized log collection<br>- Structured logging format<br>- Log integrity protection
MonitoringDetect suspicious activities– Real-time metrics<br>- Anomaly detection<br>- Health checks
AlertingNotify on security events– Prioritized alerts<br>- Alert thresholds<br>- Escalation paths
SIEMAggregate and analyze security data– Log correlation<br>- Threat intelligence integration<br>- Compliance reporting
Runtime ProtectionDetect and block attacks– Web Application Firewalls<br>- Runtime Application Self-Protection<br>- API gateways

Security Logging Best Practices

Log TypeWhat to Log
Authentication– Success/failure events<br>- IP addresses<br>- User identifiers<br>- Timestamp and timezone<br>- Authentication method
Authorization– Access attempts (success/failure)<br>- Resource identifiers<br>- User/service identities<br>- Actions attempted
Data Access– Records accessed<br>- Query parameters (sanitized)<br>- Result counts<br>- Access patterns
System Changes– Configuration modifications<br>- Account changes<br>- Permission changes<br>- System state changes
Security Events– Detected threats<br>- Block actions<br>- Security control changes<br>- Scan results

Incident Response Plan

  1. Preparation

    • Document systems and assets
    • Establish IR team and roles
    • Create communication templates
    • Develop playbooks for common incidents
  2. Detection & Analysis

    • Monitor security alerts
    • Perform initial triage
    • Determine scope and impact
    • Classify incident severity
  3. Containment

    • Isolate affected systems
    • Block attack vectors
    • Preserve evidence
    • Implement temporary workarounds
  4. Eradication

    • Remove malicious components
    • Patch vulnerabilities
    • Reset compromised credentials
    • Validate system integrity
  5. Recovery

    • Restore from clean backups
    • Verify system functionality
    • Monitor for recurring issues
    • Phase in normal operations
  6. Post-Incident

    • Conduct root cause analysis
    • Document lessons learned
    • Update security controls
    • Enhance detection capabilities

Compliance & Regulatory Considerations

Common Regulations by Region

RegionRegulationsKey Requirements
GlobalISO 27001, SOC 2– Information security management<br>- Risk assessment<br>- Access controls<br>- Vulnerability management
United StatesHIPAA, PCI DSS, CCPA– Healthcare data protection<br>- Payment card security<br>- Consumer privacy rights
European UnionGDPR– Data protection by design<br>- Consent for processing<br>- Data subject rights<br>- Breach notification
Asia PacificPDPA (Singapore), APPI (Japan)– Personal data protection<br>- Cross-border transfer rules<br>- Breach notification

Key Compliance Controls for Applications

ControlImplementation
Access control– Role-based access<br>- Multi-factor authentication<br>- Least privilege<br>- Regular access reviews
Data protection– Encryption (at rest and in transit)<br>- Data minimization<br>- Secure deletion<br>- Data classification
Audit logging– Security event logging<br>- User activity tracking<br>- Log protection and retention<br>- Tamper-evident logs
Security testing– Vulnerability scanning<br>- Penetration testing<br>- Security code reviews<br>- Regular assessments
Incident response– Detection capabilities<br>- Response procedures<br>- Notification processes<br>- Recovery plans

Resources for Further Learning

Organizations & Standards

Books & Publications

  • “The Web Application Hacker’s Handbook” by Dafydd Stuttard and Marcus Pinto
  • “Agile Application Security” by Laura Bell, Jim Bird, and Michael Brunton-Spall
  • “Threat Modeling: Designing for Security” by Adam Shostack
  • “Cloud Security: A Comprehensive Guide to Secure Cloud Computing” by Ronald L. Krutz and Russell Dean Vines

Online Resources

Scroll to Top