Skip to content

Commit 516610f

Browse files
tbeerenclaude
andcommitted
fix(browser): Strengthen type guard for persisted GraphQL operations
The isPersistedRequest type guard now validates that sha256Hash and version properties exist in the persistedQuery object, preventing undefined values from being set as span attributes and breadcrumb data. Added tests for edge cases: - Empty persistedQuery object - Missing sha256Hash property - Missing version property 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 1f44053 commit 516610f

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

packages/browser/src/integrations/graphqlClient.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ function isPersistedRequest(payload: unknown): payload is GraphQLPersistedReques
232232
isObject(payload) &&
233233
typeof payload.operationName === 'string' &&
234234
isObject(payload.extensions) &&
235-
isObject(payload.extensions.persistedQuery)
235+
isObject(payload.extensions.persistedQuery) &&
236+
typeof payload.extensions.persistedQuery.sha256Hash === 'string' &&
237+
typeof payload.extensions.persistedQuery.version === 'number'
236238
);
237239
}
238240

packages/browser/test/integrations/graphqlClient.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,44 @@ describe('GraphqlClient', () => {
111111
expect(getGraphQLRequestPayload(JSON.stringify(requestBody))).toBeUndefined();
112112
});
113113

114+
test('should return undefined for persisted operation with incomplete persistedQuery object', () => {
115+
const requestBody = {
116+
operationName: 'GetUser',
117+
variables: { id: '123' },
118+
extensions: {
119+
persistedQuery: {},
120+
},
121+
};
122+
123+
expect(getGraphQLRequestPayload(JSON.stringify(requestBody))).toBeUndefined();
124+
});
125+
126+
test('should return undefined for persisted operation missing sha256Hash', () => {
127+
const requestBody = {
128+
operationName: 'GetUser',
129+
extensions: {
130+
persistedQuery: {
131+
version: 1,
132+
},
133+
},
134+
};
135+
136+
expect(getGraphQLRequestPayload(JSON.stringify(requestBody))).toBeUndefined();
137+
});
138+
139+
test('should return undefined for persisted operation missing version', () => {
140+
const requestBody = {
141+
operationName: 'GetUser',
142+
extensions: {
143+
persistedQuery: {
144+
sha256Hash: 'abc123',
145+
},
146+
},
147+
};
148+
149+
expect(getGraphQLRequestPayload(JSON.stringify(requestBody))).toBeUndefined();
150+
});
151+
114152
test('should return undefined for invalid JSON', () => {
115153
expect(getGraphQLRequestPayload('not valid json {')).toBeUndefined();
116154
});

0 commit comments

Comments
 (0)