Incomplete Design Documentation

Description

Incomplete Design Documentation occurs when a product's design documentation fails to adequately describe critical aspects of the system. This includes insufficient documentation of control flow, data flow, system initialization sequences, relationships between components, trust boundaries, design rationales, security assumptions, and other essential design elements. Without comprehensive design documentation, developers and security reviewers cannot fully understand how the system is intended to work, making it difficult to verify correct implementation or identify security issues.

Risk

Incomplete design documentation has indirect security implications. Security reviewers cannot verify that the implementation matches security requirements. Trust boundaries may be unclear, leading to improper access control placement. Data flow paths may not be documented, hiding potential data leakage routes. Threat modeling is incomplete without understanding system design. New developers may make incorrect assumptions about security requirements. Maintenance changes may violate undocumented security invariants. Incident response is hindered when system behavior is poorly documented.

Solution

Create comprehensive design documentation that covers all critical aspects of the system. Document control flow and data flow explicitly. Clearly identify and document trust boundaries. Describe security assumptions and requirements. Document the rationale for design decisions, especially security-related ones. Include sequence diagrams for critical operations. Document system initialization and shutdown procedures. Maintain documentation as the system evolves. Use templates to ensure consistent documentation coverage. Review documentation for completeness regularly.

Common Consequences

ImpactDetails
OtherScope: Other

Reduce Maintainability - Incomplete documentation makes maintenance error-prone.
OtherScope: Other

Increase Analytical Complexity - Security analysis cannot be thorough without design documentation.
IntegrityScope: Integrity

Design Divergence - Implementation may deviate from intended design without documentation as reference.

Example Code

Vulnerable Code

// Vulnerable: Incomplete or missing design documentation

// FILE: auth_service.py
// No documentation about:
// - What authentication methods are supported
// - Session token generation algorithm
// - Token expiration policy
// - Account lockout mechanism
// - Password requirements
// - Trust boundaries

class AuthService:
    def login(self, username, password):
        # Implementation without documented design
        user = self.db.find_user(username)
        if user and check_password(password, user.password_hash):
            return generate_token(user)
        return None

// Questions that documentation should answer:
// - How long is a session valid?
// - What happens after N failed attempts?
// - Can users have multiple active sessions?
// - How are tokens validated?
// - Where should this service be called from?


// FILE: payment_processor.py
// Missing critical design documentation:
// - Payment flow sequence
// - Error handling strategy
// - Retry policy
// - Idempotency handling
// - PCI compliance considerations

class PaymentProcessor:
    def process_payment(self, order, payment_info):
        # Complex payment logic without design docs
        validated = self.validate(payment_info)
        if not validated:
            return {"error": "validation_failed"}

        result = self.gateway.charge(payment_info)
        if result.success:
            self.update_order(order, result)

        return result

// Unanswered questions:
// - What if charge succeeds but update fails?
// - How to handle duplicate submissions?
// - What data is logged?
// - What are the trust boundaries with the gateway?


// FILE: data_pipeline.py
// No data flow documentation
// Missing:
// - Data sources and sinks
// - Data transformations
// - Sensitive data handling
// - Access control on data

class DataPipeline:
    def process(self, data):
        # Data flows through without documented path
        cleaned = self.clean(data)
        transformed = self.transform(cleaned)
        enriched = self.enrich(transformed)
        self.store(enriched)

// Critical questions unanswered:
// - What PII flows through this pipeline?
// - How is data sanitized?
// - Who can access the stored data?
// - How long is data retained?

Fixed Code

// Fixed: Comprehensive design documentation

/*
 * ============================================================================
 * AUTHENTICATION SERVICE - DESIGN DOCUMENT
 * ============================================================================
 *
 * 1. OVERVIEW
 * -----------
 * The AuthService is responsible for user authentication and session
 * management. It serves as the single point of authentication for all
 * application components.
 *
 * 2. TRUST BOUNDARIES
 * -------------------
 * +------------------+     +------------------+     +------------------+
 * |   Client/UI      | --> |   AuthService    | --> |   User Database  |
 * |   (Untrusted)    |     |   (Trusted)      |     |   (Trusted)      |
 * +------------------+     +------------------+     +------------------+
 *
 * - All client input is untrusted and must be validated
 * - AuthService is the trust boundary for authentication decisions
 * - Database access is restricted to AuthService for user credentials
 *
 * 3. AUTHENTICATION FLOW
 * ----------------------
 * Client          AuthService        Database        SessionStore
 *   |                  |                 |                |
 *   |--login(u,p)----->|                 |                |
 *   |                  |--find_user(u)-->|                |
 *   |                  |<--user_record---|                |
 *   |                  |                 |                |
 *   |                  |--verify_password(p, hash)        |
 *   |                  |                 |                |
 *   |                  |--generate_token()                |
 *   |                  |--store_session----------------->|
 *   |<--token----------|                 |                |
 *   |                  |                 |                |
 *
 * 4. SECURITY REQUIREMENTS
 * ------------------------
 *
 * 4.1 Password Requirements:
 *     - Minimum length: 8 characters
 *     - Must contain: uppercase, lowercase, number
 *     - Stored using: bcrypt with cost factor 12
 *     - Never logged or returned in responses
 *
 * 4.2 Session Management:
 *     - Token format: JWT signed with RS256
 *     - Token lifetime: 15 minutes (access), 7 days (refresh)
 *     - Maximum concurrent sessions: 5 per user
 *     - Tokens stored in: Redis with TTL
 *
 * 4.3 Account Protection:
 *     - Lockout after: 5 failed attempts
 *     - Lockout duration: 30 minutes
 *     - Failed attempts tracked per: IP + username combination
 *     - Lockout notification: Email sent to user
 *
 * 5. ERROR HANDLING
 * -----------------
 * - Invalid credentials: Return generic "authentication failed" message
 * - Account locked: Return "account temporarily locked" with retry time
 * - Rate limited: Return 429 with Retry-After header
 * - Internal errors: Log details, return generic error to client
 *
 * 6. LOGGING AND AUDIT
 * --------------------
 * Logged events (without sensitive data):
 * - Login attempts (success/failure)
 * - Account lockouts
 * - Token generation
 * - Session invalidation
 *
 * NOT logged:
 * - Passwords
 * - Full tokens (only last 8 chars for correlation)
 */

