CWE-491, Public cloneable() Method Without Final ('Object Hijack'), covers a Java class whose clone method is not declared final. That lets an object be created without calling the constructor, so it can be in an unexpected state. MITRE lists Java.
How it happens
Constructors are where classes run their validation and set up secure defaults. Cloning copies an object without running the constructor. If an attacker can subclass your class and override clone, the attacker controls how the copy is built.
// Vulnerable: clone is public and can be overridden
public class Config implements Cloneable {
private String path;
public Config(String path) {
validate(path);
this.path = path;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
A malicious subclass can produce instances whose fields never went through validate.
What an attacker gains
MITRE lists integrity impact through an unexpected state, with other effects varying by context. Objects that bypass construction may skip every check the constructor performs. The record has no observed CVEs.
How to find it
Static analysis can find some instances. A quick search for classes that implement Cloneable or define clone without the final modifier is also effective.
How to fix it
MITRE's mitigation: make the clone method final.
public final Object clone() throws CloneNotSupportedException {
return super.clone();
}
Declaring the whole class final also stops subclasses, and removing Cloneable in favor of a copy constructor avoids the problem altogether.
Quick check
Why does skipping the constructor matter?
The constructor is where validation and safe initialization happen. An object that never ran it can hold values the class would have rejected.