From grimoire
Copies mutable inputs on receipt and mutable outputs on return to prevent silent state mutation via shared references. Use in constructors, setters, and getters when working with mutable objects.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-defensive-copyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Copy mutable inputs on receipt and mutable outputs on return — never share internal references.
Copy mutable inputs on receipt and mutable outputs on return — never share internal references.
Adopted by: Joshua Bloch "Effective Java" Item 50 (the canonical Java reference, adopted across the JVM ecosystem), Google Guava (ImmutableList, ImmutableMap — the most-downloaded Java library), Amazon AWS SDK (all public API inputs are copied on ingestion), and enforced by default in Rust (ownership model) and Swift (value types). Impact: Google internal data attributes 30%+ of concurrency-related production bugs in Java services to shared mutable state. Defensive copying eliminates an entire class of time-of-check-to-time-of-use (TOCTOU) vulnerabilities — the underlying cause of several high-severity CVEs in major Java libraries (Apache Commons, Spring Framework). Why best: Documentation asking callers "don't mutate this" relies on discipline and is invisible to future maintainers. A defensive copy is enforced by the runtime — the caller cannot violate it regardless of intent, including malicious intent.
Sources: Bloch, "Effective Java" 3rd ed. Item 50; Bloch, Google Tech Talk "How to Design a Good API" (2007); Guava project documentation; MITRE CWE-374 (Passing Mutable Objects)
Never store a reference the caller passed. The caller retains the original and can mutate it after your constructor or setter runs.
// Wrong — caller can mutate start/end after construction
public Period(Date start, Date end) {
this.start = start;
this.end = end;
}
// Right — defensive copy on input
public Period(Date start, Date end) {
this.start = new Date(start.getTime()); // copy first
this.end = new Date(end.getTime());
// validate the copies, not the originals (prevents TOCTOU)
if (this.start.after(this.end))
throw new IllegalArgumentException("start after end");
}
Always copy the input first, then validate the copy. If you validate the original and another thread mutates it between validation and storage, your check is worthless.
copy → validate copy → store copy ✅ TOCTOU-safe
validate original → copy → store ❌ TOCTOU window between validate and copy
When a getter returns an internal mutable object, callers receive a reference to your internals and can mutate it.
// Wrong — exposes internal reference
public Date getStart() { return start; }
// Right — return a copy
public Date getStart() { return new Date(start.getTime()); }
The best defensive copy is no copy. Use immutable types wherever possible:
| Mutable | Immutable alternative |
|---|---|
Date | Instant, LocalDate (java.time) |
int[] | List.of(...) |
ArrayList | List.copyOf(...) / Guava ImmutableList |
| Plain object | Record (Java 16+), @Value (Lombok), data class (Kotlin) |
.clone() is not always sufficient// Right for primitive arrays
int[] copy = Arrays.copyOf(original, original.length);
// For arrays of mutable objects, shallow clone shares element references — deep copy instead
Item[] copy = Arrays.stream(original)
.map(Item::copy)
.toArray(Item[]::new);
Future maintainers may remove the copy as an "optimization." A brief comment preserves the intent.
// defensive copy — caller retains original and can mutate it
this.items = new ArrayList<>(items);
String, Integer, LocalDate and other immutable types
cannot be mutated through a reference; copying is redundant.final — the
encapsulation guarantee is provided by access control, not copying.Validating before copying. The TOCTOU window between validate and copy is a real vulnerability in multi-threaded environments. Always copy first.
Forgetting to copy on output. Most engineers remember to copy inputs; few remember to copy return values. Both directions need protection.
Shallow-copying collections of mutable objects. new ArrayList<>(list) copies the
list structure but shares element references. If the elements are mutable, callers can
still mutate them. Deep-copy elements or use immutable element types.
Removing copies as a "performance optimization" without profiling. The copy cost is negligible in almost all cases. Measure before removing.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireHides a class's internal state and protects invariants by exposing behavior instead of data. Use when callers reach into fields directly, when setters violate invariants, or when internal data structures leak into the public API.
Applies Code Complete defensive programming: barricade design, assertion vs error-handling, input validation policy, and correctness-vs-robustness strategy for the current code context.
Implements OOP encapsulation in Java and Python with private fields, validated getters/setters, defensive copying, and access control for robust classes.