class AuthService:
    """
    Authentication service implementing the design documented above.

    See: docs/design/auth-service.md for complete design documentation
    """

    # Constants matching documented requirements
    MAX_LOGIN_ATTEMPTS = 5  # Per design doc section 4.3
    LOCKOUT_DURATION_MINUTES = 30
    ACCESS_TOKEN_LIFETIME_MINUTES = 15
    REFRESH_TOKEN_LIFETIME_DAYS = 7
    MAX_CONCURRENT_SESSIONS = 5

    def login(self, username: str, password: str) -> LoginResult:
        """
        Authenticate user and create session.

        Flow:
        1. Check account lockout status
        2. Retrieve user from database
        3. Verify password using bcrypt
        4. Generate JWT tokens
        5. Store session in Redis
        6. Return tokens to caller

        Security notes:
        - Password never logged (see design doc section 6)
        - Generic error messages prevent username enumeration
        - Rate limiting applied per design doc section 4.3

        Args:
            username: User's username (validated for format)
            password: User's password (never stored or logged)

        Returns:
            LoginResult with tokens on success, error code on failure

        Raises:
            AccountLockedException: If account is locked (see design 4.3)
            RateLimitedException: If too many requests (see design 5)
        """
        # Implementation follows documented design
        pass


/*
 * ============================================================================
 * PAYMENT PROCESSOR - DESIGN DOCUMENT
 * ============================================================================
 *
 * 1. PAYMENT FLOW SEQUENCE
 * ------------------------
 *
 * Client     PaymentProcessor    Validator    Gateway      Database
 *   |              |                |            |             |
 *   |--process---->|                |            |             |
 *   |              |--validate----->|            |             |
 *   |              |<--result-------|            |             |
 *   |              |                             |             |
 *   |              |--create_idempotency_key----------------->|
 *   |              |--charge------------------->|             |
 *   |              |<--charge_result-----------|             |
 *   |              |                             |             |
 *   |              |--update_order--------------------------->|
 *   |              |--log_transaction------------------------->|
 *   |<--result-----|                             |             |
 *
 * 2. IDEMPOTENCY HANDLING
 * -----------------------
 * - Each payment request must include client-generated idempotency key
 * - Key stored in database for 24 hours
 * - Duplicate requests return cached result, not re-charged
 * - Key format: UUID v4, validated on input
 *
 * 3. FAILURE HANDLING
 * -------------------
 *
 * Scenario                  | Action                | Retry?
 * --------------------------|----------------------|--------
 * Validation failure        | Return error         | No
 * Gateway timeout           | Mark pending, alert  | Yes (3x)
 * Gateway decline           | Return decline       | No
 * Charge OK, update fails   | Rollback charge      | No
 *
 * 4. PCI DSS COMPLIANCE
 * ---------------------
 * - Card numbers: Never stored, only tokenized
 * - CVV: Never stored, used only for single transaction
 * - Logs: Card numbers masked (first 6, last 4 only)
 * - Transmission: TLS 1.2+ only to gateway
 */

class PaymentProcessor:
    """
    Payment processor implementing PCI-compliant payment handling.

    See: docs/design/payment-processor.md for complete design
    """

    def process_payment(
        self,
        order: Order,
        payment_info: PaymentInfo,
        idempotency_key: str
    ) -> PaymentResult:
        """
        Process payment following documented flow.

        Idempotency:
        - Duplicate requests with same key return cached result
        - Key must be UUID v4 format
        - Keys expire after 24 hours

        PCI Compliance:
        - Card data passed directly to gateway, never stored
        - CVV used for this transaction only
        - All card data masked in logs

        Failure handling:
        - Gateway timeout: 3 retries with exponential backoff
        - Charge success + update failure: Automatic refund initiated

        Args:
            order: Order to process payment for
            payment_info: Card details (handled per PCI DSS)
            idempotency_key: UUID v4 for duplicate detection

        Returns:
            PaymentResult with transaction details
        """
        pass

CVE Examples

This CWE is marked as PROHIBITED for direct CVE mapping as it represents a documentation quality concern rather than a direct security vulnerability.


  • CWE-1059: Insufficient Technical Documentation (parent)
  • CWE-1225: Documentation Issues (category member)
  • CWE-1111: Incomplete I/O Documentation (related)

References

  1. MITRE Corporation. "CWE-1110: Incomplete Design Documentation." https://cwe.mitre.org/data/definitions/1110.html
  2. OWASP. "Threat Modeling."
  3. Martin & Shafer (1996). "Software Quality Assessment Framework."