CWE-580 describes a Java clone() method that does not call super.clone() to obtain the new object.
The Java contract says all implementations of clone() should get the new object from super.clone(). If a class builds the copy with new instead, a subclass's clone() returns an object of the wrong type.
MITRE lists the consequences as integrity impact and unexpected state, along with quality degradation.
How it happens
MITRE's example uses two classes, Kibitzer and FancyKibitzer. Kibitzer implements clone() by constructing a new Kibitzer:
public class Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = new Kibitzer(); // hard codes the type
...
return returnMe;
}
}
public class FancyKibitzer extends Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = super.clone();
...
return returnMe;
}
}
FancyKibitzer.clone() calls super.clone(), which reaches Kibitzer.clone(). That returns a plain Kibitzer. Code that casts the result to FancyKibitzer throws a ClassCastException, and code that does not cast silently loses the subclass behavior and fields.
What an attacker gains
MITRE lists unexpected state and integrity impact. The danger is indirect. A copy that is the wrong type may skip subclass validation or security checks, or carry shared mutable state. If clones are used to hand out defensive copies of sensitive objects, a bad clone undermines that protection.
How to find it
MITRE says automated static analysis can find some instances. Look for clone() methods that contain new and no super.clone() call, and add a test that clones a subclass instance and asserts the result's class.
How to fix it
MITRE gives two mitigations:
- Call
super.clone()within yourclone()method when obtaining a new object. - In some cases, remove the
clonemethod altogether and use copy constructors.
// Fixed
public class Kibitzer implements Cloneable {
@Override
public Kibitzer clone() throws CloneNotSupportedException {
return (Kibitzer) super.clone();
}
}
// Alternative: copy constructor, no cloning machinery
public Kibitzer(Kibitzer other) {
this.name = other.name;
}
Copy constructors are usually easier to reason about. Whichever you choose, deep copy any mutable fields so the clone does not share state with the original.
The free in-browser scan at gold.safeguard.sh/scan lists the dependencies in your manifest. No login is needed, the file stays on your machine, and it handles up to 100 dependencies.
Quick check
What goes wrong without super.clone()?
The clone is created as the superclass type, so subclasses get an object of the wrong type.
Is there an alternative to clone()?
Yes. MITRE suggests copy constructors in some cases.