Do not expose references to mutable objects to client code. Never initialize such a field to a client-provided object reference or return the object reference from an accessor. Exposing a public static final object allows clients to modify the contents of the object (although they will not be able to change the object itself, as it is final).
This rule does not address private mutable objects, see rule OBJ05-J. Do not return references to private mutable class members for more information.
Noncompliant Code Example
Suppose that SomeType
is immutable.
public static final SomeType [] SOMETHINGS = { ... };
Even though SomeType
is immutable, this declaration allows the SOMETHINGS
array to be modified by untrusted clients of the code. Any element of the array can be assigned a new value, namely a reference to a new SomeType
object.
This noncompliant code example also violates OBJ01-J. Limit accessibility of fields.
Noncompliant Code Example (getter method)
This noncompliant code example complies with OBJ01-J. Limit accessibility of fields by declaring the array private. But, in declaring the array private, this code example violates OBJ05-J. Do not return references to private mutable class members.
Suppose that SomeType
is immutable.
private static final SomeType [] SOMETHINGS = { ... }; public static final getSomethings() {return SOMETHINGS;}
Even though SomeType
is immutable, the public getter method enables untrusted clients to modify the SOMETHINGS
array. Any element of the array can be assigned a new value, namely a reference to a new SomeType
object.
Compliant Solution (clone)
Continuing with the assumption that SomeType
is immutable, one approach is to have a private array and a public method that returns a copy of the array:
private static final SomeType [] SOMETHINGS = { ... }; public static final SomeType [] somethings() { return SOMETHINGS.clone(); }
Now, the original array cannot be modified by any client. If SomeType
were mutable, this approach would not be effective because the array clone references the same SomeType
objects as the SOMETHINGS
array. If the client modified the clone SomeType
objects directly, the SomeType
objects referenced by the SOMETHINGS
array would also change.
Compliant Solution (Unmodifiable List)
Continuing with the assumption that SomeType
is immutable, an alternative approach is to have a private array from which a public immutable list is constructed:
private static final SomeType [] THE_THINGS = { ... }; public static final List<SomeType> SOMETHINGS = Collections.unmodifiableList(Arrays.asList(THE_THINGS));
Now, neither the original array values nor the public list can be modified by a client. If SomeType
were mutable, this would not be effective because the list references the same SomeType
objects as the SOMETHINGS
array. The unmodifiabileList
prevents the list from being modified, not the elements in the list. If the client modified the list's SomeType
objects directly, the SomeType
objects referenced by the SOMETHINGS
array would also change.
Risk Assessment
Having a public static final array is a potential security risk because the array elements may be modified by a client.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
OBJ13-J | Medium | Likely | Low | P18 | L1 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Parasoft Jtest | 2024.1 | CERT.OBJ13.RMO | Avoid referencing mutable fields |
SonarQube | 9.9 | ||
SpotBugs | 4.6.0 | MS_EXPOSE_REP | Implemented (since 4.3.0) |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
References
[Bloch 2008] | Item 13, "Minimize the Accessibility of Classes and Members" |
[JLS 2015] | §6.6, "Access Control" |
17 Comments
David Svoboda
Ahh, once again a Java programmer laments the absence of the 'const' keyword
This rule suffers from a hidden assumption. I think it is trying to say final != const, assuming that programmers would assume the opposite. I'll admit to being out of touch with the Java communitity as of late, but I thought any programmar who knew of the 'final' keword knew it does not promise immutability.
Furthermore the final!=const problem is not limited to Java arrays, but pertains to any public field member that is also an object (and not a primiitve type like int). If class A has a public (or protected) object b of class B, then if you can access object b, you can modify it, even if A is final. This is a well-known issue of the 'final' keyword.
G. Ann Campbell
Am I wrong in thinking that this is a specialization of OBJ01-J. Limit accessibility of fields?
G. Ann Campbell
To answer my own question: there's overlap, but this is broader in that it includes what's returned from methods as well.
Robert C. Seacord
But of course there is also OBJ05-J. Do not return references to private mutable class members
Steve Gertz
Please update risk assessment to reflect OBJ13-J
David Svoboda
Done
Jérôme GUY
As I read this rules, the begining seems to refer to OBJ05-J OBJ05-J. Do not return references to private mutable class members
"Do not expose references to mutable objects to client code. Never initialize such a field to a client-provided object reference or return the object reference from an accessor."
Next, explanation and samples is more about static fields.
So, i would put the firsts two setences into OBJ05-J. Do not return references to private mutable class members and delete them here.
David Svoboda
The two rules are similar but distinct. I've added sentences to the intros of both rules, so they cross-reference each other and explain why they are distinct.
Jérôme GUY
OK, Thanks !
That feels good
Diarmuid Healy
Both compliant code examples state "Now, the original array values cannot be modified by a client.", however in both cases only the reference in the array cannot be changed the state of the referenced object can be changed the same as if a client had access to the original array.
As I have read it, I took this phrasing to imply that the "SomeType" objects in the array were somehow made immutable which is untrue/incorrect.
If I have read this correctly, the examples should be changed or replaced - probably a deep copy/clone of each item in the array is necessary.
If I have misread this, then probably it would be good to include an explicit statement that the mutable "SomeType" state is still modifiable.
David Svoboda
You're right, these examples were problematic. Part of the problem is the mutability of SomeType vs the mutability of the array itself.
I fixed this by declaring SomeType to be immutable, and focusing just on the mutability of the array.
Diarmuid Healy
Thanks, with the specified precondition on the immutable "SomeType" it is now pretty clear on the intent here.
Perhaps for completeness it may be worth including an explicit statement that it will not protect mutable elements in an unmodifiable collection / cloned array, but it is probably sufficient as-is.
However, this rule is now nearly identical in content, and it would seem also intent, to the final section of OBJ01-J. Limit accessibility of fields - "Noncompliant Code Example (Public Final Array)". Only difference appears to be that OBJ01-J provides an additional compliant solution with index getter method.
David Svoboda
This rule and OBJ01-J are very similar, but distinct. This rule is about preventing mutable objects (esp arrays and containers) from client code, not just about declaring data fields private.
Granted that this rule could use another noncompliant code example, which violates this rule but not OBJ01-J. For example, if the array were private, yet provided a public getter method.
David Svoboda
I added this noncompliant code example, which should illustrate how this rule varies from OBJ01-J.
Robert Schiela
As it turns out, we discussed adding explicit statements for completeness yesterday while you were adding the comment. We just didn't get to changing the text until today. Thanks for the suggestion.
Michael Li
The difference of this rule to OBJ05-J is not that clear yet. This rule claims that "This rule does not address private mutable objects, see rule OBJ05-J", but the following examples give non-compliant example about private mutable field. I get confused now. So is this rule only cares about static mutable objects, and OBJ05-J cares only about non-static private mutable objects?
David Svoboda
Not quite. The first noncompliant code example violates this rule but not OBJ05-J.
The second noncompliant code example, which is clearly an attempt to mitigate the first, does violate OBJ05-J. I added some text to explain it.
This rule is still distinct from OBJ05-J, because it addresses leakage of mutable data by means other than returning references to private data (OBJ05-J).