SI2 — DOCUMENTED OMISSION: the cross-USER statusUpdates leak (SEC6) and the unfiltered
cacheInvalidation broadcast (SEC7) are NOT headlessly reproducible here. This check does not
assert against a fabricated surface — it records precisely WHY, so the gap is visible in every run
and a future harness (a real dual-identity WS rig) knows exactly what to build. It is a skip-as-pass
marker for a GENUINE gap, not a filler assertion.
THE TWO FINDINGS (research-confirmed against @memberjunction/server):
• SEC6 — PushStatusResolver.statusUpdates filters payload.sessionId === args.sessionId, trusting
the CLIENT-SUPPLIED sessionId subscription variable. The WS connection context's own sessionId
is hard-wired to 'default' (context.ts getUserPayload is called with an undefined sessionId),
so the server never compares against the authenticated identity. A subscriber that passes another
user's sessionId (GraphQLDataProvider.PushStatusUpdates(<victim sessionId>)) receives that
user's payloads. Reproduction needs TWO authenticated identities on one live socket; the
integration client authenticates with a SINGLE system API key, so it cannot mint a second victim.
• SEC7 — CacheInvalidationResolver.cacheInvalidation has NO filter; every connected browser
receives every tenant's entity-change events, and the payload includes RecordData
(a full GetAll() of the mutated row). Characterizing the cross-tenant broadcast requires two
authenticated sockets on distinct tenants — again beyond the single-identity client transport.
WHY NOT ASSERT THE FILTERS DIRECTLY: both filters are inline arrow functions inside @Subscription
decorators in @memberjunction/server (not separately exported). Importing that package into a check
file is impossible — its barrel validates DB config at module load and throws when absent, which
would crash this package's registry unit tests (they import the barrel with no DB configured). SI1
already exercises the ONE channel (RemoteOperationProgress) whose isolation IS reachable over the
wire; these two remain a documented live-WS omission.
SI2 — DOCUMENTED OMISSION: the cross-USER
statusUpdatesleak (SEC6) and the unfilteredcacheInvalidationbroadcast (SEC7) are NOT headlessly reproducible here. This check does not assert against a fabricated surface — it records precisely WHY, so the gap is visible in every run and a future harness (a real dual-identity WS rig) knows exactly what to build. It is a skip-as-pass marker for a GENUINE gap, not a filler assertion.THE TWO FINDINGS (research-confirmed against
@memberjunction/server): • SEC6 —PushStatusResolver.statusUpdatesfilterspayload.sessionId === args.sessionId, trusting the CLIENT-SUPPLIEDsessionIdsubscription variable. The WS connection context's own sessionId is hard-wired to'default'(context.tsgetUserPayloadis called with an undefined sessionId), so the server never compares against the authenticated identity. A subscriber that passes another user's sessionId (GraphQLDataProvider.PushStatusUpdates(<victim sessionId>)) receives that user's payloads. Reproduction needs TWO authenticated identities on one live socket; the integration client authenticates with a SINGLE system API key, so it cannot mint a second victim. • SEC7 —CacheInvalidationResolver.cacheInvalidationhas NOfilter; every connected browser receives every tenant's entity-change events, and the payload includesRecordData(a fullGetAll()of the mutated row). Characterizing the cross-tenant broadcast requires two authenticated sockets on distinct tenants — again beyond the single-identity client transport.WHY NOT ASSERT THE FILTERS DIRECTLY: both filters are inline arrow functions inside
@Subscriptiondecorators in@memberjunction/server(not separately exported). Importing that package into a check file is impossible — its barrel validates DB config at module load and throws when absent, which would crash this package's registry unit tests (they import the barrel with no DB configured). SI1 already exercises the ONE channel (RemoteOperationProgress) whose isolation IS reachable over the wire; these two remain a documented live-WS omission.