signals-scout-csp-violations
Focused Signals scout for PostHog projects collecting Content Security Policy (CSP) violation reports. Watches `$csp_violation` events for fresh blocked-URL clusters, per-directive bursts, page-scoped regressions after deploys, and suspicious third-party domains that may indicate a compromised script. Emits aggregated findings only when a cluster clears the confidence bar; otherwise writes durable memory and closes out empty. Self-contained peer in the signals-scout-* fleet — no dependencies on other skills. Picked uniformly at random by the coordinator alongside `signals-scout-general` and other specialists.
What this skill does
# 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 emit findings
only when a cluster clears the confidence 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.
## 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}"`
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
Three cheap reads cold-start a run:
- `signals-scout-scratchpad-search` (`text=csp` or `text=blocked`) — durable team steering
from past CSP runs. Entries with `pattern:`, `noise:`, `addressed:`, `dedupe:`, or
`allowlist:` key prefixes tell you the team's healthy domains, recurring
browser-extension noise, fingerprints already surfaced, and what to skip.
- `signals-scout-runs-list` (last 7d) — what prior CSP scouts found and ruled out.
- `signals-scout-project-profile-get` — the `$csp_violation` row in `top_events` carries
`count`, `distinct_users`, `recent_24h_count`, `recent_24h_users`. Pattern the
count/users ratio against the table below.
### Profile shape — count vs distinct_users
| Pattern | What it usually means |
| ------------------------------------------------------- | ---------------------------------------------------------------- |
| Both `count` and `distinct_users` spike in 24h | Fresh broad-impact CSP regression — deploy missed an allowlist |
| `recent_24h_count / count` ≫ `1/7`, users also spike | Today's burst is unusually broad — investigate first |
| `count` very high, `distinct_users` very low (≤ 5) | Single user / bot / browser extension — usually skip |
| `count` ~ `distinct_users` for one blocked URL | Per-pageload violation hitting every visitor — broken policy |
| Steady high `count` across many users + many directives | Mature CSP policy in `report-only` mode — high baseline expected |
| `count` and `distinct_users` both quiet | Nothing fresh today — close out |
### Explore
Patterns to watch — starting points, not a checklist. Group violations along four
dimensions and look for clusters worth a finding. The team's existing push-based
emission (PR #58596) already deduplicates _individual_ violations at
`sha1(violated_directive | blocked_url | document_url | source_file)` granularity with a
24h Redis TTL; your job is to _aggregate_ across that grain into higher-confidence
findings the inbox wouldn't surface on its own.
#### Fresh blocked-URL domain
The single highest-value CSP pattern. Group by `domain(properties.$csp_blocked_url)` over
the last 24–48h. A domain with `first_seen` inside the window, ≥ 10 distinct pageviews,
and not in the team's `allowlist`-tagged memory is the strongest scout signal.
```sql
SELECT
domain(JSONExtractString(properties, '$csp_blocked_url')) AS blocked_domain,
count() AS occurrences,
uniq(person_id) AS distinct_users,
uniq(JSONExtractString(properties, '$csp_document_url')) AS distinct_documents,
min(timestamp) AS first_seen,
max(timestamp) AS last_seen,
groupArray(DISTINCT JSONExtractString(properties, '$csp_effective_directive'))[1:5] AS directives
FROM events
WHERE event = '$csp_violation'
AND timestamp > now() - INTERVAL 48 HOUR
AND JSONExtractString(properties, '$csp_blocked_url') != ''
GROUP BY blocked_domain
HAVING first_seen > now() - INTERVAL 24 HOUR
AND distinct_users >= 10
ORDER BY occurrences DESC
LIMIT 20
```
Three lenses for triage — copy these directly from PR #58596's `_build_description`,
they're the prompt the team needs:
1. **Legitimate — CSP policy needs widening.** New CDN, new analytics provider, new
marketing tag the team rolled out and forgot to add to the allowlist.
2. **Compromised — injected or third-party script indicating a security incident.**
Fresh domain nobody recognizes, especially script-src violations on a small number of
high-traffic pages, especially with `disposition=enforce` and a `source_file` that
points at the team's own JS bundle.
3. **Third-party drift — vendor script the team should remove.** Old analytics SDK still
loaded from a deprecated bundle, ad pixel from a churned vendor, etc.
Emit only when one of these lenses fits with high confidence (≥ 0.85). If you're
genuinely unsure which of the three it is, write a `pattern:csp_violations:<entity>`
scratchpad entry for the next run and close out.
#### Per-directive burst
Group by `properties.$csp_effective_directive`. A directive whose recent 24h count is
materially above its 7d-prior baseline (≥ 3×) with reach across multiple documents is a
strong "policy regression after deploy" signal. Pair with `activity-log-list` filtered to
the last 24–48h — a deploy or hog-flow change correlating to the burst timestamp is the
clean cross-source convergence.
Top directives to expect (rough share-of-violations on a typical SPA): `script-src`,
`script-src-elem`, `img-src`, `style-src`, `connect-src`, `frame-src`. `script-src`
violations are weighted highest for security relevance; `img-src` and `style-src` more
often indicate vendor / CDN drift.
#### Document-scoped regression
Group by `properties.$csp_document_url`. A document with no violations in the
7d-prior window and a sudden burst in the recent 24h is almost always a deploy regression
on that route — a new script tag or inline style that the existing policy doesn't allow.
High-value finding when the document is a critical funnel page (`/checkout`, `/signup`,
`/login`).
#### Stuck loop / single-user noise
`count` very high but `distinct_users` ≤ 5 over the recent window. Almost always a single
user with a misbehaving browser extension, or a bot probing the page. Skip — write a
`noise:csp_violations:<blocked_domain>` scratchpad entry so future runs short-circuit.
Common skippable patterns:
- `chrome-extension://` / `moz-extension://` / `safari-extension://` blocked URLs
- Brave / DuckDuckGo / privacy-browser injected scripts
- `about:blank`, `data:` URIs from translation tooling or password managers
#### Disposition shift
Group by `properties.$csp_disposition`. A team running `report-only` for a long time and
then flipping to `enforce` will see violations turn into actual blocks. If the project
profile shows `count` for `disposition='enforce'` rising sharply (`recent_24h_count`
materially above baseline) while `report-only` shows a corresponding fall, the team has
flipped enforcement — write a `pattern:csp_violations:disposition-flip` scratchpad entry
and emit only if a critical page is suddenly seeing enforced blocks.
### Save memory as you go
Memory is a continuous activity. WriteRelated in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.