Security Checklist

KRITIS/NIS2-compliant security review based on CWE vulnerabilities and attack patterns.

This checklist is mandatory for changes to: Network, authentication, cryptography, database, external APIs.

When to Apply

Apply this checklist when changes involve:

  • Cryptographic operations
  • Authentication / Authorization
  • Network communication
  • Database access
  • External API calls
  • File uploads
  • User input

Cryptographic Security

Check CWE Description
[ ] Nonce uniqueness CWE-323 AES-GCM nonce must be unique per encryption
[ ] Nonce tracking CWE-323 Track used nonces, enforce MAX_NONCES_PER_KEY
[ ] Key rotation CWE-323 Rotate key after nonce limit
[ ] Cryptographic RNG CWE-330 OpenSSL/OS CSPRNG for keys/nonces
[ ] Random IDs CWE-330 No sequential keys/session IDs
[ ] Constant-time comparison CWE-208 For secrets, MACs, tokens, API keys
[ ] Replay protection CWE-294 Nonce/timestamp/sequence tracking
[ ] Channel encryption CWE-300 mTLS for external communication

Example: Constant-Time Comparison

(* FORBIDDEN - Timing attack possible *)
function VerifyToken(const AToken, AExpected: string): Boolean;
begin
  Result := AToken = AExpected;  (* Aborts on first difference! *)
end;
 
(* CORRECT - Constant time *)
function VerifyToken(const AToken, AExpected: string): Boolean;
var
  I: Integer;
  Diff: Byte;
begin
  if Length(AToken) <> Length(AExpected) then
    Exit(False);
 
  Diff := 0;
  for I := 1 to Length(AToken) do
    Diff := Diff or (Ord(AToken[I]) xor Ord(AExpected[I]));
 
  Result := Diff = 0;
end;

Memory Security

Check CWE Description
[ ] Memory zeroization CWE-316 Clear secrets after use
[ ] No secrets in logs CWE-532 Never log keys, passwords, tokens
[ ] Secure string handling CWE-316 SecureString (C#), secrecy (Rust)
[ ] Key material cleared CWE-316 try-finally guarantees cleanup on exception

Example: Zeroization

procedure ProcessSecret(const ASecret: string);
var
  LocalCopy: string;
begin
  LocalCopy := ASecret;
  try
    (* Processing *)
    DoSomethingWith(LocalCopy);
  finally
    (* Clear secret - not just release! *)
    FillChar(LocalCopy[1], Length(LocalCopy) * SizeOf(Char), 0);
    LocalCopy := '';
  end;
end;

Input Validation

Check CWE Description
[ ] Size limits CWE-400 Enforce MAX_PAYLOAD_SIZE (default: 64KB)
[ ] Integer overflow CWE-190 SafeAdd(), checked_add(), checked arithmetic
[ ] Null checks CWE-476 At all API boundaries
[ ] No unwrap on input CWE-248 Proper error handling, no panic
[ ] Parameterized queries CWE-89 Never string concatenation for SQL
[ ] Character validation - Whitelist for identifiers where appropriate

Example: SQL Injection Prevention

(* FORBIDDEN - SQL Injection possible *)
procedure GetUser(const AUsername: string);
begin
  Query.SQL.Text := 'SELECT * FROM users WHERE name = ''' + AUsername + '''';
  Query.Open;
end;
 
(* CORRECT - Parameterized *)
procedure GetUser(const AUsername: string);
begin
  Query.SQL.Text := 'SELECT * FROM users WHERE name = :username';
  Query.ParamByName('username').AsString := AUsername;
  Query.Open;
end;

Error Handling (Security)

Check CWE Description
[ ] Sanitized messages CWE-209 No paths/versions/stack traces to client
[ ] Complete logging - Log full error internally before sanitizing
[ ] No panic in service CWE-248 Graceful recovery, service stays active
[ ] Stack trace preserved - Re-throw without wrapping

Example: Sanitized Error Messages

(* FORBIDDEN - Too much information *)
procedure HandleError(E: Exception);
begin
  ShowMessage('Error in C:\Users\Admin\App\src\Database.pas:142: ' + E.Message);
end;
 
(* CORRECT - Log internally, sanitize externally *)
procedure HandleError(E: Exception);
begin
  (* Log full details internally *)
  Logger.Error('Database error at %s: %s', [E.ClassName, E.Message]);
 
  (* Externally only sanitized message *)
  raise EUserError.Create(rsDatabaseOperationFailed);
end;

Availability (DoS Protection)

Check CWE Description
[ ] Rate limiting CWE-400 Token bucket per client/endpoint
[ ] Request size limits CWE-400 Reject oversized payloads early
[ ] Lock safety CWE-667 Lock recovery mechanism
[ ] Resource cleanup CWE-772 try-finally, using, defer, RAII - always
[ ] Timeout handling CWE-400 Timeouts for all external operations

Thread Safety

Check CWE Description
[ ] Lock poisoning handled CWE-667 Recovery from poisoned locks
[ ] No race conditions CWE-362 Thread-safe data structures
[ ] Atomic operations CWE-362 For counters, flags, shared state
[ ] Deadlock prevention CWE-833 Lock ordering, timeouts

Audit & Compliance

Check Standard Description
[ ] All changes logged ISO 27001 A.12.4 Data changes with user, timestamp, old/new
[ ] Security events logged NIS2 Art. 21 Failed auth, rate limiting, suspicious input
[ ] Log rotation - Incremental format
[ ] No sensitive data in logs CWE-532 Check for accidental disclosure

Quick Reference - By Attack Type

Cryptographic Attacks

[ ] Nonce reuse prevented
[ ] Timing attacks mitigated (constant time)
[ ] Replay attacks blocked
[ ] Key enumeration prevented (random IDs)

Input Attacks

[ ] Buffer overflow prevented (size limits)
[ ] Integer overflow prevented
[ ] Malformed input handled
[ ] SQL injection prevented

Availability Attacks

[ ] Resource exhaustion prevented (rate limiting)
[ ] Lock poisoning handled
[ ] Memory exhaustion prevented

Information Disclosure

[ ] Error messages sanitized
[ ] Secrets cleared after use (zeroization)
[ ] No sensitive data in logs

OWASP Top 10 Reference

Rank Vulnerability Prevention in WvdS
1 Broken Access Control Check authorization at all endpoints
2 Cryptographic Failures Modern algorithms, zeroization
3 Injection Parameterized queries, input validation
4 Insecure Design Threat modeling, defense in depth
5 Security Misconfiguration Secure defaults, no debug in prod
6 Vulnerable Components Keep dependencies current
7 Auth Failures MFA, rate limiting, session management
8 Data Integrity Failures Signatures, integrity checks
9 Logging Failures Structured logging, alerting
10 SSRF URL validation, network segmentation

See also

Zuletzt geändert: on 2026/01/29 at 10:31 PM