Callable with Insufficient Behavioral Summary
Description
Callable with Insufficient Behavioral Summary occurs when code contains a function or method whose signature and/or associated inline documentation does not sufficiently describe the callable's inputs, outputs, side effects, assumptions, or return codes. Without adequate behavioral documentation, developers using the function may misuse it, leading to bugs, security vulnerabilities, or unexpected behavior. This is especially critical for security-sensitive functions where callers need to understand preconditions, postconditions, and error handling requirements.
Risk
Insufficient behavioral summaries have indirect security implications. Callers may not properly validate inputs if requirements aren't documented. Return codes indicating errors or security issues may be ignored. Side effects affecting security state may not be anticipated. Assumptions about thread safety or reentrancy may be violated. Resource cleanup requirements may not be understood. Security-critical preconditions may not be met. Error handling paths may be incorrectly implemented. Functions may be called in insecure contexts due to missing usage guidance.
Solution
Document all function parameters with types, valid ranges, and constraints. Document return values including all possible return codes and their meanings. Explicitly state side effects (file system, network, global state modifications). Document preconditions that must be met before calling. Document postconditions that are guaranteed after the call. Specify thread safety characteristics. Document exceptions that may be thrown and when. Include security-relevant warnings. Provide usage examples. Keep documentation synchronized with implementation. Use documentation generation tools (Javadoc, Doxygen, Sphinx).
Common Consequences
| Impact | Details |
|---|---|
| Other | Scope: Other Reduce Maintainability - Makes it more difficult to maintain the product, which indirectly affects security by making it more difficult or time-consuming to find and fix vulnerabilities. |
| Integrity | Scope: Integrity Improper Use - Without clear behavioral documentation, callers may misuse functions in ways that compromise security. |
Example Code
Vulnerable Code
// Vulnerable: Function with insufficient behavioral summary
public class UserService {
// What does this return on failure? null? throws?
// What inputs are valid?
// What side effects does it have?
public User authenticate(String u, String p) {
// ...
}
// What happens if user is null?
// What permissions are required?
// What does the int return mean?
public int updateUser(User user) {
// ...
}
// Does this throw on error or return null?
// What if the user doesn't exist?
// Is this thread-safe?
public User findById(long id) {
// ...
}
// What are "options"? What are valid values?
// What happens with invalid options?
public void process(Map<String, Object> options) {
// ...
}
// What errors can occur? How are they reported?
// What happens if connection fails partway through?
public void syncToRemote() {
// ...
}
}
# Vulnerable: Python functions without proper documentation
def validate(data, rules):
# What format is data? dict? string? object?
# What format are rules? How are they applied?
# What does it return? True/False? Validated data? Errors?
pass
def encrypt(text, key):
# What algorithm is used?
# What format is the key? bytes? string? length requirements?
# What encoding does it return?
# What errors can occur?
pass
def connect(host, opts=None):
# What are valid opts? What's the default behavior?
# What does it return? A connection object? Nothing?
# How do you close the connection?
# What exceptions might be raised?
pass
def process_payment(amount, card):
# What's the format of amount? cents? dollars? Decimal?
# What's the format of card? dict? object? string?
# What happens on failure?
# Is the charge atomic?
pass
// Vulnerable: C functions without behavioral documentation
// What is max length? What happens on overflow?
// Does this null-terminate? Who owns the memory?
char* copy_string(char* dest, char* src);
// Return values: -1 error? 0 success? Or opposite?
// What errors are possible? How to get error details?
int process_data(void* data, int len);
// Does this free the pointer? Set it to NULL?
// Can you call this multiple times safely?
void cleanup(void* resource);
// What happens with NULL callback?
// When is callback invoked? What thread?
// What's the lifetime of user_data?
void register_callback(void (*cb)(int), void* user_data);
// Vulnerable: JavaScript with insufficient documentation
// What is config? What properties are expected?
// What does it return? Promise? Value? undefined?
function initialize(config) {
// ...
}
// Does this sanitize? Encode? Validate?
// What inputs are considered "safe"?
function processUserInput(input) {
// ...
}
// How should errors be handled?
// What format is the response?
// Are there rate limits?
async function fetchData(url, options) {
// ...
}
// What are the valid operations?
// What's the return type?
// Does this modify global state?
function execute(operation, params) {
// ...
}
Fixed Code
// Fixed: Complete behavioral documentation
public class UserService {
/**
* Authenticate a user with username and password.
*
* <p>Validates the provided credentials against the user store
* and returns the authenticated user if successful.
*
* <p><strong>Security:</strong> Failed attempts are logged and
* rate-limited. Passwords are compared using constant-time comparison.
*
* @param username The username, must be non-null and 1-50 characters.
* Case-insensitive comparison is used.
* @param password The plaintext password, must be non-null.
* Not logged or stored.
* @return The authenticated User object with session token populated
* @throws IllegalArgumentException if username or password is null
* @throws AuthenticationException if credentials are invalid
* @throws AccountLockedException if account is locked due to failed attempts
* @throws RateLimitException if too many attempts in short period
*
* @see #logout(User) to end the session
* @see User#getSessionToken() for the generated token
*/
public User authenticate(String username, String password)
throws AuthenticationException, AccountLockedException, RateLimitException {
// ...
}
/**
* Update user profile information.
*
* <p>Updates the user's profile in the database. Only non-null fields
* in the provided User object are updated (partial update).
*
* <p><strong>Thread Safety:</strong> This method is thread-safe.
* Concurrent updates to the same user are serialized.
*
* <p><strong>Permissions:</strong> Caller must have UPDATE_USER permission
* or be updating their own profile.
*
* @param user The user with updated fields. Must not be null.
* The user.id must correspond to an existing user.
* @return Number of fields that were modified:
* <ul>
* <li>0 = No changes made (values same as existing)</li>
* <li>1+ = Number of fields updated</li>
* <li>-1 = User not found</li>
* </ul>
* @throws IllegalArgumentException if user is null or user.id is null
* @throws PermissionDeniedException if caller lacks required permissions
* @throws ValidationException if any field values are invalid
*/
public int updateUser(User user)
throws PermissionDeniedException, ValidationException {
// ...
}
/**
* Find a user by their unique ID.
*
* <p><strong>Thread Safety:</strong> Thread-safe for concurrent reads.
*
* @param id The user's unique ID. Must be positive.
* @return The User if found, or null if no user exists with that ID.
* The returned User is a detached copy; modifications do not
* affect the stored user.
* @throws IllegalArgumentException if id is less than 1
*/
public User findById(long id) {
// ...
}
}
# Fixed: Python with comprehensive documentation
def validate(data: dict, rules: list[ValidationRule]) -> ValidationResult:
"""
Validate data dictionary against a set of validation rules.
Applies each rule to the data and collects validation errors.
Rules are applied in order; all rules are evaluated even if
early rules fail.
Args:
data: Dictionary of field names to values to validate.
All values must be JSON-serializable types.
rules: List of ValidationRule objects defining constraints.
Empty list is valid (returns success with no checks).
Returns:
ValidationResult containing:
- is_valid: True if all rules passed, False otherwise
- errors: List of ValidationError for each failed rule
- validated_data: Copy of data with type coercions applied
Raises:
TypeError: If data is not a dict or rules is not a list
ValueError: If any rule is malformed
Example:
>>> rules = [Required('name'), MaxLength('name', 50)]
>>> result = validate({'name': 'John'}, rules)
>>> result.is_valid
True
Security Note:
This function does NOT sanitize data for SQL or HTML.
Use SqlParameterizer or HtmlEscaper after validation.
Thread Safety:
This function is thread-safe and has no side effects.
"""
pass
def encrypt(
plaintext: bytes,
key: bytes,
algorithm: str = 'AES-256-GCM'
) -> tuple[bytes, bytes, bytes]:
"""
Encrypt data using authenticated encryption.
Uses the specified algorithm with a random IV/nonce.
The authentication tag is included for integrity verification.
Args:
plaintext: Data to encrypt. Maximum size: 64MB.
key: Encryption key. Must be:
- 32 bytes for AES-256-GCM (default)
- 32 bytes for ChaCha20-Poly1305
algorithm: Encryption algorithm. Supported values:
- 'AES-256-GCM' (default, recommended)
- 'ChaCha20-Poly1305'
Returns:
Tuple of (ciphertext, nonce, auth_tag):
- ciphertext: Encrypted data (same length as plaintext for GCM)
- nonce: Random 12-byte nonce (must be stored with ciphertext)
- auth_tag: 16-byte authentication tag
Raises:
ValueError: If key length doesn't match algorithm requirements
ValueError: If algorithm is not supported
ValueError: If plaintext exceeds 64MB
CryptoError: If encryption fails (rare, usually system issue)
Example:
>>> key = secrets.token_bytes(32)
>>> ciphertext, nonce, tag = encrypt(b'secret', key)
>>> decrypt(ciphertext, key, nonce, tag)
b'secret'
Security Notes:
- Never reuse a (key, nonce) pair
- Store nonce and auth_tag with ciphertext; they're not secret
- Key must be kept secret and generated securely
"""
pass
CVE Examples
This CWE is marked as PROHIBITED for direct CVE mapping as it represents a code quality concern rather than a direct security vulnerability.
Related CWEs
- CWE-1078: Inappropriate Source Code Style or Formatting (parent)
- CWE-1006: Bad Coding Practices (category member)
- CWE-1111: Incomplete I/O Documentation (related)
- CWE-1116: Inaccurate Comments (related)
References
- MITRE Corporation. "CWE-1117: Callable with Insufficient Behavioral Summary." https://cwe.mitre.org/data/definitions/1117.html
- Javadoc Documentation Guidelines
- Python PEP 257 - Docstring Conventions
- "Clean Code" by Robert C. Martin