Invokable Control Element with Signature Containing an Excessive Number of Parameters
Description
Invokable Control Element with Signature Containing an Excessive Number of Parameters occurs when a function or method has an excessive number of parameters, making it difficult to use correctly and maintain. CISQ recommends a default threshold of 7 parameters maximum. Functions with many parameters are error-prone because callers may confuse parameter order, pass incorrect values, or forget required parameters. This anti-pattern often indicates that the function is doing too much and should be refactored.
Risk
While primarily a code quality issue, excessive parameters create indirect security risks. Parameter confusion can lead to security-critical values being placed in wrong positions (e.g., swapping a user ID with a permission level). Long parameter lists make code reviews harder, potentially missing security issues. The complexity discourages thorough testing, leaving edge cases untested. Functions with many parameters often have complex internal logic that may contain vulnerabilities. Boolean parameters in long lists are especially problematic as their meaning is unclear at call sites, potentially leading to security misconfigurations.
Solution
Use parameter objects or data transfer objects (DTOs) to group related parameters. Apply the Builder pattern for complex object construction. Use named parameters where the language supports them. Break down complex functions into smaller, focused functions. Apply the Single Responsibility Principle - if a function needs many parameters, it's likely doing too much. Use default parameter values for optional settings. Create overloaded methods for common use cases. Document parameters clearly and use meaningful parameter names.
Common Consequences
| Impact | Details |
|---|---|
| Other | Scope: Other Reduce Maintainability - Functions with many parameters are hard to understand, use correctly, and modify. |
| Other | Scope: Other Quality Degradation - Parameter confusion leads to bugs that may have security implications. |
| Other | Scope: Other Reduce Reliability - Complex function signatures increase the likelihood of caller errors. |
Example Code
Vulnerable Code
// Vulnerable: Too many parameters (12 parameters!)
public class VulnerableUserService {
public User createUser(
String username,
String password,
String email,
String firstName,
String lastName,
String phone,
String address,
String city,
String state,
String zipCode,
String country,
boolean isAdmin // Easy to accidentally set true!
) {
// Parameter confusion is likely
User user = new User();
user.setUsername(username);
user.setPassword(password); // Which one is password again?
// ... many more assignments
user.setAdmin(isAdmin);
return user;
}
// Callers get confused:
// createUser("john", "[email protected]", "password123", ...) // WRONG ORDER!
}
// Vulnerable: Boolean parameters with unclear meaning
public void configureConnection(
String host,
int port,
String username,
String password,
boolean param1, // What is this?
boolean param2, // And this?
boolean param3, // No idea!
int param4,
String param5
) {
// Callers write: configureConnection("host", 443, "user", "pass", true, false, true, 30, "TLS")
// What do those booleans mean?
}
# Vulnerable: Excessive positional parameters
def vulnerable_send_email(
sender,
recipient,
cc,
bcc,
subject,
body,
html_body,
attachments,
priority,
read_receipt,
delivery_receipt,
encrypt,
sign,
custom_headers
):
"""
Caller has to remember order of 14 parameters!
Easy to confuse 'encrypt' and 'sign' positions.
"""
# Implementation...
pass
# Calling code is confusing and error-prone:
vulnerable_send_email(
"[email protected]",
"[email protected]",
None,
None,
"Subject",
"Body text",
"<p>HTML body</p>",
[],
"high",
True, # read_receipt? or delivery_receipt?
False, # encrypt? or sign?
True, # Did I get this right?
False,
{}
)
// Vulnerable: Method with excessive parameters
public class VulnerablePaymentProcessor
{
public PaymentResult ProcessPayment(
string cardNumber,
string cardHolderName,
int expirationMonth,
int expirationYear,
string cvv,
decimal amount,
string currency,
string merchantId,
string orderId,
string customerEmail,
string billingAddress,
string billingCity,
string billingState,
string billingZip,
string billingCountry,
bool saveCard, // Position 16 - easy to confuse
bool useThreeDS, // Position 17
string returnUrl,
string cancelUrl,
Dictionary<string, string> metadata
)
{
// 20 parameters! Very difficult to call correctly.
// ...
return new PaymentResult();
}
}
// Callers make mistakes:
// processor.ProcessPayment(card, name, 12, 2025, "123", 99.99, "USD",
// merchant, order, email, addr, city, state, zip, country,
// true, false, ... // Which boolean is which?!
// Vulnerable: JavaScript function with many parameters
function vulnerableCreateOrder(
customerId,
customerEmail,
items,
shippingAddress,
shippingCity,
shippingState,
shippingZip,
shippingCountry,
billingAddress,
billingCity,
billingState,
billingZip,
billingCountry,
paymentMethod,
cardToken,
couponCode,
giftWrap,
giftMessage,
deliveryInstructions,
isExpress
) {
// 20 positional parameters!
// JavaScript doesn't even warn about wrong argument count
}
// Calling this is a nightmare:
vulnerableCreateOrder(
"cust123",
"[email protected]",
[{id: 1, qty: 2}],
"123 Main St",
"Springfield",
"IL",
"62701",
"US",
"123 Main St", // Duplicate? Or billing?
"Springfield",
"IL", // Did I put state in the right spot?
"62701",
"US",
"card",
"tok_123",
null, // No coupon
false, // gift wrap?
null, // gift message
"Leave at door",
true // is express?
);
Fixed Code
// Fixed: Using parameter objects and builder pattern
public class FixedUserService {
// Fixed: Parameter object groups related data
public User createUser(UserCreationRequest request) {
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(request.getPassword());
user.setEmail(request.getEmail());
user.setProfile(request.getProfile());
user.setAddress(request.getAddress());
user.setAdmin(request.isAdmin());
return user;
}
}
// Fixed: Builder pattern for complex object construction
public class UserCreationRequest {
private final String username;
private final String password;
private final String email;
private final UserProfile profile;
private final Address address;
private final boolean isAdmin;
private UserCreationRequest(Builder builder) {
this.username = builder.username;
this.password = builder.password;
this.email = builder.email;
this.profile = builder.profile;
this.address = builder.address;
this.isAdmin = builder.isAdmin;
}
// Getters...
public static class Builder {
// Required parameters
private final String username;
private final String password;
private final String email;
// Optional parameters with defaults
private UserProfile profile = new UserProfile();
private Address address = null;
private boolean isAdmin = false; // Secure default!
public Builder(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public Builder profile(UserProfile profile) {
this.profile = profile;
return this;
}
public Builder address(Address address) {
this.address = address;
return this;
}
public Builder admin(boolean isAdmin) {
this.isAdmin = isAdmin;
return this;
}
public UserCreationRequest build() {
return new UserCreationRequest(this);
}
}
}
// Fixed: Clear, readable call site
UserCreationRequest request = new UserCreationRequest.Builder(
"johndoe", "SecurePass123!", "[email protected]")
.profile(new UserProfile("John", "Doe", "+1234567890"))
.address(new Address("123 Main St", "Springfield", "IL", "62701", "US"))
.admin(false) // Explicitly named - no confusion!
.build();
User user = userService.createUser(request);
# Fixed: Using dataclasses and keyword arguments
from dataclasses import dataclass, field
from typing import Optional, List, Dict
@dataclass
class EmailMessage:
"""Parameter object for email configuration"""
sender: str
recipient: str
subject: str
body: str
cc: Optional[List[str]] = None
bcc: Optional[List[str]] = None
html_body: Optional[str] = None
attachments: List[str] = field(default_factory=list)
@dataclass
class EmailOptions:
"""Separate object for email options"""
priority: str = "normal"
read_receipt: bool = False
delivery_receipt: bool = False
encrypt: bool = False
sign: bool = False
custom_headers: Dict[str, str] = field(default_factory=dict)
def fixed_send_email(message: EmailMessage, options: Optional[EmailOptions] = None):
"""
Fixed: Two clear parameter objects instead of 14 parameters.
"""
options = options or EmailOptions()
# Implementation using message and options
pass
# Fixed: Clear, self-documenting call site
message = EmailMessage(
sender="[email protected]",
recipient="[email protected]",
subject="Important Update",
body="Please review the attached document.",
cc=["[email protected]"]
)
options = EmailOptions(
priority="high",
encrypt=True, # Clearly named!
sign=True # No confusion!
)
fixed_send_email(message, options)
// Fixed: Using parameter objects and records
public class FixedPaymentProcessor
{
public PaymentResult ProcessPayment(PaymentRequest request)
{
// Single parameter object contains everything needed
ValidateRequest(request);
return ExecutePayment(request);
}
}
// Fixed: Immutable record types for parameter groups
public record CardDetails(
string CardNumber,
string CardHolderName,
int ExpirationMonth,
int ExpirationYear,
string Cvv
);
public record BillingAddress(
string Street,
string City,
string State,
string ZipCode,
string Country
);
public record PaymentOptions
{
public bool SaveCard { get; init; } = false;
public bool UseThreeDS { get; init; } = true; // Secure default
public string? ReturnUrl { get; init; }
public string? CancelUrl { get; init; }
public Dictionary<string, string>? Metadata { get; init; }
}
public record PaymentRequest(
CardDetails Card,
decimal Amount,
string Currency,
string MerchantId,
string OrderId,
string CustomerEmail,
BillingAddress BillingAddress,
PaymentOptions? Options = null
);
// Fixed: Clear, readable usage
var request = new PaymentRequest(
Card: new CardDetails("4111111111111111", "John Doe", 12, 2025, "123"),
Amount: 99.99m,
Currency: "USD",
MerchantId: "merchant_123",
OrderId: "order_456",
CustomerEmail: "[email protected]",
BillingAddress: new BillingAddress("123 Main St", "Springfield", "IL", "62701", "US"),
Options: new PaymentOptions
{
SaveCard = true,
UseThreeDS = true // Named parameter - no confusion
}
);
var result = processor.ProcessPayment(request);
// Fixed: Using options object pattern
class OrderRequest {
constructor({
customer,
items,
shipping,
billing = null, // Optional, defaults to shipping
payment,
options = {}
}) {
this.customer = customer;
this.items = items;
this.shipping = shipping;
this.billing = billing || shipping;
this.payment = payment;
this.options = {
couponCode: null,
giftWrap: false,
giftMessage: null,
deliveryInstructions: null,
isExpress: false,
...options
};
}
}
function fixedCreateOrder(request) {
// Single parameter object
validateOrder(request);
return processOrder(request);
}
// Fixed: Clear, self-documenting call with named properties
const order = new OrderRequest({
customer: {
id: "cust123",
email: "[email protected]"
},
items: [
{ productId: "prod1", quantity: 2 }
],
shipping: {
address: "123 Main St",
city: "Springfield",
state: "IL",
zip: "62701",
country: "US"
},
payment: {
method: "card",
token: "tok_123"
},
options: {
isExpress: true,
deliveryInstructions: "Leave at door"
}
});
const result = fixedCreateOrder(order);
CVE Examples
This CWE is marked as PROHIBITED for direct CVE mapping as it represents a code quality/design concern rather than a direct security vulnerability.
Related CWEs
- CWE-710: Improper Adherence to Coding Standards (parent)
- CWE-1120: Excessive Code Complexity (related)
- CWE-1226: Complexity Issues (category member)
References
- MITRE Corporation. "CWE-1064: Invokable Control Element with Signature Containing an Excessive Number of Parameters." https://cwe.mitre.org/data/definitions/1064.html
- Martin, Robert C. "Clean Code: A Handbook of Agile Software Craftsmanship."
- Fowler, Martin. "Refactoring: Improving the Design of Existing Code."