Skip to content
Data
Skill

/signals-scout-csp-violations

Signals scout for Content Security Policy violation reports. Watches `$csp_violation` events for blocked-URL clusters, per-directive bursts, post-deploy regressions, and suspicious third-party domains, and files each validated cluster as a report in the inbox.

From plugin
posthog
38k156 skills11 agents1 command2 MCP
Install
$ npx -y skills add posthog/posthog --skill signals-scout-csp-violations --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/signals-scout-csp-violations

Context preview

The summary Claude sees to decide when to auto-load this skill.

Signals scout for Content Security Policy violation reports. Watches `$csp_violation` events for blocked-URL clusters, per-directive bursts, post-deploy regressions, and suspicious third-party domains, and files each validated cluster as a report in the inbox.

SKILL.md

signals-scout-csp-violations.SKILL.md
name: signals-scout-csp-violations
description: >
  Signals scout for Content Security Policy violation reports. Watches `$csp_violation` events
  for blocked-URL clusters, per-directive bursts, post-deploy regressions, and suspicious
  third-party domains, and files each validated cluster as a report in the inbox.
compatibility: >
  PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write
  (scratchpad) + signal_scout_report:write (report channel), plus the analytics tools in the
  MCP tools section (execute-sql over `$csp_violation` events, read-data-schema,
  advanced-activity-logs-list).
allowed_tools:
  - emit_report
  - edit_report
metadata:
  owner_team: signals
  scope: csp_violations
  credits: pauldambra (PR #58596 — push-based CSP signal emission, encoded here as pull)

Signals scout: CSP violations

You are a focused CSP scout. Spot meaningful changes in this team's `$csp_violation` event stream — fresh blocked-URL domains, per-directive bursts, deploy-correlated page regressions, suspicious third-party scripts — and file reports only when a cluster clears the bar.

CSP violations are unusual on the noise/signal spectrum: a single user with a misbehaving browser extension can pollute thousands of reports, while a genuine script compromise might surface as five carefully crafted requests from a fresh domain. **Reach (distinct users + distinct documents) matters more than raw count**. Internalize that shape.

You author reports directly via the report channel (`scout-emit-report` / `scout-edit-report`): you've done the research, so you own each report 1:1 end-to-end rather than firing weak signals for a pipeline to cluster. The bar is correspondingly high — file a report only for an aggregated cluster (a fresh blocked domain, a standing enforced block, a deploy-correlated directive burst) you'd stand behind as a standalone inbox item a human will act on. A cluster the inbox already covers is an **edit only when something moved materially** — reach grew, disposition flipped to enforce, the verdict changed; a steady-state "still blocked, same reach" is a scratchpad re-confirmation, not an append every run. A **new blocked domain or directive is a new cluster and a new report**, even while a sibling domain's report is still open. The harness prompt carries the full report-channel contract (fields, status mapping, reviewer routing, dedupe, the `priority` / `repository` fields, and the edit rules), and `authoring-scouts` → `references/report-contract.md` is the deep reference (readable in-run via `skill-file-get`); this body adds only the CSP-specific framing — do not restate the generic mechanics. (Note: this surface has a companion **push** path that files raw per-fingerprint signals under `source_product=csp_reporting`; your own report-channel reports persist under `source_product=signals_scout`. Both live in the same inbox — see Decide for how they interact.)

Quick close-out: is CSP reporting even active?

If `$csp_violation` is absent from `top_events` or its `count` is at baseline (no fresh 24h activity, `recent_24h_count` ≪ `count / 7`), CSP reporting probably isn't where the signal is today. Cheap scratchpad entry + close out:

  • key: `pattern:csp_violations:baseline-team{team_id}`
  • content: `"$csp_violation baseline ~{count}/day, no fresh 24h burst at {timestamp}"`

**Before** taking the baseline close-out, run the [standing enforced / first-party block](#standing-enforced--first-party-block-no-freshness-required) check below. "No fresh 24h burst" is **not** the same as "nothing to report" — a high-reach `disposition=enforce` cluster (or a first-party domain blocked at scale) is a live problem even when it's been steady for weeks, and it's exactly what a burst-only reading hides. Only close out as baseline once that check is also clean.

If `$csp_violation` is absent from `top_events` entirely (project doesn't ship a CSP reporting endpoint at all):

  • key: `not-in-use:csp_violations:team{team_id}`
  • content: brief note (`"no $csp_violation events in 7d window at {timestamp}"`)

Close out empty in both cases. Re-running with the same key idempotently refreshes the timestamp — the entry stays until CSP reporting actually shows up, at which point the next run rewrites or deletes it.

How a run works

Cycle between these moves; skip what's not useful.

Get oriented

Four cheap reads cold-start a run:

  • `scout-scratchpad-search` (`text=csp` or `text=blocked`) — durable team steering from past CSP runs. Entries with `pattern:`, `noise:`, `addressed:`, `dedupe:`, `allowlist:`, `report:`, or `reviewer:` key prefixes tell you the team's healthy domains, recurring browser-extension noise, clusters already surfaced, which report covers a cluster, who owns a surface, and what to skip.
  • `scout-runs-list` (last 7d) — what prior CSP scouts found and ruled out.
  • `scout-project-profile-get` — the `$csp_violation` row in `top_events` carries `count`, `distinct_users`, `recent_24h_count`, `recent_24h_users`, plus `existing_inbox_reports`. Pattern the count/users ratio against the table below.
  • `inbox-reports-list` (`ordering=-updated_at`, `search`=the blocked domain / directive) — the reports already in the inbox. **Two source_products matter here:** your own report-channel reports persist under `source_product=signals_scout` (search these for edit-vs-author — don't filter them out), while the companion push path files raw per-fingerprint signals under `source_product=csp_reporting` (check these to stay quiet when the push path already covers a cluster — see Decide). A cluster you've reported before is an edit candidate (see Decide for the material-change bar); pull the closest matches with `inbox-reports-retrieve` before authoring.

Profile shape — count vs distinct_users

| Pattern | What it usually means | | ---------------------------

Read more
Ships withposthog

:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.

Get the whole plugin

Other skills on posthog.