VNX-491: Public cloneable() Method Without Final ('Object Hijack')
A Java class that is not final declares a public clone() that is not final and builds its copy with super.clone() within the next few lines. super.clone() creates the object without running a constructor, and because neither the class nor the method is final, a subclass can override clone() and hand out copies that skip the constructor's checks or share mutable internals. Not reported: a final clone() (including one that only throws CloneNotSupportedException), a clone() in a final class or record, a clone() that copies through a constructor rather than super.clone(), a clone overload with parameters, non-public clone methods, and the pattern in comments or string literals.
| Field | Value |
|---|---|
| Rule ID | VNX-491 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java |
| CWE | CWE-491 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | clone object-hijack final cwe-491 |
| Source | internal/sast/rules/vnx-491.rego |
Overview
VNX-491 maps to CWE-491: Public cloneable() Method Without Final (‘Object Hijack’). It reports an overridable public clone() that copies with super.clone() in a class that is not final.
Why This Matters
super.clone() produces an object without running any constructor, so constructor validation never happens for the copy. When the method and the class are both open to extension, a subclass can override clone() to return an object in a state the original class would never allow, or one that shares its mutable internals.
What Gets Flagged
public class Account implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException { // FLAGGED
return super.clone();
}
}
Not flagged: public final Object clone(), a clone() in a final class, and a clone() that returns new Point(x, y).
Remediation
- Declare
clone()final, or make the classfinal. - Prefer a copy constructor or static factory (
Account.copyOf(a)), which runs the constructor’s checks. - If the class must not be cloned, declare
public final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-491
// nosec vnx-491
Or record an ignore rule: vulnetix ignore add --rule vnx-491 --reason "...". See Suppressing findings.