CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
Overview
This vulnerability occurs when user input is used to modify object attributes or properties dynamically, allowing attackers to alter application behavior or access unauthorized data.
Related: Mass assignment (CWE-915) controls which properties can be modified. For ASP.NET applications, also see CWE-1174 which validates the values of properties that users are allowed to set.
OWASP Classification
A08:2025 - Software or Data Integrity Failures
Risk
High: Attackers can escalate privileges, bypass security controls, or corrupt data by manipulating object attributes at runtime.
Remediation Steps
Core principle: Never allow mass assignment of object attributes; bind/allowlist permitted fields and enforce invariants server-side.
Locate the dynamically-determined object attribute modification
- Review the flaw details to identify the specific file, line number, and code pattern
- Understand the data flow from source to sink: where user input influences object attributes
- Identify the source: HTTP parameters, JSON input, form data, external configuration
- Trace to the sink:
setattr(),__dict__,obj[user_input] =,Object.defineProperty(), mass assignment - Determine risk: can attacker modify security-critical attributes (isAdmin, role, price, balance)
Restrict attribute modification to allowed properties (Primary Defense)
- Use allowlist of permitted attributes:
ALLOWED_ATTRS = {'name', 'email', 'phone'} - Validate attribute name before modification:
if attr_name not in ALLOWED_ATTRS: raise ValueError - Reject unauthorized properties: Block attempts to set attributes not in allowlist
- Never use user input directly as attribute name: Don't do
setattr(obj, user_input, value) - Use explicit setters: Prefer
obj.set_name(value)oversetattr(obj, 'name', value) - Why this works: Attacker can only modify pre-approved, non-security-critical attributes
Validate and sanitize attribute names and values
- Enforce strict type checks: Verify attribute values match expected type (string, int, boolean)
- Apply length and format validation: Limit string length, validate email/phone formats
- Sanitize values: Remove dangerous characters, encode special characters
- Check attribute name format: Use regex to ensure attribute names are alphanumeric only
- Reject special attributes: Block
__class__,__dict__,__init__,constructor,prototype
Use safe APIs for object manipulation (Defense in Depth)
- Prefer explicit setters/methods: Use
obj.setName(),obj.setEmail()instead of dynamic assignment - Use immutable objects: Use frozen dataclasses, namedtuples, or read-only properties where possible
- Avoid dynamic features with untrusted input: Don't use
setattr,__dict__,eval,getattrwith user input - Use frameworks with built-in protection: ORM allowlists (Django
fields, Railspermit), schema validation - Implement property decorators: Use
@propertyand explicit setters to control attribute access
Monitor and audit attribute changes
- Log all dynamic attribute modifications with attribute name, value, and source
- Alert on suspicious changes (attempts to modify security-critical attributes like
isAdmin,role,permissions) - Track rejected modification attempts (blocked by allowlist)
- Monitor for unusual patterns (bulk attribute changes, rapid modifications)
- Audit security-sensitive object changes (user roles, permissions, pricing)
Test the attribute control fix thoroughly
- Test with allowed attributes (should work:
name,email,phone) - Test with forbidden attributes (should be rejected:
isAdmin,role,__class__) - Test attribute injection:
isAdmin=true,role=administrator,price=0 - Test special Python/JavaScript attributes:
__dict__,prototype,constructor - Verify legitimate functionality still works (profile updates, settings changes)
- Re-scan with security scanner to confirm the issue is resolved
Common Vulnerable Patterns
- Using user input to set object attributes directly
- Allowing arbitrary property modification via APIs
Dynamic Attribute Assignment from User Input (Pseudocode)
Why this is vulnerable: Allowing user input to directly control which object attributes are modified enables attackers to set arbitrary properties including sensitive fields like is_admin, role, or password_hash, leading to privilege escalation, authentication bypass, or data corruption through mass assignment attacks.
Secure Patterns
Allowlist-Based Attribute Assignment (Pseudocode)
# Safe: use allowlist for attributes
allowed_attrs = {'name', 'email', 'phone'}
if user_input in allowed_attrs:
setattr(obj, user_input, value)
else:
raise SecurityError('Attribute not allowed')
Why this works:
- Restricts attribute modification to pre-approved properties, preventing privilege escalation
- Blocks attackers from modifying sensitive fields like
is_admin,role, orpassword_hash - Prevents mass assignment vulnerabilities where attackers set unauthorized object properties
- Ensures only intended user-modifiable fields can be changed via API or form submissions
- Protects against prototype pollution in JavaScript and similar attribute manipulation attacks