fix(router): reject an empty reference id instead of matching every one - #718
Draft
vishal-bala wants to merge 1 commit into
Draft
fix(router): reject an empty reference id instead of matching every one#718vishal-bala wants to merge 1 commit into
vishal-bala wants to merge 1 commit into
Conversation
_make_filter_queries built `Tag("reference_id") == id` with no guard, and
Tag renders any falsy value as the match-all `*`. Both callers read the
first row of each query's results, so an empty id resolved to one
arbitrary reference: get_route_references returned a reference nobody
asked for, and delete_route_references deleted one and reported success.
Reproduced on Redis 8.4 against a four-reference router --
delete_route_references(reference_ids=[""]) removed a real reference key
and returned 1.
Raise ValueError at the shared chokepoint, which covers both public
methods and the path that derives ids by splitting stored keys.
Whitespace-only ids are left alone: they render a clause that matches
nothing, so they already fail safe.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
SemanticRouter.delete_route_references(reference_ids=[""])deletes a reference the caller never named._make_filter_queriesbuildsTag("reference_id") == idwith no guard onid, andTagrenders any falsy value as the match-all*. Both callers then read the first row of each query's results, so a match-all resolves to one arbitrary reference:get_route_referencesreturns it, anddelete_route_referencesremoves it.Reproduced against Redis 8.4 with a four-reference router:
The blast radius is one reference per empty id rather than the whole route, because each query carries
LIMIT 0 10and the caller takes onlyr[0]. It is still a silent deletion of data the caller did not ask about, and the reported count of1makes it look like the requested delete succeeded.Changes
An empty reference id is rejected rather than matched
_make_filter_queriesraisesValueErroron a falsy id before constructing the expression. Rejecting rather than skipping is deliberate: an empty id in the list means the caller's own id-building went wrong, and quietly dropping it would hide that while still reporting success for the rest of the batch.Both public methods already raise
ValueErrorfor unusable arguments, so the failure mode is unchanged in kind. The guard sits at the shared chokepoint, which coversget_route_referencesanddelete_route_referencestogether, including the path that derives ids by splitting stored keys.Secondary changes
tests/unit/test_semantic_router_queries.py, a new hermetic file:_make_filter_queriesis a static method that touches neither Redis nor a vectorizer, so a regression this consequential should be caught by a test that always runs rather than one behind the router's integration fixtures.Notes
Whitespace-only ids are deliberately left alone.
Tag("reference_id") == " "renders@reference_id:{\ \ }, which matches nothing rather than everything, so it already fails safe. Widening the guard to cover it would change behaviour without fixing a defect.The guard was mutation-checked: removing it alone fails the three new unit cases and the integration test, and nothing else.
Release Notes
An empty reference id no longer resolves to a match-all filter.
SemanticRouter.get_route_referencesanddelete_route_referencesnow raiseValueErrorwhen passed one, instead of matching every reference in the index.This changes behaviour for callers that pass an empty id, which previously succeeded and now raises. Such a call was always operating on the wrong data: an empty id rendered as a match-all filter, so it resolved to one arbitrary reference.
get_route_referencesreturned a reference that was never requested, anddelete_route_referencesdeleted one and reported success. Code that swallowed the old result now sees an exception instead, which is the point.Calls that pass real reference ids are unaffected, as are whitespace-only ids, which have always matched nothing rather than everything.
Next Steps