Skip to content

The __search companion column, declared client-invisible, is echoed in every record body #7642

Description

@huangyiirene

Symptom

The __search companion column — declared invisible to clients — is echoed in every record body: query results, GET by id, /search hits, and the 201 create body. Still present after restarting with OS_SEARCH_PINYIN_ENABLED=false.

The $searchFields-override half of the contract IS correctly enforced (supplying __search as an override → 400 "is hidden"); only the default-projection strip is missing.

Root cause

packages/objectql/src/search-companion.ts provisions the column hidden + system + readonly + searchable:false. Those flags only keep it out of auto-views, the $search auto-default, and $searchFields overrides — no read path strips it from the default projection, so hidden system columns come back (as organization_id does).

Confirmed still present on origin/main (76d74ecb): the provisioning (lines 151–154) still sets hidden / readonly / system / searchable:false, with no default-projection strip on any read path.

Impact

Disclosure risk is low — the value derives from the display field only, and secret/FLS-restricted sources are excluded. But the declared client-invisibility contract is broken and every payload carries a private index column.

Reproduction

POST /api/v1/data/showcase_contact/query {"search":"zhangwei","limit":1}
  → the returned record contains "__search":"zhangwei zw"
GET  /api/v1/data/showcase_account/
  → "__search":"huaningkeji hnkj"
GET  /api/v1/search?q=INV-1003
  → each hit.record carries a __search key

The 201 body of a create carries it too. Still echoed after restarting with OS_SEARCH_PINYIN_ENABLED=false.

Source

Extracted from the QA run #7629 (framework 92f26f7, console 6314e87f).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions