Skip to content

Commit db1e794

Browse files
authored
fix(api): add CSP header to generic error SVGs (JhaSourav07#1596)
## Description Fixes JhaSourav07#1595 ## Pillar - [x] 🛠️ Other (Bug fix, refactoring, docs) ## What changed The generic 500 SVG response in `app/api/streak/route.ts` was missing the same `Content-Security-Policy` header used by the other SVG responses from this route. This PR adds `Content-Security-Policy: SVG_CSP_HEADER` to the catch-all error SVG response so the security headers stay consistent across success, validation, not-found, rate-limit, and generic failure paths. I also added a route regression test that forces a generic fetch failure and verifies the 500 SVG response includes the CSP header. This is a GSSoC 2026 API/security bug fix contribution. Please add the relevant GSSoC labels if they are missing. ## Visual Preview N/A — this is a response header change only. ## Local checks ```bash npm run format:check npm run lint npm run test -- app/api/streak/route.test.ts ``` ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally. - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors. - [x] My commit follows the Conventional Commits format. - [x] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have starred the repo. - [x] I have made sure that I have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse quality standard.
2 parents a231edc + 04478db commit db1e794

2 files changed

Lines changed: 12 additions & 0 deletions

File tree

app/api/streak/route.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,17 @@ describe('GET /api/streak', () => {
670670
expect(response.headers.get('Cache-Control')).toBe('no-store');
671671
});
672672

673+
it('sets the SVG Content-Security-Policy header on generic error responses', async () => {
674+
vi.mocked(fetchGitHubContributions).mockRejectedValue(new Error('Network failure'));
675+
676+
const response = await GET(makeRequest({ user: 'octocat' }));
677+
const csp = response.headers.get('Content-Security-Policy');
678+
679+
expect(response.status).toBe(500);
680+
expect(csp).toContain("default-src 'none'");
681+
expect(csp).not.toContain('script-src');
682+
});
683+
673684
it('returns 429 with no-cache headers and rate limit SVG when rate limited', async () => {
674685
vi.mocked(fetchGitHubContributions).mockRejectedValue(new Error('API Rate Limit Exceeded'));
675686

app/api/streak/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ function buildErrorResponse(error: unknown, parseResult: ParseResult): NextRespo
336336
headers: {
337337
'Content-Type': 'image/svg+xml',
338338
'Cache-Control': 'no-store',
339+
'Content-Security-Policy': SVG_CSP_HEADER,
339340
},
340341
});
341342
}

0 commit comments

Comments
 (0)