Skip to content

update_schema rename_fields persists the rename BEFORE field-name grammar validation runs — invalid field names get committed to schema and all node data, then the caller is told the update failed #2208

Closed

Description

@mstomar125

Summary

Field-name grammar (validate_schema_field_name: alphanumeric/_ with optional single namespace prefix) is enforced on create_schema and on add_fields via SchemaNodeBehavior validation, but handle_update_schema executes renames in Phase 1 (schema/mod.rs:756 → NodeService::rename_schema_field, which checks only from-exists/to-not-taken and writes the schema via update_node_unchecked, bypassing behavior validation) and only validates the resulting field list in Phase 2 (schema/mod.rs:905) — after the rename and its full node-data migration are already durably committed.

Failure scenario

Agent or user calls update_schema {schema_id:"venue", rename_fields:[{from:"capacity", to:"max capacity"}]} (space in name; any character including quotes works). Phase 1 migrates every venue node's properties.venue.capacity to key "max capacity" and rewrites the schema definition unchecked. Phase 2 then fails validate_schema_field_name and returns "Schema validation failed: Invalid field name 'max capacity'" — the caller (an LLM, then the user) is told nothing was applied, but the invalid name is now persisted in the schema and in every node. Every subsequent update_schema call on that schema (add a field, change the description) now fails the same Phase-2 validation on the already-stored bad name, wedging the schema until someone guesses to rename it back; find_conflicting_unique silently disables uniqueness checking for the field (it rejects non-grammar names and returns no-conflict).

Location

packages/core/src/schema/mod.rs:756

Severity

important


Found via a full-repo adversarial bug sweep, independently verified by two separate skeptical reviewers reading the actual current code before filing.

Activity

  1. self-assigned this
    on Aug 21, 2026
  2. mstomar125 commented on Aug 27, 2026

    @mstomar125
    ContributorAuthor

    Fixed in #2304: added a protection-level guard (checked against SchemaProtectionLevel via can_delete_field/can_modify_field) to handle_update_schema's Phase 0 and to the NodeService::rename_schema_field/update_schema_field_friendly_name primitives, so a Core/System-protected field can no longer be removed, renamed, or relabeled through update_schema. Also moved rename-destination grammar validation ahead of the migration/persist step, so a malformed destination name is rejected before anything is written rather than after. Regression tests cover the removal, rename, friendly-name-relabel, and grammar-before-persist scenarios described here. PR is open for review, not yet merged.

  3. mstomar125 commented on Aug 27, 2026

    @mstomar125
    ContributorAuthor

    Fixed in PR #2304 (merged 7528411a), part of the same cluster as #2194. Closing — GitHub's auto-close only picked up the first issue in the PR's comma-separated closing list, closing the rest manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions