Security Architecture Review

Production engineering guide for security architecture review covering patterns, implementation strategies, and operational best practices.

A Security Architecture Review is a structured evaluation of a system’s security design, conducted early in the development lifecycle or before a major release. It ensures that security is not an afterthought but embedded in the architecture: from data flows to trust boundaries, from identity models to runtime protections. It matters most when onboarding a new service, planning a major cloud migration, or responding to a security incident that reveals systemic weaknesses.

Preparing for the Review

Before the review meeting, the architecture team must compile a set of artifacts that define the system’s security posture. These should be accessible, versioned, and consistent across teams.

Core Artifacts

A diagram showing external actors, system components, and data flows. Use standard notation: boxes for services, arrows for data, and labels for security-sensitive interactions. Include trust boundaries: zones like "Internet," "DMZ," "Internal Network," and "Secure Data Center."

For each service or subsystem, provide a DFD showing data inputs, processing, storage, and outputs. Mark security-relevant data: PII, credentials, session tokens, audit logs. Label security controls at each stage: encryption, authentication, integrity checks.

A list of security requirements, each with a unique ID, priority (must-have, should-have, could-have), and acceptance criteria. Examples:

A documented process identifying threats using STRIDE or DREAD. Include:

Review Readiness Checklist

Conducting the Review

The review is a collaborative session focused on three core activities: validating the architecture, identifying gaps, and aligning on decisions.

1. Walkthrough of System Context and Data Flows

Begin with a 20-minute presentation of the SCD and DFD. The presenter should walk through the journey of a user request, highlighting security-sensitive steps.

Key Questions to Ask

Common Validation Commands


curl -I https://api.example.com/v1/users

# Output:
HTTP/2 200
content-type: application/json
strict-transport-security: max-age=31536000; includeSubDomains; preload
# Check that all services expose a health endpoint with security metadata
curl https://api.example.com/health

# Response:
{
  "status": "OK",
  "version": "1.2.3",
  "security": {
    "tls": {
      "version": "TLSv1.3",
      "cipher": "TLS_AES_256_GCM_SHA512",
      "certificates": 2,
      "chain_length": 3
    },
    "auth": {
      "type": "JWT",
      "audience": "api.example.com",
      "issuer": "https://auth.example.com"
    }
  }
}

2. Threat Model Deep Dive

Review the threat model document with a focus on high-risk threats.

Example: SQL Injection in User Login

An attacker sends a malicious username parameter: ' OR 1=1-- This bypasses the login form and gains admin access.

Validate Implementation of Mitigations

-- Check if prepared statements are used
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM users
WHERE username = $1 AND password = $2;

The query plan shows a sequential scan, not an index scan. The username column is not indexed.

# Verify rate limiting via Redis
redis-cli GET "login:rate:ip:192.168.1.1"

# Response:
"12"

The key exists, but the value is a string, not a JSON object with count, last_attempt, and window.

3. Security Requirements Validation

Review each security requirement against the architecture and implementation.

Example: SR-001 – All user data encrypted at rest using AES-256

  1. Query the database for user data.
  2. Check encryption at the database level.
  3. Verify that the application code applies AES-256.
-- In PostgreSQL, check table encryption
SELECT
  schemaname,
  tablename,
  hasindexes,
  relpages,
  pg_size_pretty(pg_total_relation_size('users')) AS total_size
FROM pg_tables
WHERE tablename = 'users';

-- Output:
schemaname | tablename | hasindexes | relpages | total_size
-----------|-----------|------------|----------|------------
public     | users     | t          | 142      | 11 MB
# Check application-level encryption
curl -H "Authorization: Bearer <JWT>" https://api.example.com/v1/users/123

# Response:
{
  "id": 123,
  "name": "Alice Smith",
  "email": "[email protected]",
  "address": {
    "street": "123 Main St",
    "city": "Boston",
    "zip": "02101"
  },
  "created_at": "2023-10-05T14:30:00Z",
  "encrypted": true,
  "encryption_key_id": "key-456"
}

The address field is encrypted, but name and email are not. The encrypted flag is set, but the actual data is stored in plaintext.

Common Errors in Requirement Fulfillment

The encryption key is fixed and never rotated. The key is used for 18 months but never updated.

Two services use different key identifiers: key-456 and enc-key-456. No standard naming.

The application uses raw AES-256 keys, but no key derivation (e.g., PBKDF2, scrypt) to derive keys from a master key.

Deciding on Architecture Decisions

The review ends with a decision session to resolve open issues and set new directions.

Decision Template

Each decision should include:

e.g., "Use JWE for end-to-end encrypted user data"

Why this decision is necessary or better than alternatives.

Which components, teams, and processes will change.

Concrete, measurable conditions for success.

Person responsible for implementation and documentation.

Example Decision

Title: Use JWT with JWE for secure API payloads

Rationale: Current API responses contain sensitive user data in JSON. The JWT is signed but not encrypted. A compromised API gateway exposes the full payload to attackers.

Impact:

Acceptance Criteria:

Owner: Backend team lead, with support from platform team.

Implementation Steps

# Generate a JWE-protected JWT
curl -X POST https://auth.example.com/jwe \
  -H "Content-Type: application/json" \
  -d '{
    "aud": "api.example.com",
    "iss": "https://auth.example.com",
    "exp": 1700000000,
    "sub": "user-123",
    "jwe": {
      "protected": {
        "alg": "RSA-OAEP",
        "enc": "A256GCM"
      },
      "recipients": [
        {
          "header": {
            "kid": "key-456"
          },
          "encrypted_key": "base64url-encoded-encrypted-key"
        }
      ],
      "ciphertext": "base64url-encoded-ciphertext",
      "tag": "base64url-encoded-authentication-tag"
    }
  }'

Failure Modes in Implementation

alg: A256GCM instead of A256GCM (typo), causing clients to fail to decrypt.

Client expects kid to identify the key, but kid is missing — leads to key mismatches.

Gateway receives JWE but only validates the JWT signature, not the encryption. Data is accessible even if the JWE key is invalid.

The jwe object is present, but the ciphertext field is missing or misnamed (ciphertext vs ct).

After the Review

The review is not complete until decisions are documented and actions are tracked.

Follow-Up Tasks

# Decision: Use JWE for API Payloads

## Status
- **Status:** Approved
- **Date:** 2023-11-02
- **Owner:** [email protected]

## Context
Current API responses use JWTs with signatures but no encryption. Sensitive data is exposed in plaintext.

## Decision
All API responses must be JWE-protected. The JWE must use RSA-OAEP for key encryption and A256GCM for content encryption.

## Consequences
- Increased latency due to JWE processing.
- Client libraries must handle JWE decoding.
- New audit trail for key rotation and JWE validation.

## Implementation
- Update `api-service` to generate JWEs.
- Update `api-gateway` to validate and decrypt JWEs.
- Add `jwe` field in all API response schemas.

Review Success Metrics

Common Pitfalls

TLS is not enough; additional mechanisms like mutual TLS, token validation, and endpoint authentication are often overlooked.

JWTs are used for authentication but not for authorization or encryption. They are signed but not encrypted, leading to exposed claims.

Keys are created but not rotated, backed up, or audited. No process for key retirement or revocation.

Services log to files, but audit logs are not centralized. No timeline of security-relevant events across services.

user_id, userId, userID, user_id, user_id, user_id — all used interchangeably.

The Security Architecture Review is not a formality. It is a diagnostic, a design workshop, and a commitment to security as a core architectural discipline.

This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.