fix(mcp): validate the claim envelope before brain_edit writes too #136
@@ -268,6 +268,27 @@ func touchesFrontmatter(oldStr, newStr string) bool {
|
|||||||
// those cases at write time regardless of what this function decides, so
|
// those cases at write time regardless of what this function decides, so
|
||||||
// the only thing riding on this preview's accuracy is the envelope check
|
// the only thing riding on this preview's accuracy is the envelope check
|
||||||
// itself, not write safety.
|
// itself, not write safety.
|
||||||
|
// checkClaimEnvelope previews what old_str->new_str would produce and
|
||||||
|
// validates the resulting claim envelope before the real edit runs
|
||||||
|
// (hyperguild#123). Seven review rounds closed every plausible bypass in the
|
||||||
|
// fence-detection family (field-name substring, block-containment,
|
||||||
|
// fence-stripping, CRLF, UTF-8 BOM) and the first instance of a
|
||||||
|
// value-extraction gap (a folded YAML block scalar hiding a value behind an
|
||||||
|
// empty inline colon).
|
||||||
|
//
|
||||||
|
// Known, accepted v1 gap: frontmatterScalars's block-scalar fold is a
|
||||||
|
// best-effort approximation, not a YAML parser — a blank line interrupting a
|
||||||
|
// folded continuation, or other contrived multi-line YAML shapes not yet
|
||||||
|
// probed (block-scalar indicators `|`/`>`, inline comments on a key line,
|
||||||
|
// quoted multi-line values), can still hide an invalid value from
|
||||||
|
// ValidateEnvelope. Accepted deliberately rather than chased indefinitely:
|
||||||
|
// every bypass found so far requires the caller to already hold brain_edit
|
||||||
|
// write access and to deliberately construct a specific malformed-YAML shape
|
||||||
|
// with knowledge of this exact gap — a narrow, low-likelihood threat next to
|
||||||
|
// the diminishing returns of another incremental patch round. The real fix
|
||||||
|
// (a shared, tested, encoding-normalized frontmatter parser used by all
|
||||||
|
// three independent implementations in this codebase) is tracked separately
|
||||||
|
// as hyperguild#138, not bolted on here piece by piece.
|
||||||
func checkClaimEnvelope(brainDir, path, oldStr, newStr string) error {
|
func checkClaimEnvelope(brainDir, path, oldStr, newStr string) error {
|
||||||
if oldStr == "" {
|
if oldStr == "" {
|
||||||
// hyperguild#115: strings.Replace treats "" as matching position 0,
|
// hyperguild#115: strings.Replace treats "" as matching position 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user