Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Recall that immutability offers several benefits such as thread-safety, prevention against inadvertent modification of fields, and malicious tampering. Class invariants and state of immutable objects are always consistent with their requirements, so no defensive copying is necessary. However, sometimes it is not possible to make sensitive classes immutable. Fortunately, there is a mechanism that allows code to expose mutable classes to untrusted code by granting read-only access. This is largely achieved through unmodifiable wrappers. For example, the Collection classes include a set of wrappers that allow clients to observe an unmodifiable view of the particular Collection object.

Noncompliant Code Example

This noncompliant code example consists of class Modifiable, which allows the internal ArrayList object to be modified. An untrusted invoker may call the mutator method listIt() and violate the object's immutability property.

Code Block
bgColor#FFcccc
class Modifiable {	
  private List<Integer> list = new ArrayList<Integer>();

  public void listIt() {
    addSomething(list);
    // ...
  }

  private void addSomething(Collection<Integer> collection) {
    collection.add(1); 
  }
}

Compliant Solution

This compliant solution recommends an unmodifiable wrapper to shield the mutator method(s) and provide an unmodifiable view to the caller. Internally, the unmodifiable Collection's mutator methods are designed to throw an UnsupportedOperationException in such events.

Code Block
bgColor#ccccff
// ...
public void listIt() {
  addSomething(Collections.unmodifiableCollection(list));
  // ...
}

private void addSomething(Collection<Integer> collection) {
  collection.add(1); // throws java.lang.UnsupportedOperationException
} 

It should be noted that objects present within the Collection may not be thread-safe, making them mutable in multithreaded contexts. Consider, for example, an ArrayList of ArrayLists wherein the contained ArrayList is still susceptible to modification.

Noncompliant Code Example

This noncompliant code example shows an interface MutableInterface that declares an accessor and a mutator method. This class does not expose an unmodifiable view to implementing clients.

Code Block
bgColor#FFcccc
interface MutableInterface {
  int[] getArray(); // accessor
  void setArray(int[] i); //mutator
}

class SensitiveMutable implements MutableInterface {
  int[] array = new int[10]; // mutable array

  public int[] getArray() {
    return array.clone(); 
  }

  public void setArray(int[] i) {
    array = i;
  }
}

Compliant Solution

In general, sensitive classes can be transformed into safe-view objects by implementing all the methods defined by the core interface, including the mutator methods. In this case, the difference is that the mutators need to throw an UnsupportedOperationException so that clients cannot perform operations that affect the immutability property of the object.

This compliant solution constructs an UnmodifiableSensitiveMutable by extending the class SensitiveMutable. An interface UnmodifiableInterface consists of the method unmodifiableView(), which accepts a SensitiveMutable object as the sole parameter. It returns an equivalent object that is a subtype of the same class and is unmodifiable. An exception is thrown if the caller attempts to use the mutator method on the returned object. This object can be passed to untrusted code as required.

Code Block
bgColor#ccccff
interface UnmodifiableInterface {
  SensitiveMutable unmodifiableView(SensitiveMutable sm);
}

class UnmodifiableSensitiveMutable extends SensitiveMutable  {
  int[] array = new int[10];

  public void setArray(int[] i) {
    throw new UnsupportedOperationException();
  }
}

class UnmodifiableWrapper extends UnmodifiableSensitiveMutable implements UnmodifiableInterface {
  public SensitiveMutable unmodifiableView(SensitiveMutable sm) { 
    return new UnmodifiableWrapper(); // subtype of SensitiveMutable
  }
}

class Invoker {
  public static void main(String[] args) {
    UnmodifiableWrapper uw = new UnmodifiableWrapper();
    SensitiveMutable s = uw.unmodifiableView(sm);
    s.setArray(new int[10]); // throws UnsupportedOperationException unlike s.getArray()    
  }
}

Risk Assessment

Failure to provide an unmodifiable safe-view of a sensitive mutable object to untrusted code can lead to malicious tampering and corruption of the object.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

SEC59-JG

medium

probable

high

P4

L3

Automated Detection

Automated detection is not feasible.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Bibliography

[Tutorials 2008] Unmodifiable Wrappers


SEC58-JG. Do not allow unauthorized construction of classes in inaccessible packages      09. Platform Security (SEC)      SEC15-J. Prefer using SSLSockets over Sockets for secure data exchange