Summary
Retracted Verifiable Presentations (retraction markers with type RetractedVerifiablePresentation) leak into Discovery Service search results when the search query is empty (or omits credential-based filters).
Endpoint
GET /internal/discovery/v1/{serviceID}
Root cause
When a retraction VP is registered, sqlStore.add (discovery/store.go:169) deletes the previous VP for the subject and stores the retraction marker VP in its place. The retraction marker has no credentials.
sqlStore.search (discovery/store.go:268) filters by service_id and validated, and only joins discovery_credential when the caller passes a non-empty query map. With an empty query, no credential join happens, and the retraction marker — which has zero credentials — is returned as a regular result.
Module.Search (discovery/module.go:484) then returns the retraction VP as a SearchResult with an empty Fields map (a PEX match failure is only logged, not filtered).
The server-side Get() timeline correctly keeps retraction markers (they're required for replication), so the fix must be limited to the search path.
Expected behavior
Retraction markers must never appear in Discovery Service search results — they are a protocol-level signal, not discoverable data.
Reproduction
Register a VP, then register a retraction for it, then call Search with an empty query. The retraction marker is returned.
Fix
Post-search filter on IsType(RetractedVerifiablePresentation) in sqlStore.search's result-assembly loop. A SQL-level filter would require a schema migration (no retraction column exists on presentationRecord).
Summary
Retracted Verifiable Presentations (retraction markers with type
RetractedVerifiablePresentation) leak into Discovery Service search results when the search query is empty (or omits credential-based filters).Endpoint
GET /internal/discovery/v1/{serviceID}Root cause
When a retraction VP is registered,
sqlStore.add(discovery/store.go:169) deletes the previous VP for the subject and stores the retraction marker VP in its place. The retraction marker has no credentials.sqlStore.search(discovery/store.go:268) filters byservice_idandvalidated, and only joinsdiscovery_credentialwhen the caller passes a non-empty query map. With an empty query, no credential join happens, and the retraction marker — which has zero credentials — is returned as a regular result.Module.Search(discovery/module.go:484) then returns the retraction VP as aSearchResultwith an emptyFieldsmap (a PEX match failure is only logged, not filtered).The server-side
Get()timeline correctly keeps retraction markers (they're required for replication), so the fix must be limited to the search path.Expected behavior
Retraction markers must never appear in Discovery Service search results — they are a protocol-level signal, not discoverable data.
Reproduction
Register a VP, then register a retraction for it, then call Search with an empty query. The retraction marker is returned.
Fix
Post-search filter on
IsType(RetractedVerifiablePresentation)insqlStore.search's result-assembly loop. A SQL-level filter would require a schema migration (no retraction column exists onpresentationRecord).