5 min read
On this page

Application Security

Application security encompasses the practices, tools, and processes that protect software from vulnerabilities throughout its lifecycle — from design through deployment and operations.

Secure Software Development Lifecycle (SSDLC)

Security must be integrated at every phase, not bolted on after development.

| Phase | Security Activities | |-------|-------------------| | Requirements | Threat modeling, security requirements, abuse cases | | Design | Architecture risk analysis, security design patterns | | Implementation | Secure coding standards, code review, SAST | | Testing | DAST, penetration testing, fuzzing | | Deployment | Configuration hardening, secrets management | | Operations | Monitoring, incident response, patching |

Threat Modeling

STRIDE categorizes threats:

  • Spoofing identity
  • Tampering with data
  • Repudiation (denying actions)
  • Information disclosure
  • Denial of service
  • Elevation of privilege

Process: Decompose the application into components. Identify trust boundaries. Enumerate threats per component. Prioritize by risk (likelihood x impact). Define mitigations.

Security Testing Tools

SAST (Static Application Security Testing)

Analyzes source code or bytecode without executing the program. Finds vulnerabilities early in the development cycle.

Strengths: Covers all code paths. Finds issues before deployment. Integrates into CI/CD.

Weaknesses: High false-positive rate. Cannot find runtime or configuration issues. Language-specific.

Tools: Semgrep, CodeQL, Bandit (Python), cargo-audit and clippy lints (Rust), SonarQube.

// SAST would flag this pattern
PROCEDURE HANDLE_REQUEST(user_input)
    // Flagged: command injection risk
    output ← EXECUTE_COMMAND("sh", "-c",
                "echo " + user_input)  // Unsanitized input in command

DAST (Dynamic Application Security Testing)

Tests the running application by sending crafted requests and analyzing responses. Black-box testing.

Strengths: Finds runtime vulnerabilities (authentication flaws, misconfigurations). Language-agnostic. Low false-positive rate.

Weaknesses: Limited code coverage. Only tests reachable endpoints. Slower than SAST.

Tools: OWASP ZAP, Burp Suite, Nuclei.

SCA (Software Composition Analysis)

Identifies known vulnerabilities in dependencies by matching library versions against vulnerability databases (CVE, NVD, OSV).

# Rust: check dependencies for known vulnerabilities
cargo audit

# Example output
Crate:     chrono
Version:   0.4.19
Warning:   RUSTSEC-2020-0159
Title:     Potential segfault in localtime_r invocations

Tools: cargo-audit (Rust), Dependabot, Snyk, Trivy (also scans containers).

SBOM (Software Bill of Materials): A machine-readable inventory of all components. Formats: SPDX, CycloneDX. Required by some regulations and government contracts.

Secrets Management

Secrets (API keys, database passwords, TLS certificates) must never be hardcoded or committed to version control.

Principles

  1. Centralized storage: Single source of truth with access controls.
  2. Encryption at rest: Secrets encrypted in storage.
  3. Least privilege: Applications receive only the secrets they need.
  4. Rotation: Secrets expire and are rotated regularly.
  5. Audit logging: Every access is recorded.

HashiCorp Vault

A secrets management platform providing dynamic secrets, encryption as a service, and identity-based access.

# Authenticate
vault login -method=approle role_id=xxx secret_id=yyy

# Read a secret
vault kv get secret/myapp/database
# Returns: { "username": "app_user", "password": "..." }

# Dynamic secrets: Vault creates a temporary database credential
vault read database/creds/readonly
# Returns: { "username": "v-approle-readonly-abc", "password": "...", "ttl": "1h" }

Dynamic secrets: Generated on-demand with automatic expiration. No long-lived credentials to leak.

Cloud KMS (Key Management Service)

Cloud providers offer managed key storage with hardware security module (HSM) backing.

PROCEDURE ENCRYPT_SECRET(client, key_id, plaintext) → bytes
    response ← client.ENCRYPT(
        key_id ← key_id,
        plaintext ← plaintext
    )
    IF response IS error THEN FAIL("encryption failed")
    RETURN response.ciphertext_blob

Envelope encryption: KMS encrypts a data encryption key (DEK). The DEK encrypts the actual data. Only the encrypted DEK is stored alongside the data.

Secure Coding Practices

Input Validation

Validate all input at the boundary of your application. Prefer allowlists over denylists.

// Validates and parses a port number from user input.
PROCEDURE PARSE_PORT(input) → port or error
    port ← PARSE_INTEGER(TRIM(input))
    IF port IS error THEN RETURN error("Invalid port number")
    IF port < 1024 THEN RETURN error("Privileged ports not allowed")
    RETURN port

// Validates that a URL points to an allowed external host (SSRF prevention).
PROCEDURE VALIDATE_URL(url) → parsed_url or error
    parsed ← URL_PARSE(url)
    IF parsed IS error THEN RETURN error("Invalid URL: " + error_message)

    // Block private/internal IPs
    host ← parsed.HOST
    IF host IS NOT null THEN
        ip ← PARSE_IP(host)
        IF ip IS valid THEN
            IF IS_LOOPBACK(ip) OR IS_UNSPECIFIED(ip) THEN
                RETURN error("Internal addresses not allowed")
    RETURN parsed

Output Encoding

Encode output based on the context where it will be rendered.

| Context | Encoding | |---------|----------| | HTML body | HTML entity encoding (<&lt;) | | HTML attribute | Attribute encoding, quote wrapping | | JavaScript | JavaScript escaping (\xHH) | | URL parameter | Percent encoding (%HH) | | CSS | CSS escaping (\HHHHHH) | | SQL | Parameterized queries (not encoding) |

Error Handling

Never expose internal details in error messages. Map internal errors (database errors, stack traces) to generic client-facing messages. Log the full error with context server-side, but return only safe messages like "An internal error occurred" to users. In Rust, use thiserror to define typed errors with internal #[source] chains that are logged but never serialized to API responses.

Logging and Monitoring

Security Logging

Log security-relevant events with sufficient context for investigation.

What to log: Authentication attempts (success and failure), authorization failures, input validation failures, privilege changes, administrative actions, data access to sensitive resources.

What NOT to log: Passwords, session tokens, credit card numbers, personal data (or log redacted versions).

PROCEDURE LOGIN(username, password) → Session or AuthError
    user ← FIND_USER(username)
    IF user IS error THEN RETURN error

    IF NOT VERIFY_PASSWORD(password, user.password_hash) THEN
        LOG_WARNING("Failed login attempt",
                    username ← username,
                    source_ip ← REQUEST_IP())   // Never log the password
        RETURN error(InvalidCredentials)

    LOG_INFO("Successful login", username ← username, user_id ← user.id)
    RETURN CREATE_SESSION(user)

Monitoring and Alerting

Key metrics: Failed login rate, error rate spikes, unusual data access patterns, new admin accounts, configuration changes.

SIEM (Security Information and Event Management): Aggregates logs from multiple sources, correlates events, and triggers alerts. Examples: Splunk, Elastic SIEM, Microsoft Sentinel.

Incident Response

Phases (NIST SP 800-61)

  1. Preparation: Establish IR team, runbooks, communication plans, tools.
  2. Detection and Analysis: Identify incidents through monitoring, alerts, or reports. Determine scope and impact.
  3. Containment: Short-term (isolate affected systems) and long-term (apply patches, change credentials).
  4. Eradication: Remove the root cause — malware, unauthorized access, vulnerable code.
  5. Recovery: Restore systems from clean backups. Monitor for recurrence.
  6. Post-Incident Activity: Lessons learned. Update defenses and runbooks.

Containment Strategies

| Strategy | Use Case | |----------|----------| | Network isolation | Compromised server — remove from network | | Credential rotation | Stolen credentials — rotate all affected secrets | | WAF rules | Active exploitation — block attack pattern | | Feature flag | Vulnerable feature — disable without full deploy | | DNS sinkhole | C2 communication — redirect malicious domains |

Incident Severity Levels

  • P1/Critical: Active data breach, ransomware, complete service outage.
  • P2/High: Exploitation of vulnerability, partial compromise, significant data exposure risk.
  • P3/Medium: Detected vulnerability, suspicious activity, policy violation.
  • P4/Low: Minor policy deviation, informational security event.

Application security is not a one-time effort but a continuous process. The most effective programs combine automated tooling (SAST, DAST, SCA) with secure development practices, robust secrets management, comprehensive monitoring, and well-rehearsed incident response procedures.