feat(admin): surface the CSP report sample/detail in /admin/stats#69
Merged
Conversation
The /admin/stats Reports table showed type, path, directive, blocked, and disposition but not the one field that names the offending Trusted Types policy (or the blocked inline snippet): the CSP report's `sample`. reports.ts only populated blob6 from `message`/`reason`, which CSP violation bodies never carry — so the detail was being dropped at write time. Pick `sample` (Reporting API) / `script-sample` (legacy csp-report) as a fallback, and add a "detail" column to the dashboard's recent-reports table so the policy name shows up. Privacy policy updated to disclose the new field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds the missing detail column to the
/admin/statsrecent-reports table — the field that names the rejected Trusted Types policy or the blocked inline snippet for a CSP violation.Why
While reviewing the CSP logs, the dashboard showed
type / path / directive / blocked / dispositionbut not the one field that disambiguates the report-onlytrusted-typesnoise: which policy name was rejected. That lives in the CSP report'ssample.The schema had a
blob6slot (message), butfunctions/reports.tspopulated it only frompick(body, "message", "reason")— and CSP violation bodies carry neither. So the detail was being thrown away at write time; just adding a column would have shown empty cells.Changes
functions/reports.ts—blob6now falls back tosample(Reporting API, camelCase) /script-sample(legacyapplication/csp-report, kebab). Browsers capsamplethemselves; we still truncate to 300. Deprecation/intervention/crash reports keep usingmessage/reason.functions/admin/stats.ts—report_recentselectsblob6 AS detail; the recent-reports table renders adetailcolumn. Existing filterdata-colindices are unchanged (column appended at the end).src/pages/privacy.astro— discloses the new field (rejected policy name / truncated blocked-content snippet) and bumps the "Last updated" date, per the repo's privacy-honesty rule.Note
Historical CSP rows will show an empty detail (the sample was never stored); new reports populate it once deployed. No IP, cookies, or query strings are stored —
sampleis browser-capped and about the page, not the visitor.Checks
npm run build,astro check(0 errors),eslint(only the pre-existinganywarning), andprettier --checkall clean.🤖 Generated with Claude Code