Version / branch / commit
Audited on main at 903e3d13 (2026-08-23).
Problem
edit_file promises that old_string must match byte-for-byte, but blockAnchorReplacer falls back to matching the first and last lines plus an average interior similarity threshold of 0.65. It then replaces the entire on-disk span even when the interior differs from old_string.
Reproduction
Given an on-disk block containing:
func a() {
x := 1
y := 2
z := 3
return
}
request an edit whose old_string is identical except for y := 99. The fuzzy matcher accepts the block and reports success, replacing the real y := 2 line even though the requested old content never existed.
Expected behavior
A drifted interior must make the edit fail or require an exact re-read/retry. The tool must not discard content that differs from old_string.
Actual behavior
The whole span is replaced and the tool reports Successfully edited (replaced 1 occurrence).
Relevant code
internal/tools/edit_replacers.go:30,154-249,466-481
internal/tools/edit_file.go:109-131
Suggested fix
Reject fuzzy block matches when any interior line materially differs from the requested old block. Add a regression test using the y := 2 / y := 99 drift case and prove it fails before the fix.
Version / branch / commit
Audited on
mainat903e3d13(2026-08-23).Problem
edit_filepromises thatold_stringmust match byte-for-byte, butblockAnchorReplacerfalls back to matching the first and last lines plus an average interior similarity threshold of 0.65. It then replaces the entire on-disk span even when the interior differs fromold_string.Reproduction
Given an on-disk block containing:
request an edit whose
old_stringis identical except fory := 99. The fuzzy matcher accepts the block and reports success, replacing the realy := 2line even though the requested old content never existed.Expected behavior
A drifted interior must make the edit fail or require an exact re-read/retry. The tool must not discard content that differs from
old_string.Actual behavior
The whole span is replaced and the tool reports
Successfully edited (replaced 1 occurrence).Relevant code
internal/tools/edit_replacers.go:30,154-249,466-481internal/tools/edit_file.go:109-131Suggested fix
Reject fuzzy block matches when any interior line materially differs from the requested old block. Add a regression test using the
y := 2/y := 99drift case and prove it fails before the fix.