Commit Graph
100 Commits
Author SHA1 Message Date
Claude a0bb7bdddb ci(clickgrab): weekly cadence + single rolling PR
The daily cron cut a fresh dated branch (data/clickgrab-${DATE}) and opened
a new PR every run. Since each PR edits the tail + meta of the same growing
_data/clickgrab_trends.yml, they mutually conflict the moment one merges,
leaving a pileup of stuck PRs (#146/#147/#148).

Fixes the structure rather than the symptom:
- Publish to a fixed rolling branch (data/clickgrab-auto), force-pushed each
  run and refreshed via `gh pr edit`, so at most one ClickGrab PR is ever
  open and it always shows a clean append-only diff vs main.
- Drop cadence from daily to weekly (Mondays 06:00 UTC). The generator's
  14-day lookback + watermark dedup backfills every daily bucket regardless,
  so weekly captures the same data with far less churn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQzGNdzZK4svMZPTK9BikA
2026-06-21 04:20:55 +00:00
Claude 2976acb1eb feat(chokepoint): add BYOSI Scripting Interpreters detection chokepoint
New defense-evasion chokepoint covering Bring Your Own Scripting Interpreter
(BYOSI) attacks where adversaries deliver legitimately signed interpreter
binaries (Python, PHP, Node.js, Ruby, etc.) to execute malicious scripts
that bypass EDR binary analysis.

Includes:
- Chokepoint YAML with 8 variations (BYOSI PHP, PolyDrop, IronNetInjector,
  NodeLoader, Lu0Bot, PYC evasion, .NET BYOI, AutoHotKey)
- 3-stage detection chain (interpreter delivery → execution → script action)
- Evolution timeline from 2019 (DerbyCon BYOI) through 2025 (Node.js ClickFix)
- Sigma rules at Research, Hunt, and Analyst maturity levels
- Emulation script for safe telemetry generation

https://claude.ai/code/session_01NXHWaktiuig3uta8WV6dGc
2026-03-29 04:35:09 +00:00
Claude 0c1ff36f63 standardize(chokepoints): clickfix-techniques — CIDR modifier for IP filter
- [x] Attack Chokepoints accordion: already present (transformed from Prerequisites | already present)
- [x] The Constant: absorbed into accordion
- [x] Variations: timeline events removed, collapsed by default, source links: 2 placeholders added
- [x] Detection Strategy: Pre-Execution tab moved from Early Detection, CIDR modifiers applied
- [x] Raw Log Samples: collapsed by default
- [x] Emulation: collapsed by default
- [x] Intel Resources: removed
- [x] OSINT renamed to OSINT Pivots: kept 5 queries
- [x] Prerequisites standalone section: removed

CIDR change: Converts DestinationIp|startswith list (17 entries + filter_loopback) to
DestinationIp|cidr notation covering 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16,
127.0.0.0/8, ::1/128. No other sigma rule files contain IP startswith lists.

PLACEHOLDERS: TerminalFix — source link missing; DownloadFix — source link missing

https://claude.ai/code/session_01LPLZjqeDGL5pBXwtvi4fvs
2026-03-29 01:13:48 +00:00
Claude 29563f4570 standardize(chokepoints): shared layout — 8-section structural refactor
- [x] Attack Chokepoints accordion: <details> markup per stage, prereqs in first stage;
      pages without Chokepoints field (browser-credential-theft, edr-bypass-techniques,
      web-shells) get PLACEHOLDER comment
- [x] The Constant: both standalone boxes removed; invariant text lives in accordion stages
- [x] Variations: EvolutionTimeline entries and chip strip removed; all variants collapsed
      by default via <details>; source links rendered or TODO placeholder
- [x] Detection Strategy: Pre-Execution tab added as first tab; EarlyDetections content
      rendered for clickfix; PLACEHOLDER for all other pages; Research/Hunt/Analyst tabs
      converted to det-tab/det-panel/det-meta-row pattern
- [x] Raw Log Samples: per-item <details class="log-item"> collapsed by default
- [x] Emulation: native <details class="emulation-wrapper"> collapsed by default;
      lab warning visible in summary row
- [x] Intel Resources: section removed globally
- [x] OSINT renamed to OSINT Pivots; osint-grid/osint-top/osint-source/osint-desc markup
- [x] Prerequisites standalone section: removed globally; content absorbed into accordion
- [x] CSS: all new classes (chokepoint-item, variant-item, det-tab, det-panel, log-item,
      emulation-wrapper, osint-grid, etc.) added; old chain-stage/var-card/intel-flat CSS removed
- [x] JS: switchTab() and copyCode() named functions; event delegation removed

PLACEHOLDERS added:
  - browser-credential-theft — Attack Chokepoints missing (no Chokepoints field in YAML)
  - edr-bypass-techniques    — Attack Chokepoints missing (no Chokepoints field in YAML)
  - web-shells               — Attack Chokepoints missing (no Chokepoints field in YAML)
  - all pages except clickfix-techniques — Pre-Execution tab placeholder
  - variants without SourceURL across all pages — "Source link needed" placeholder
    (TerminalFix, DownloadFix on clickfix; multiple on browser-credential-theft,
    edr-bypass, web-shells, renamed-rmm, remote-execution-tools)

https://claude.ai/code/session_01LPLZjqeDGL5pBXwtvi4fvs
2026-03-29 01:13:39 +00:00
Claude 44c83df8a4 Standardize attack chain pages with interactive TTP filter
- Replace SVG-based TTP diagram with interactive HTML vertical filter
  on all attack chain pages (actor pill buttons dim/light technique
  cards; orange border marks universal chokepoints)
- Remove attack flow swimlane section from the shared layout
- Add new AiTM / Phishing Kit attack chain page covering Tycoon 2FA,
  Evilginx, EvilProxy, Sneaky 2FA, and Device Code Flow across five
  stages (Lure Delivery → Persistence & Objectives)
- Add AiTM card to attack-chains/index; add .ac-card-badge.aitm CSS
- Trim references on ransomware and infostealer pages to direct sources
- Cross-link all three chains to each other in Related Attack Chains

https://claude.ai/code/session_01DpMSTJkS25aCCEqBJBFBtC
2026-03-28 21:22:35 +00:00
Claude fcb02022b5 feat: add Streamlit Cloud data persistence via GitHub API
The Streamlit app is hosted on Streamlit Community Cloud which has an
ephemeral filesystem — collected data was lost on every restart with no
way to push it back to the repo for the GitHub Pages site.

Adds GitHub API-based commit and PR functions so collected data can be
published from the cloud app. Also adds missing VT_API_KEY and GH_TOKEN
to the secrets pipeline, and creates a secrets.toml.example for cloud
configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 05:13:48 +00:00
Claude 8f87a173ea fix: end-to-end pipeline bugs preventing website data display
Root cause: update_masq_infra.py produced a schema incompatible with
the Jekyll templates — missing meta.record_count, records[], campaigns[],
payload_summary, and infrastructure_summary. The website gates all
content on `site.data.masq_infra.meta.record_count > 0`, so every
section showed "No data yet".

Fixes across 11 files:

Schema & data (update_masq_infra.py, _data/masq_infra.json):
- Add meta.record_count alongside sample_size
- Build records[], payload_summary, infrastructure_summary sections
  matching build_data.py's output schema
- Add campaigns[] placeholder for standalone pipeline

Collection scripts (collect_ioc_feeds.py, collect_infra_hunts.py,
fetch_payload_chains.py):
- Fix "agenttesl a" typo in _C2 set across all 3 files — AgentTesla
  was never classified as C2
- Fix MalwareBazaar query_status check: "tag_info" → "ok"
- Add shared abuse.ch API key fallback for ThreatFox and URLhaus

History (append_history.py, _data/masq_infra_history.json):
- Read actual total_domains from record_count or sample_size
- Read lets_encrypt_pct from stats instead of hardcoded 0.0
- Read traffic_sources from data instead of hardcoded {}
- Fix week 2026-12 snapshot: 0 domains → 1569, 0% LE → 91.2%

Website (trends/masq-infra.md):
- Inject window.MASQ_HISTORY and load masq-infra-history.js
- Add chart container divs with correct IDs
- Add Trends to sidenav navigation

CI (.github/workflows/update-masq-infra.yml):
- Add missing MB_API_KEY to IOC feeds and infra hunts steps
- Add missing ANTHROPIC_API_KEY to cluster campaigns step

Streamlit app (collection_tab.py, helpers.py):
- Add VT_API_KEY to env builder and key map

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 05:05:23 +00:00
Claude 8a82ad5e69 fix: end-to-end pipeline silent failure bugs across collection and app scripts
- collect_infra_hunts.py extract_domain(): log tldextract exceptions to stderr
  instead of silently passing; bare `except Exception:` → `except Exception as exc:`
- fetch_payload_chains.py compute_favicon_hash(): log favicon fetch failures to
  stderr instead of silently passing; same bare-except fix
- app/utils/helpers.py load_records(): log JSON parse errors to stderr before
  returning []; previously a corrupt cache file was indistinguishable from a
  missing one in the Streamlit UI
- cluster_campaigns.py build_campaign(): guard `r["id"]` list comprehension with
  `if "id" in r` to prevent unhandled KeyError from aborting all campaign clustering
- cluster_campaigns.py assign_records_to_clusters(): use r.get("id") instead of
  r["id"] in the assigned-ids membership check for the same reason
- append_history.py _extract_row(): fix schema mismatch with build_data.py v2.0.0
  output; was reading stale top-level keys (generated_at, summary, stats,
  lure_types, traffic_sources, asn_distribution, payload_families) that no longer
  exist, causing every history entry to be written with all-zero values while the
  script reported success; now reads from meta.last_updated, meta.record_count,
  campaigns[], payload_summary.lure_payload_matrix, infrastructure_summary.top_asns,
  and payload_summary.top_families

https://claude.ai/code/session_01BdaHsgueTdZc4su7SfM8AN
2026-03-28 01:41:23 +00:00
Claude e00b3e4ad1 feat: CF origin unmasking tab in Validin UI with Shodan confirmation
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-27 00:04:49 +00:00
Claude b0a61af76c feat: add CF origin unmasking to Validin pivot flow
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-27 00:04:01 +00:00
Claude 6facd0de37 feat: Validin CloudFlare origin IP unmasking function
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-27 00:03:42 +00:00
Claude a3b2164fcd feat: Validin pivot UI tab and collection controls
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-26 23:49:28 +00:00
Claude 9d34571a24 feat: wire Validin pivots into infra hunt collection flow
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-26 23:48:10 +00:00
Claude d7f8465327 feat: Validin pDNS and cert pivot collection functions
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-26 23:47:06 +00:00
Claude 62587d96a0 feat: Validin API helper functions
https://claude.ai/code/session_01N72P8PggbvsLDmDoURiai4
2026-03-26 23:46:34 +00:00
Claude 1fd959e349 fix: add requirements.txt for Streamlit Community Cloud
Streamlit Community Cloud installs from requirements.txt in the repo
root. The existing requirements-update.txt was not picked up, causing
plotly (and other pipeline deps) to be missing at runtime.

https://claude.ai/code/session_0191A2u4PjnLynghfj2iEVHX
2026-03-25 00:51:20 +00:00
Claude c17d49927e fix: guard samples sort against null records
site.data.masq_infra.records is nil before the pipeline
runs; Liquid's sort filter throws on nil. Assign to a
temp var and gate the sort inside the size > 0 check.

https://claude.ai/code/session_01YWa3QbXW3cKba534DfvCJZ
2026-03-24 23:23:32 +00:00
Claude d4fdecb1fb feat: masq-infra page content sections
https://claude.ai/code/session_01YWa3QbXW3cKba534DfvCJZ
2026-03-24 23:17:17 +00:00
Claude 7a9805e14f feat: masq-infra page skeleton and CSS
https://claude.ai/code/session_01YWa3QbXW3cKba534DfvCJZ
2026-03-24 23:15:22 +00:00
Claude b12b2b86fb chore: remove old masq-infra page ahead of rewrite
https://claude.ai/code/session_01YWa3QbXW3cKba534DfvCJZ
2026-03-24 23:14:33 +00:00
Claude 18e7684748 feat: Streamlit review and export app
Adds the full Streamlit data review and export UI:
- app/streamlit_app.py — main entry point with sidebar nav and custom CSS
- app/utils/helpers.py — shared utilities: load_secrets (st.secrets → os.environ
  fallback), load_records/load_campaigns, confidence_badge, payload_class_color,
  format_chain, run_script
- app/components/collection_tab.py — IOC feeds, infra hunts, chain reconstruction,
  AI triage buttons with [SUMMARY] stderr parsing; cache file status row
- app/components/records_tab.py — filterable dataframe of triaged records with
  detail expander and below-threshold warning metric
- app/components/chains_tab.py — chain flow diagram using st.columns, depth
  distribution table, CDN usage metric
- app/components/payloads_tab.py — metric row, plotly class bar chart, top-15
  families table, lure×payload pivot table
- app/components/campaigns_tab.py — campaign cards with confidence badges, class/
  lure chips, narrative display, cross-tab navigation to samples tab
- app/components/infrastructure_tab.py — delivery domain table, favicon clusters
  with Shodan links, ASN distribution chart (CDN providers excluded)
- app/components/samples_tab.py — full record table with urlscan links, export
  masq_infra.json via build_data.py, raw records download
- .streamlit/config.toml — dark theme matching site palette

https://claude.ai/code/session_0191A2u4PjnLynghfj2iEVHX
2026-03-24 03:36:09 +00:00
Claude f6790341e7 feat: analysis, clustering, and data build scripts
Add claude_triage.py and replace cluster_campaigns.py + build_data.py
as part of the masq-infra pipeline rebuild:

- scripts/claude_triage.py (new): reads cache/enriched_records.json,
  calls claude-sonnet-4-6 to classify records where payload_class is
  unknown or payload_family is null. Hard cap of 50 API calls per run
  with 1s rate limit. Gracefully falls back to copying input unchanged
  when ANTHROPIC_API_KEY is missing. Writes cache/triaged_records.json.

- scripts/cluster_campaigns.py (replaced): hard-signal-only clustering
  replaces the old union-find composite-key approach. Groups records by
  shared_payload > shared_favicon > shared_ip (30-day window) >
  shared_cert_pattern (cheap TLD + self-signed), each record assigned to
  at most one cluster by priority. Confidence scored from hard-signal
  base + corroborating signals. Writes cache/campaigns.json (≥70) and
  cache/low_confidence_campaigns.json (<70). Optional --narratives flag
  triggers AI-generated campaign summaries via claude-sonnet-4-6.

- scripts/build_data.py (replaced): reads cache/triaged_records.json +
  cache/campaigns.json, filters to confidence ≥ 40, assembles meta /
  payload_summary / infrastructure_summary / weekly_summary sections per
  the schema in _data/masq_infra_schema.md, and writes
  _data/masq_infra.json. Supports --dry-run flag.

https://claude.ai/code/session_0191A2u4PjnLynghfj2iEVHX
2026-03-24 03:11:32 +00:00
Claude fadb69fca8 feat: IOC collection and chain reconstruction scripts
Add three pipeline scripts for the masq-infra rebuild:

- scripts/collect_ioc_feeds.py: queries MalwareBazaar (20 payload family
  tags), ThreatFox (bulk IOC pull, confidence ≥ 75), and URLhaus (recent
  500 URLs filtered to online/unknown status). Assembles unified
  schema-conformant records, deduplicates by record id, writes
  cache/ioc_records.json. Graceful degradation on missing API keys.

- scripts/collect_infra_hunts.py: proactive hunting via Shodan favicon
  hash queries (6 brand hashes) and open-directory queries, plus URLScan
  filename/title pivots across 11 brand lures. All candidate records
  start with lower confidence scores than confirmed IOC feed records.
  Writes cache/infra_records.json.

- scripts/fetch_payload_chains.py: reads both cache files, reconstructs
  redirect chains from URLScan result JSON (classifies each hop as lure /
  redirector / payload-delivery / cdn), fetches favicon hashes via
  MurmurHash3, re-scores confidence using the full schema rules, and
  writes cache/enriched_records.json. Hard cap of 200 URLScan lookups per
  run to stay within free-tier limits.

https://claude.ai/code/session_0191A2u4PjnLynghfj2iEVHX
2026-03-24 02:48:02 +00:00
Claude 14462ef693 chore: pipeline foundation — schema, deps, gitignore, cache dir
https://claude.ai/code/session_0191A2u4PjnLynghfj2iEVHX
2026-03-24 02:21:49 +00:00
Claude fb1171be45 Commit 5: Trim Intel Resources to foundational-only (per-chokepoint judgment)
YAML: Removed variant-specific, single-incident, secondary, and annual
report entries from all 7 chokepoint Intel sections. Migrated variant-
specific sources to SourceURL on variation cards (Commit 3). Added
Tier: primary to entries that lacked the field. No Tier: supporting entries
remain in any chokepoint file.

Entry counts after trim:
  clickfix:             18 → 9
  renamed-rmm:           7 → 4
  edr-bypass:           10 → 4  (Tier field added to all kept entries)
  ransomware-svc:        8 → 3
  browser-credential:    9 → 5  (Tier field added to all kept entries)
  web-shells:           10 → 5  (Tier field added to all kept entries)
  remote-execution:      9 → 7

Layout: Replaced tiered Intel rendering (primary card grid + supporting
collapsible toggle) with a uniform flat link list — title (link) + one
sentence description. Removed intel-card, intel-grid, intel-card-name,
intel-card-desc, intel-linked, intel-link-tag, intel-supporting-toggle CSS.
Removed intel-supporting-toggle JS event handler.

https://claude.ai/code/session_018xsxUHnwvGtKP6J2W69qa5
2026-03-22 23:50:00 +00:00
Claude 3679258a43 Commit 4: Remove Known Bypasses & Mitigations from layout
Layout: deleted the entire {% if cp.KnownBypasses %}...{% endif %} block
including section heading, table, and surrounding markup. Nothing replaces it.

Schema + template: marked KnownBypasses as deprecated with comments
explaining it is preserved in YAML data for future migration but no longer
rendered. Template entry commented out to discourage use in new files.

YAML data files are untouched — KnownBypasses data remains in all chokepoints.

https://claude.ai/code/session_018xsxUHnwvGtKP6J2W69qa5
2026-03-22 23:46:32 +00:00
Claude cdcba301a3 Commit 3: Add SourceURL to variation cards
YAML: Added SourceURL to top-level Variations entries across all 7
chokepoint files (24 total). One authoritative primary source per variant;
omitted field where no clear primary source exists. No SourceURL added to
nested structures (MasqueradeThemes in renamed-rmm-tools).

Layout: Added .variant-source-link CSS class (small monospace text, subtle
accent border, hover underline — matches chain-sigma-link pattern). Added
{% if v.SourceURL %} footer block to var-card template rendering
"Source →" link at the bottom of each variation card.

https://claude.ai/code/session_018xsxUHnwvGtKP6J2W69qa5
2026-03-22 23:45:53 +00:00
Claude d2032a3540 Commit 2: Revert to 3 chokepoint stages per chokepoint (per-chokepoint judgment)
clickfix: merge Lure Page Delivery + Clipboard Seeding into Lure/Delivery
  (Research); rename User Execution → Execution (Hunt); rename Outbound
  Network Connection → Second Stage Retrieval (Analyst). Clipboard ETW
  content folded into merged stage LogSources and BypassNote.

renamed-rmm: drop Payload Hosting stage; fold hosting/reachability
  invariant into Browser Download WhyCantBypass. Result: Browser Download
  (Research) → User Execution (Hunt) → Outbound RMM Connection (Analyst).

ransomware-service-manipulation: drop Privilege Verification stage; fold
  Admin/SYSTEM privilege requirement into Service Enumeration WhyCantBypass.
  Result: Service Enumeration (Research) → Service Stop and Disable (Hunt)
  → Service Deletion (Analyst).

remote-execution-tools: drop Network Access stage; fold protocol-port
  reachability requirement into Remote Execution Primitive WhyCantBypass.
  Result: Credential Acquisition (Research) → Remote Execution Primitive
  (Analyst) → Lateral Spread (Hunt).

edr-bypass, browser-credential-theft, web-shells: no Chokepoints section
  exists in these files — left as-is per "fewer than 3 stages" rule.

https://claude.ai/code/session_018xsxUHnwvGtKP6J2W69qa5
2026-03-22 23:41:37 +00:00
Claude 05edba9b60 Commit 1: Rename Detection Chain → Attack Chokepoints
- Update CSS comment, HTML comment, heading text, aria-controls,
  data-target, and collapsible body id from chain-body to
  attack-chokepoints-body
- Stage count subtitle already used {{ cp.Chokepoints.size }}
  dynamically; switch to Liquid filter form {{ cp.Chokepoints | size }}
  for consistency with other collapsible subtitles in the layout

https://claude.ai/code/session_018xsxUHnwvGtKP6J2W69qa5
2026-03-22 23:40:14 +00:00
Claude 658fd9ac34 Deduplicate Storm-2561 variations and condense redundant YAML fields
- Merge duplicate Storm-2561 Variation entries into single entry (2025-Q2)
- Merge two duplicate 2026-Q1 Storm-2561 EvolutionTimeline entries into one
- Trim LummaC2 Notes: remove sentence restating Status (disruption date)
- Trim RedLine Notes: remove sentence restating Status (disruption date)
- Replace verbose 2025-Q2 DetectionImpact with "No change to core detection pattern"

https://claude.ai/code/session_01RkmeTxBwe4djWBSc6rANyS
2026-03-22 16:17:02 +00:00
Claude df032dc369 Strip emulation script doc blocks and add two-line ATT&CK headers
For all emulation/*/emulate.ps1:
- Remove <# .SYNOPSIS/.DESCRIPTION/.NOTES/.EXAMPLE #> blocks
- Remove # ── section banner comment lines
- Remove Write-Verbose lines duplicating Signal:/Matched rules: annotations
- Replace with two-line header: ATT&CK technique ref + one-sentence behavior summary

https://claude.ai/code/session_01RkmeTxBwe4djWBSc6rANyS
2026-03-22 16:15:10 +00:00
Claude ed11609625 Strip Sigma comment blocks from all remaining chokepoints
Remove all content after level: in every sigma-rules/**/*.yml file
outside browser-credential-theft (handled in prior commit): section
banners, investigation notes, KQL/SPL queries, and operational
narrative across clickfix, edr-bypass, ransomware-service,
remote-execution, renamed-rmm, and web-shells.

Also removes a mid-file implementation note block in
remote-execution/analyst.yml that preceded logsource:.

https://claude.ai/code/session_01RkmeTxBwe4djWBSc6rANyS
2026-03-22 16:14:12 +00:00
Claude 718ebc11ee Strip Sigma comment blocks from browser-credential-theft
Remove all content after the level: field in research.yml, hunt.yml,
and analyst.yml: investigation notes, KQL queries, and operational
narrative. These belong in documentation, not in Sigma rule files.
Validates the strip pattern before applying it broadly.

https://claude.ai/code/session_01RkmeTxBwe4djWBSc6rANyS
2026-03-22 16:13:28 +00:00
Claude 52a934b9ef Fix hljs race condition and flatten log sample language class
- Remove defer from hljs script tags; wrap highlightAll() in DOMContentLoaded
  to guarantee scripts are loaded before the call executes
- Replace xml/plaintext conditional log language assignment with flat language-yaml

https://claude.ai/code/session_01RkmeTxBwe4djWBSc6rANyS
2026-03-22 16:11:49 +00:00
Claude 635d376dd4 Surface payload clusters as separate cache file and top-level JSON fields
Extracts fingerprint_campaigns() from aggregate() into main() in
update_masq_infra.py; writes result to cache/payload_clusters.json.
In build_data.py, loads payload_clusters.json independently, writes
merged["infra_clusters"] and merged["payload_clusters"] as distinct
top-level fields, and cleans up legacy campaigns/campaign_clusters keys.
build_campaigns() gains cluster_type parameter passed through to score_cluster().

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-22 05:40:00 +00:00
Claude 1297f33ef2 Add three-category heuristic_v1 confidence scoring to campaign clusters
Adds score_cluster(cluster, cluster_type) with separate signal sets for
infra clusters (lure_type, favicon_hash, asn, registration_week) and
payload clusters (payload_families, file_type, asn_cohort, date_range
width). Applies scoring in build_campaigns() and new build_payload_campaigns().
Each cluster output gains confidence, confidence_label, and signal_breakdown.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-22 05:35:50 +00:00
Claude 6e8e773096 Add three-level registration date fallback in cluster_campaigns and build_data
In _extract_domains() and build_domain_age_histogram(), replace bare
vt_creation_date lookup with: vt_creation_date → record["date"] →
record["first_seen"]. Handles privacy-protected domains (~40% of registrar
domains lack WHOIS) and pipeline records that use different field names.
Age histogram is documented as best-effort approximation.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-22 05:31:28 +00:00
Claude 14a4d04840 Add BRAND_CANONICAL_DOMAINS exclusion filter to update_masq_infra.py
Adds a BRAND_CANONICAL_DOMAINS frozenset derived from BRAND_FAVICON_SEEDS
canonical domains. Filters raw_records after collect_urlscan() returns,
excluding exact domain matches and subdomains while preventing false
exclusions (e.g. notdiscord.com) via explicit exact-match guard.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-22 04:08:14 +00:00
Claude d5881b6649 data(sources): add five high-signal threat intel RSS feeds
Adds The DFIR Report, Elastic Security Labs, Red Canary Blog,
Mandiant (mandiant.com), and SentinelOne Labs to rss_feeds.
Huntress Blog was already present and skipped.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-21 23:01:38 +00:00
Claude cd7b488320 feat(pipeline): replace vague accuracy prompt with detection-specific questions
Replaces the generic "are there factual inaccuracies" closing question in
validate_accuracy_with_claude() with three targeted questions covering
prerequisite bypass, Variation Status staleness, and Sigma rule evasion.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-21 22:45:55 +00:00
Claude cbfb18a603 feat(pipeline): enrich chokepoint context with Description and first Variation notes
Adds Description field and the Notes from the first existing Variation
to each chokepoint block in build_chokepoint_context(), giving Claude
detection scope rather than just names when evaluating articles.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-21 22:43:51 +00:00
Claude f113d800b7 feat(pipeline): add fetch_full_article() for richer article context
Replaces RSS body-only text assembly with a full HTTP fetch of each
article URL, stripping HTML via html.parser and truncating to
MAX_ARTICLE_CHARS. Failed fetches fall back to the original RSS body
so the pipeline is never broken by unreachable URLs.

https://claude.ai/code/session_01M2dV1Y8ujm65zXemApvfo4
2026-03-21 22:32:54 +00:00
Claude 6d0248fcee feat(page): add historical trend charts
https://claude.ai/code/session_01YKvD6RdYbkqoLif8UPZzqm
2026-03-19 03:19:55 +00:00
Claude 074038a884 feat(pipeline): add weekly history accumulator for trend analysis
https://claude.ai/code/session_01YKvD6RdYbkqoLif8UPZzqm
2026-03-19 03:04:52 +00:00
Claude ef9546a845 fix(charts): bind masq-infra charts to correct data source, add narrative headlines
https://claude.ai/code/session_01YKvD6RdYbkqoLif8UPZzqm
2026-03-19 02:55:30 +00:00
Claude 79ebfd97cd feat(page): redesign delivery chain as two-stage CSS flow diagrams
https://claude.ai/code/session_01YKvD6RdYbkqoLif8UPZzqm
2026-03-19 02:47:07 +00:00
Claude 68e63fc7fb fix(index): guard against null site.data.chokepoints before sort
_data/chokepoints.* has never existed in this repo; the unconditional
`| sort:` call crashes the build with "Cannot sort a null object".
Wrap with {% if site.data.chokepoints %} so the page builds cleanly
whether or not the data file is present.

https://claude.ai/code/session_01CsVRSuTipWjCaQ2mqCGVsF
2026-03-19 02:12:11 +00:00
Claude 960d842fec feat(page): CSS-only IOK tabs, fix recent samples empty columns, add URLScan links
Wrap three IOK rule code blocks in a radio-input CSS-only tab interface
(no JavaScript) with labels Generic download lure / Crypto wallet /
Fast-deploy typosquat. Append matching .iok-tabs CSS to style.css.

Add cg-samples-table class and URLScan search column to both sample
tables. Add inline script that hides Payload host and Family columns
at page load when >80% of rows are empty, identified by header text.

https://claude.ai/code/session_01CsVRSuTipWjCaQ2mqCGVsF
2026-03-19 02:03:53 +00:00
Claude 9cd450ebeb feat(page): add lure→payload table and campaign cards
Replace placeholder callouts in #lure-payload and #campaigns with
data-driven Liquid content sourced from masq_infra.lure_payload_matrix
and masq_infra.campaigns. Adds family tag pill CSS, campaign card
layout, and green ACTIVE badge for clusters seen within 7 days.

https://claude.ai/code/session_01CsVRSuTipWjCaQ2mqCGVsF
2026-03-19 01:58:52 +00:00
Claude ab88a4dda5 feat(page): restructure section order, add sticky nav, collapse reference tables
- Reorder masq-infra sections: Arrival → Fingerprinting → Lure→Payload →
  Campaigns → Chokepoints → Samples (How Users Arrive now leads)
- Add sticky .page-anchors nav bar (anchors to all 6 sections; sits flush
  below .site-nav at top:var(--nav-h); overflow-x:auto for mobile)
- Collapse 5 reference tables behind <details><summary> by default:
  Lure Taxonomy, Observed Lure Types, Observed Traffic Sources,
  Observed Naming Patterns, and Recent Samples rows 11+
- Replace Campaign Clustering section with Active Campaigns placeholder
  (id=campaigns); replace Payload Inventory section with Lure→Payload
  Analysis placeholder (id=lure-payload) — both reserved for Phase 2b
- Add CSS rules for .page-anchors and .cg-page details/summary to style.css

https://claude.ai/code/session_01CsVRSuTipWjCaQ2mqCGVsF
2026-03-19 01:51:55 +00:00
Claude fe2e5cc569 fix(pipeline): join lure_type and HA families to campaign clusters
- _extract_domains(): inspect enriched record keys (lure_type → category →
  tag fallback) and brand; propagate both into domain_info entries
- cluster_domains(): compute majority-vote lure_type, brand, and
  lure_type_breakdown across cluster members; add all three to cluster dicts
- build_campaigns(): accept ha_lookup_results param; join HA family hits
  keyed as "domain:{host}" into per-domain families; pass lure_type and
  brand from cluster dict through to campaign output
- add build_lure_payload_matrix(): aggregates {lure_type, top_families,
  domain_count} across all campaigns; written to merged["lure_payload_matrix"]

https://claude.ai/code/session_01CsVRSuTipWjCaQ2mqCGVsF
2026-03-19 01:35:56 +00:00
Claude f859bbd3d4 refactor: pathlib, httpx async, and .env for pipeline scripts
Apply three coding standards across all 6 enrichment pipeline scripts:

pathlib
- Replace all os.path.join/exists/dirname/makedirs with Path / operator,
  path.exists(), path.mkdir(), path.read_text(), path.write_text()

httpx + async
- Replace requests.Session with httpx.AsyncClient throughout
- Drop the hand-rolled blocking RateLimiter class in enrich_infra.py;
  replace with _VTThrottle (async lock + sliding window, same semantics)
- Parallelize: hostname enrichment (asyncio.gather + Semaphore),
  favicon fetches (configurable FAVICON_CONCURRENCY), HA IOC lookups
  (Semaphore of 6), LFS file downloads (asyncio.gather per file),
  sandbox poll loops (concurrent per-job coroutines)
- All main() functions are now async; entry point is asyncio.run(main())

.env
- Add .env.example with all tunable constants (URLs, timeouts, rate limits,
  concurrency, environment IDs); values load via python-dotenv with sane
  defaults so scripts work without a local .env file
- Add .env to .gitignore
- Add httpx python-dotenv to workflow pip install line

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 23:25:35 +00:00
Claude 08733d24d8 feat: write pipeline_run.json log after each enrichment run
Each script now appends its section to cache/pipeline_run.json at the
end of main(), recording API key presence, query counts, success/failure
tallies, and a status field:

- ingest_clickgrab: files_found, files_in_window, lfs_skipped, records_ingested
- enrich_infra: IPinfo queried/enriched/failed + VT requests_used/budget_exhausted
- ha_lookup: new_lookups, reports_found, total_cached
- cluster_campaigns: domains_processed, favicons_obtained, clusters_identified
- sandbox_submit: candidates, submitted_new, completed, failed, timed_out
- build_data: records_merged, clusters_merged, payload_families + full summary

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 19:25:27 +00:00
Claude 298560e817 refactor: merge enrich workflow into update-masq-infra; add HA IOC lookup
- Combines enrich.yml steps into update-masq-infra.yml so all trends
  pages update in a single Monday run with one PR
- Deletes enrich.yml (now redundant)
- Adds scripts/ha_lookup.py: queries HA /search/terms for existing
  public reports on enriched domains/IPs (cached across runs)
- Updates build_data.py to merge HA lookup family tags into
  payload_families alongside sandbox submission results

Step order: update_masq_infra → ingest_clickgrab → enrich_infra →
ha_lookup → sandbox_submit (opt-in) → cluster_campaigns → build_data

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 02:40:35 +00:00
Claude f2185ec64b refactor: replace Triage sandbox with Hybrid Analysis
Rewrites sandbox_submit.py to use the Hybrid Analysis (Falcon Sandbox)
API v2 instead of tria.ge. Key changes:

- Auth: api-key header instead of Bearer token
- Submit: POST /submit/url with environment_id=160 (Windows 10 64-bit)
- Poll: GET /report/{job_id}/state watching for state == "SUCCESS"
- Report: GET /report/{job_id}/summary, extracts vx_family,
  compromised_hosts, domains, sha256, threat_score, and verdict
- Cache files renamed: triage_submitted.json → ha_submitted.json,
  triage_results.json → ha_results.json
- Env var: TRIAGE_TOKEN → HA_API_KEY

Updates enrich.yml to use secrets.HA_API_KEY and updates step/PR
body copy to reference Hybrid Analysis.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 01:55:10 +00:00
Claude 4120dc3ea7 chore: update masq_infra.json with enrichment pipeline schema fields
Result of dry-run build_data.py execution during pipeline validation.
Adds new top-level fields (asn_distribution, country_distribution,
domain_age_histogram, campaigns, summary, date_range, generated_at)
with zero-count values since ClickGrab LFS budget is currently
exhausted. Existing fields preserved (hosting_providers, lure_types,
urlhaus_tags, etc.).

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:56:09 +00:00
Claude 7942aad326 fix: correct ClickGrab filename format and add LFS Batch API download
Dry run revealed two bugs:
1. Filename format was YYYY-MM-DD but actual files use YYYYMMDD_HHMMSS
   (e.g. clickgrab_report_20260302_032841.json)
2. All nightly reports are stored in Git LFS — raw.githubusercontent.com
   returns pointer files, not JSON content

Fix: use GitHub Contents API to list nightly_reports/ and filter by
YYYYMMDD prefix in filename. Then fetch the LFS pointer via raw URL,
resolve the real download URL via GitHub LFS Batch API, and download
the actual content.

Gracefully handles LFS budget exceeded (logs warning, empty output,
downstream scripts run cleanly with zero records — confirmed by dry run).

Also pass GITHUB_TOKEN to the ingest step in enrich.yml so the workflow
uses authenticated GitHub API calls and gets LFS access priority.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:55:34 +00:00
Claude b5dab58994 feat: add Chart.js live infrastructure charts to masq-infra page
Adds a 'Live Infrastructure Charts' section to trends/masq-infra.md
with 6 charts powered by Chart.js 4.4.3 (CDN):

  1. ASN/Hosting Distribution — horizontal bar, top 10 ASNs
     (CDN orange, bulletproof red, other purple)
  2. Country of Origin — horizontal bar, country-level only
     (IPinfo Lite free tier — no city precision)
  3. Domain Age at Observation — histogram (0-1d → 90d+ buckets)
  4. Payload Families — doughnut (Triage data); shows placeholder
     when sandbox pipeline hasn't run
  5. Campaign Timeline — swimlane (stacked bar per cluster)
  6. TLS CA Distribution — pie; falls back to stats.tls_lets_encrypt_pct
     from the existing update_masq_infra.py pipeline

Data is embedded at Jekyll build time via {{ site.data.masq_infra | jsonify }}
so charts work on GitHub Pages without serving _data/ files directly.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:45:25 +00:00
Claude a61b33d780 feat: add enrich.yml GitHub Actions workflow
Weekly Monday 07:00 UTC pipeline that runs the full ClickGrab
enrichment sequence:
  1. ingest_clickgrab.py   — fetch last 7 nightly reports from GitHub
  2. enrich_infra.py       — IPinfo Lite + VT enrichment
  3. sandbox_submit.py     — Triage sandbox (gated on ENABLE_SANDBOX=true)
  4. cluster_campaigns.py  — favicon+ASN+reg-week clustering
  5. build_data.py         — merge into _data/masq_infra.json

Cache is persisted between runs via actions/cache so DNS lookups and
VT responses are not re-queried unnecessarily. Opens a PR on the
data/enrich-clickgrab-{DATE} branch for review before publishing.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:43:27 +00:00
Claude e59919da70 feat: add build_data.py — merge enrichment pipeline into masq_infra.json
Reads cache/enriched_infra.json, cache/campaign_clusters.json, and
cache/triage_results.json (optional) to compute:
  - asn_distribution, country_distribution, domain_age_histogram
  - campaigns (from cluster data + Triage family tags)
  - summary counters (total_domains, unique_asns, etc.)
  - payload_families (from Triage; falls back to existing value)

Merges into the existing _data/masq_infra.json, preserving all fields
written by update_masq_infra.py (hosting_providers, lure_types,
traffic_sources, urlhaus_tags, tls_cert_authorities, etc.) so both
pipelines can coexist in the same data file.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:42:57 +00:00
Claude 993b413dd1 feat: add cluster_campaigns.py — favicon + ASN + reg-week clustering
Groups domains into campaigns using union-find over a composite
(favicon_hash, ASN, registration_week) signal graph. Two domains are
linked when they share ≥2 of 3 signals; clusters require ≥3 members.

Favicon hashing uses Shodan's exact MMH3 / RFC 2045 base64 algorithm
(reused from update_masq_infra.py). A blocklist of common default
favicon hashes prevents false cluster merges. Falls back to 2-key
(favicon + ASN) clustering when VT creation date is absent.

Cluster IDs are human-readable: CLUSTER-{YYYY-WW}-{ASN}.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:30:02 +00:00
Claude af00abc709 feat: add sandbox_submit.py — Triage payload sandbox integration
Submits staging URLs from the ClickGrab pipeline to Triage (tria.ge)
for behavioral analysis. Pre-submission filter requires:
  - VT malicious vote count > 0
  - Downloaded file with actionable extension (.ps1/.hta/.js/.bat/.exe/.msi)
  - Not a CDN root without a deep file path

Tracks submitted URLs in cache/triage_submitted.json to avoid
resubmission on subsequent runs. Polls events stream every 30s with
15-minute timeout, then extracts family tags, network IOCs, and dropped
file hashes from the behavioral report.

Gated in CI by ENABLE_SANDBOX=true repository variable to prevent
accidental public submissions.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:29:05 +00:00
Claude d5a8f637b2 feat: add enrich_infra.py — IPinfo Lite + VirusTotal enrichment
Resolves hostnames from ClickGrab URLs to IPs, enriches with:
- IPinfo Lite: ASN, org name, country, continent (free tier only)
- VirusTotal: reputation stats and domain creation date

Implements a sliding-window RateLimiter for VT's 4 req/min, 500/day
free tier — gracefully exits VT lookups on budget exhaustion without
crashing the pipeline. DNS and VT responses are persisted to
cache/dns_cache.json and cache/vt_cache.json across weekly runs.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:28:02 +00:00
Claude b5142969e0 feat: add ingest_clickgrab.py to fetch nightly reports from GitHub
Fetches the last 7 days of ClickGrab nightly reports from the public
MHaggis/ClickGrab repo, extracts per-URL records (url, tags,
redirect_chain, downloaded_files, script_snippets, risk_score),
deduplicates by (url, date), and writes cache/clickgrab_raw.json.

Mirrors the report schema handling from analyze_clickgrab.py to
support both old (list-of-dicts with Sites) and new (dict with sites)
report formats.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:26:46 +00:00
Claude b106293df3 chore: add cache/ to gitignore, add python-dateutil dependency
Preps for the new ClickGrab enrichment pipeline scripts which write
intermediate data to cache/ during CI runs and use dateutil for
date arithmetic.

https://claude.ai/code/session_01A9ipwynqdYKxToTJPMW8uf
2026-03-18 00:25:52 +00:00
Claude b91cb08570 feat: refocus masq-infra on infrastructure fingerprinting + campaign clustering
Script:
- Add lure categories: crypto_wallet, vpn_tool, remote_work (MetaMask, NordVPN, Zoom, Slack, etc.)
- Add brands: metamask, ledger, exodus, phantom, electrum, nordvpn, expressvpn, protonvpn, mullvad, zoom, slack
- Extract redirect chain + payload host fields from URLScan (was_redirected, payload_offhost, payload_host)
- Add classify_traffic_source() — combosquat / typosquat / seo_bait / redirected
- Add collect_malwarebazaar_brand_samples() — proactive brand-tag payload queries (no SHA256 required)
- Add fingerprint_campaigns() — cluster domains by shared_payload SHA256 or asn_cohort
- Add extract_domain_patterns() — find recurring structural naming skeletons
- Add _build_delivery_chains() — sample lure→payload hop walk-throughs
- aggregate() now includes: traffic_sources, payload_hosting, campaign_clusters, domain_patterns, delivery_chains

JSON skeleton:
- Add traffic_sources, payload_hosting, campaign_clusters, domain_patterns, delivery_chains keys
- Add traffic_source, payload_host, payload_offhost fields to recent_samples entries

Page (masq-infra.md):
- Restructured around three themes: infrastructure fingerprinting, campaign clustering, payload inventory
- New sections: Lure Taxonomy table, How Users Arrive (traffic sources), IOK rules, Delivery Chain diagram
- Detection Chokepoints expanded with concrete Sigma rules and matched payload examples
- Recent samples table updated with traffic_source and payload_host columns

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-17 04:48:25 +00:00
Claude adf1415797 feat: refocus masq-infra on infrastructure fingerprinting + campaign clustering
Script:
- Add lure categories: crypto_wallet, vpn_tool, remote_work (MetaMask, NordVPN, Zoom, Slack, etc.)
- Add brands: metamask, ledger, exodus, phantom, electrum, nordvpn, expressvpn, protonvpn, mullvad, zoom, slack
- Extract redirect chain + payload host fields from URLScan (was_redirected, payload_offhost, payload_host)
- Add classify_traffic_source() — combosquat / typosquat / seo_bait / redirected
- Add collect_malwarebazaar_brand_samples() — proactive brand-tag payload queries (no SHA256 required)
- Add fingerprint_campaigns() — cluster domains by shared_payload SHA256 or asn_cohort
- Add extract_domain_patterns() — find recurring structural naming skeletons
- Add _build_delivery_chains() — sample lure→payload hop walk-throughs
- aggregate() now includes: traffic_sources, payload_hosting, campaign_clusters, domain_patterns, delivery_chains

JSON skeleton:
- Add traffic_sources, payload_hosting, campaign_clusters, domain_patterns, delivery_chains keys
- Add traffic_source, payload_host, payload_offhost fields to recent_samples entries

Page (masq-infra.md):
- Restructured around three themes: infrastructure fingerprinting, campaign clustering, payload inventory
- New sections: Lure Taxonomy table, How Users Arrive (traffic sources), IOK rules, Delivery Chain diagram
- Detection Chokepoints expanded with concrete Sigma rules and matched payload examples
- Recent samples table updated with traffic_source and payload_host columns

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-17 04:29:33 +00:00
Claude 57e0da8caf chore: add cleanup-merged-branches.sh script
Adds a utility script to identify and delete remote branches that have
already been merged into main. Supports --dry-run mode for safe preview
before actually deleting anything.

Identified 30 merged branches ready for deletion:
- 17 claude/* work branches
- 2 chore/weekly-ttp-update-* branches
- 11 feature/fix/data/docs/misc branches

4 unmerged branches remain for review:
- claude/clickfix-malware-research-C8YsK (7 days old)
- claude/verify-clickfix-osint-pohiZ (8 days old)
- updated-chokepoints (9 days old)
- claude/review-slide-deck-content-NBanr (2 weeks old)

https://claude.ai/code/session_013k8d24eYFrsJhz1Lvr37iN
2026-03-17 02:58:26 +00:00
Claude 3eb2cc3c02 fix: remove blank line from workflow YAML causing syntax error on line 62
Blank lines inside a YAML literal block scalar (`run: |`) terminate the
block early. Moved PR body into a printf variable to avoid the blank line
in the YAML itself.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 03:16:23 +00:00
Claude 6e83367191 fix: fall back to MB_API_KEY for URLHaus auth (abuse.ch shared key)
abuse.ch issues one API key that covers both MalwareBazaar and URLHaus.
When URLHAUS_API_KEY is not set, use MB_API_KEY as the Auth-Key header
so URLHaus requests authenticate correctly without requiring a separate secret.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 02:54:42 +00:00
Claude a64ba3e37f fix: Validin DNS early-exit and workflow PR creation
Two improvements:

1. Validin DNS failure produces 100 identical warnings (one per domain)
   because api.validin.com does not resolve from GitHub Actions runners.
   Now catches requests.exceptions.ConnectionError, checks for
   NameResolutionError/Failed to resolve in the message, and breaks the
   domain loop immediately with a single warning. Non-DNS errors (timeouts,
   HTTP errors) still iterate all domains as before.

2. Workflow committed _data/masq_infra.json directly to the default branch
   with no review step. Replaced with a PR flow matching weekly-ttp-update:
   - Creates a dated branch data/masq-infra-YYYY-MM-DD
   - Commits and force-pushes (idempotent on re-runs same day)
   - Opens a PR against main via gh pr create
   - Skips PR creation if one is already open for that branch
   - Skips everything if _data/masq_infra.json has no changes
   Adds pull-requests: write permission to the workflow.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 02:47:44 +00:00
Claude 9b50e9dc42 fix: null-safe classify_lure and URLHaus Auth-Key support
Two bugs fixed:

1. TypeError in classify_lure when download_url or page_title is None.
   rec.get("download_url", "") returns None when the key exists with value
   None — the default only fires on a missing key. Fixed by coercing all
   three inputs inside classify_lure with `v or ""`, making the function
   null-safe regardless of call site.

2. URLHaus 401 Unauthorized. abuse.ch added mandatory Auth-Key header
   authentication to all /v1/ endpoints in late 2024. Added optional
   URLHAUS_API_KEY env var (free key at abuse.ch); passes Auth-Key header
   when set, warns and continues without it when unset. Updated workflow
   to expose the new secret.

Verified with: null-input classify_lure assertions, collect_urlhaus
signature check, and aggregate-with-None-fields assertions.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 02:07:34 +00:00
Claude 4ef029f18b fix: pass full sort array to search_after for URLScan pagination
URLScan's Elasticsearch backend requires all sort values for search_after
cursor pagination (typically [timestamp_ms, result_id]). Passing only
sort_val[0] produced a malformed single-value cursor, causing 400 Bad
Request on page 2+ of high-volume brand queries (discord, telegram, etc.).

Fix: pass sort_val (full list) instead of sort_val[0]. requests encodes
a list as repeated params: search_after=v1&search_after=v2, which is the
format Elasticsearch expects for composite sort cursors.

Also extend the 400 handler in _urlscan_request_with_backoff to stop
pagination gracefully for the current brand (return None) rather than
raising, so a single bad cursor doesn't crash the whole pipeline.

Validated with a requests.Request encoding test confirming both sort
values appear as separate search_after params in the prepared URL.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 01:45:11 +00:00
Claude fccf4bb0ab fix: remove over-aggressive verdicts filter in URLScan collector
Three bugs fixed in collect_urlscan():

1. Root cause of 0-results exit: the client-side verdicts.overall.malicious
   filter was dropping nearly all results. URLScan only sets this flag when
   its own scanner or a community submission explicitly marks a domain — most
   brand-impersonation sites are scanned by researchers before weaponization
   and receive no malicious verdict. Removed the filter; verdict is now stored
   on the record as urlscan_malicious for informational use only. Quality
   signal comes from MalwareBazaar/VirusTotal hash enrichment and URLHaus
   cross-reference, not URLScan verdicts.

2. IndexError on empty results page: added `if not results: break` guard
   before results[-1] access (edge case when has_more is true but results=[]).

3. IndexError on empty sort field: replaced last.get("sort", [""])[0] with
   safe extraction using `sort_val = results[-1].get("sort") or []` plus
   an explicit break if sort_val is empty.

All three bugs validated with syntax check and pure-function unit tests.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 01:36:54 +00:00
Claude 443b4ad1cd fix: drop verdicts.malicious:true filter from URLScan query
The verdicts.malicious filter requires an elevated API tier; free keys
receive a 403. Replace with client-side filtering on verdicts.overall.malicious
from the response payload, which is available on all tiers.

Also handle 403 responses gracefully (log + skip) instead of raising,
so a single restricted query doesn't crash the entire pipeline.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 01:23:57 +00:00
Claude 9048d6a6f0 fix: strip whitespace from API key env vars
Prevents requests.exceptions.InvalidHeader when secrets are stored with
leading/trailing whitespace (common from copy-paste into GitHub Secrets UI).

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-16 01:15:57 +00:00
Claude 11841776e9 feat: masq-infra weekly data pipeline
- Add scripts/update_masq_infra.py: queries URLScan, crt.sh, Shodan,
  Validin, URLHaus, MalwareBazaar, and VirusTotal to collect real-world
  stats on software-impersonation infrastructure. Supports --dry-run flag.
- Add .github/workflows/update-masq-infra.yml: runs every Monday 06:00 UTC,
  commits updated _data/masq_infra.json; no-op when data unchanged.
- Add _data/masq_infra.json: initial skeleton so Jekyll renders without error
  before the first pipeline run.
- Update trends/masq-infra.md: replace hardcoded stat cards with Liquid
  variables; add data-driven sections for hosting providers, lure types,
  payload families, URLHaus tags, favicon clusters, and recent samples —
  all guarded by sample_size > 0 so the page degrades gracefully.
- Update requirements-update.txt: add mmh3>=4.1.0, shodan>=1.31.0.

https://claude.ai/code/session_018u1RitQLKpYyxFBTRbFKnM
2026-03-15 20:37:52 +00:00
Claude 43693035fe feat: add payload examples and infra enrichment to clickgrab trends
- Detection recommendation cards now have expandable "Example payloads"
  sections showing real/representative command strings per category
  (IWR/IEX, IRM/IEX, WebClient, Curl, Base64 encoded+decoded, self-delete,
  CDN staging URLs, hidden-window)

- Staging infrastructure table rows are now click-to-expand with detail
  panels showing hosting type badge, status, ASN/geo, domain registration
  date, registrar, and a SecurityTrails DNS history link per entry

- analyze_clickgrab.py extended with:
  - payload_examples collector: harvests up to 3 deduplicated examples per
    detection category from PowerShellCommands / EncodedPowerShell /
    Base64Strings / PowerShellDownloads fields on each pipeline run
  - enrich_domain(): calls ip-api.com (ASN/geo) and RDAP (registration
    date/registrar) per staging domain; results written to YAML
  - HOSTING_ANALYST lookup dict for manually-tagged hosting_type/status

- _data/clickgrab_trends.yml pre-populated with representative payload
  examples and analyst-tagged enrichment fields (ASN/geo populated by
  pipeline on next run; DNS history links to SecurityTrails free tier)

- assets/css/style.css: .cg-payload-example, .cg-payload-meta,
  .cg-payload-label, .cg-infra-detail-*, .cg-badge-hosting-*,
  .cg-badge-status-* classes

https://claude.ai/code/session_0183gMN46x4Gaq6JxTc3SvrG
2026-03-15 17:15:19 +00:00
Claude ce0ffade0c feat: replace Q1/chokepoint-shifts pages with masq-infra analysis
Removed the two placeholder trend pages (2025-q1.md, chokepoint-shifts.md)
that didn't fit the site's analysis-first direction.

Added trends/masq-infra.md — a full analysis of software impersonation
infrastructure covering:
- Domain naming patterns (typosquatting, combosquatting, homoglyphs)
- Hosting provider abuse (Cloudflare Pages, GitHub Pages, Firebase)
- Favicon abuse from both attacker and defender perspectives, including
  Murmur3 hash pivoting on Shodan/Censys for infrastructure clustering
- Detection chokepoint chain (T1036.005 PE metadata mismatch, execution
  from download paths, MotW, cert transparency monitoring)

Updated trends/index.md to replace two old cards with the new page.
All styling uses CSS variables for full dark/light theme compatibility.

https://claude.ai/code/session_01Nza6uzSyU61aAX1txaoGve
2026-03-15 04:17:34 +00:00
Claude 3c42e27d0e style: convert clickgrab page hardcoded colors to CSS variables
Replaces all hardcoded dark-mode hex values (#c9d1d9, #8b949e, #30363d,
#161b22, #21262d, #58a6ff, #e3b341, #f0883e, #da3633, #388bfd, #3fb950)
with the site's CSS variable system (var(--text), var(--text-muted),
var(--border), var(--bg-card), var(--bg-input), var(--link), var(--high),
var(--accent), var(--critical), var(--low), var(--medium)).

Consistent with chokepoint and attack-chain pages, and now compatible
with the site's dark/light theme toggle.

https://claude.ai/code/session_01Nza6uzSyU61aAX1txaoGve
2026-03-15 03:54:45 +00:00
Claude 21f7a258eb style: add themed styling to chokepoint-shifts and 2025-q1 trend pages
Both pages were rendering as unstyled raw markdown. Added the same
.cg-page layout wrapper used by clickgrab.md, but using CSS variables
(var(--text), var(--text-muted), var(--border), var(--link), var(--bg-card))
instead of hardcoded hex values — consistent with the rest of the site
(chokepoints, attack-chain pages) and compatible with the dark/light theme toggle.

https://claude.ai/code/session_01Nza6uzSyU61aAX1txaoGve
2026-03-15 03:50:35 +00:00
Claude 2aad04e6e6 fix: add Jekyll frontmatter and permalinks to trends subpages
All three trend subpages were unreachable:
- chokepoint-shifts.md and 2025-q1.md had no YAML frontmatter, so
  Jekyll treated them as static files (copied as .md, not rendered to
  HTML) — navigating to /trends/chokepoint-shifts/ produced a 404.
- clickgrab.md had frontmatter but no explicit permalink, so Jekyll
  output it at trends/clickgrab.html while the index linked to
  /trends/clickgrab/ (trailing slash), also a 404.

Fix: add layout, title, description, and explicit permalink to each
subpage so Jekyll renders them as proper HTML pages at the expected URLs.

https://claude.ai/code/session_01Nza6uzSyU61aAX1txaoGve
2026-03-15 03:29:41 +00:00
Claude d64ba068c4 Add Kaspersky-style TTP overlap flow diagram to attack chain pages
Adds a vertical node-graph flow diagram to the ransomware and infostealer
attack chain pages showing which MITRE techniques are shared across the
groups/families already tracked in the actor convergence matrix. Colored
dots on each technique node indicate which actors use it — techniques where
all dots are filled are universal chokepoints and the highest-ROI targets
for detection engineering.

- _data/ransomware_ttp_overlap.yml: 9 phases, ~35 techniques mapped to
  BlackBasta, LockBit 3.0, Akira, Alphv/BlackCat, and Play
- _data/infostealer_ttp_overlap.yml: 6 phases, ~16 techniques mapped to
  RedLine, LummaC2, Vidar, StealC, and Raccoon
- _includes/ttp-overlap-diagram.html: legend + SVG container + JSON data
  injection consumed by ttp-overlap.js
- assets/js/ttp-overlap.js: vanilla JS SVG renderer with hover tooltips;
  nodes with full group coverage highlighted in accent orange
- _layouts/attack-chain.html: new TTP overlap section (show_ttp_overlap
  front-matter flag), ttp-overlap.js script tag, and supporting CSS
- attack-chains/ransomware.md, infostealers.md: opt-in front-matter flags

https://claude.ai/code/session_01VVQNo9RGmnS6CTLVZxFuJW
2026-03-14 04:34:33 +00:00
Claude bd93e99fe7 fix: remove orphaned Liquid endif in attack-chain.html
The {% if page.chokepoints %} block wrapping the Mermaid script was
replaced but its closing {% endif %} after the <style> block was left
behind, causing 'Unknown tag endif' at build time.

https://claude.ai/code/session_01HSkU42mGpi5VjgjXd3HcZi
2026-03-13 02:22:33 +00:00
Claude 5a66d4f096 feat: replace Mermaid flowchart with SVG swimlane attack-flow diagram
Redesigns the attack chain visualization on ransomware and infostealer
pages from a basic Mermaid LR flowchart to a three-swimlane SVG diagram
that maps attacker actions, MITRE ATT&CK techniques, and detection
posture at each stage.

Key changes:
- _includes/attack-flow.html: new Liquid-driven inline SVG swimlane
  (3 lanes: Attacker / ATT&CK / Detection). Fully driven by page YAML;
  no CDN requests. Each stage is keyboard-focusable with ARIA labels.
- assets/js/attack-flow.js: ~1.5 KB vanilla JS for hover/focus/touch
  tooltips showing ATT&CK IDs, technique names, and detection signals.
- assets/css/style.css: ~280 lines of .af-* rules covering dark/light
  themes, color-blind-safe edge patterns, reduced-motion, and the
  tooltip component. WCAG 2.2 AA compliant.
- _layouts/attack-chain.html: replaces Mermaid block + CDN script with
  {% include attack-flow.html %} and deferred attack-flow.js load.
- attack-chains/ransomware.md + infostealers.md: enriched YAML with
  mitre_tactic, mitre_techniques[], detection_status, attacker_action,
  and systems fields for all stages.

Detection-status color coding: red=exploited, yellow=detected,
green=blocked (also encoded as stroke patterns for color-blind users).
Total added payload: ~25 KB inline SVG + 1.5 KB JS (Mermaid CDN removed).

https://claude.ai/code/session_01HSkU42mGpi5VjgjXd3HcZi
2026-03-13 02:13:48 +00:00
Claude 03dc09fb90 feat: redesign attack chains page for clarity and de-duplication
- Replace stage pills with chokepoint stage cards that show the invariant
  prerequisite, top detection signals, and hyperlinked chokepoints per stage
- Keep Mermaid flowchart as visual attack chain illustration (future enhancement)
- Remove duplicate prose sections: per-stage breakdowns, common actor family
  profiles, and layered detection strategy bullets (all now in stage cards or matrix)
- Extend stage frontmatter with detection_signals and chokepoint_links arrays
- Add actor status badges to convergence matrix (Active / Disrupted / Defunct /
  Inactive) reflecting current threat landscape accuracy:
  Ransomware: BlackBasta=Inactive, LockBit=Disrupted, Alphv=Defunct
  Infostealers: RedLine=Disrupted (Op Magnus Oct 2024), Raccoon=Disrupted (Oct 2023)
- Fix broken chokepoint links from raw .yml paths to /chokepoints/[slug]/ URLs

https://claude.ai/code/session_013ezw6S3Ba8uSDMLYyTE6yp
2026-03-13 01:31:59 +00:00
Claude 7461fcb156 fix: force-push update branch to handle re-runs on the same day
When the workflow is re-triggered (manually or after a failure) on the same
calendar day, the branch chore/weekly-ttp-update-YYYY-MM-DD already exists on
the remote. The plain `git push` is rejected with "fetch first".

Use `--force` since these branches are exclusively managed by the automation —
no human commits ever land on chore/weekly-ttp-update-* branches. Force-pushing
keeps any existing open PR updated with the latest run's data.

https://claude.ai/code/session_014vs9nGxHZPgFYkbcZrRpjK
2026-03-12 14:01:35 +00:00
Claude 56fcea0b3a chore: gitignore MITRE cache and pycache from update script
https://claude.ai/code/session_014vs9nGxHZPgFYkbcZrRpjK
2026-03-12 05:11:07 +00:00
Claude 026e67da37 fix: replace feedparser with stdlib XML parsing to fix install failure
feedparser depends on sgmllib3k, which requires sgmllib — a module removed
from Python 3 stdlib. sgmllib3k fails to build on the Actions runner,
causing ModuleNotFoundError and aborting the workflow before any intel
is collected.

Replace fetch_rss_articles with a stdlib-only implementation using
xml.etree.ElementTree + email.utils.parsedate_to_datetime. Handles both
RSS 2.0 and Atom feeds. Remove feedparser from requirements-update.txt.

https://claude.ai/code/session_014vs9nGxHZPgFYkbcZrRpjK
2026-03-12 05:10:25 +00:00
Claude 90b882d645 fix: remove invalid thinking param and fix workflow git add + label bugs
Three bugs causing the weekly TTP update workflow to fail:

1. `thinking={"type": "adaptive"}` is not a valid Anthropic API parameter —
   "adaptive" is not a recognised type (valid: "enabled"/"disabled"). This
   caused a 400 error on every Claude API call. Removed the thinking param
   from both analyze_article_with_claude and validate_accuracy_with_claude.

2. `git add scripts/.seen_articles.json` fails with exit code 1 on the first
   run before those files are committed. Split into two git add calls and
   added --ignore-errors for the optional cache files.

3. `--label "automated,ttp-update"` is interpreted as a single label name
   rather than two labels, and fails if neither label exists on the repo.
   Removed the --label flag entirely.

https://claude.ai/code/session_014vs9nGxHZPgFYkbcZrRpjK
2026-03-12 04:19:03 +00:00
Claude 06bafa0ddd Add Mermaid.js attack flow visualization to attack chain pages
Adds an interactive flowchart section between the stage pills and the
Actor Convergence Matrix on all attack chain pages. The diagram renders
from existing YAML front-matter (no data changes) — stage nodes connect
left-to-right with dotted arrows dropping to orange chokepoint nodes,
making the invariant prerequisites immediately visible at a glance.

- _layouts/attack-chain.html: new "Attack Flow Visualization" section
  using Liquid-templated Mermaid syntax; Mermaid v11 loaded via jsDelivr
  CDN with base theme and transparent background to match site styling
- assets/css/style.css: .ac-flowviz-wrap styles for responsive overflow
  and SVG transparency

https://claude.ai/code/session_01TnmRypmV2fragVoDG3Q77G
2026-03-12 03:03:58 +00:00
Claude ccbdd3d984 feat: add automated weekly TTP update pipeline with accuracy validation
Adds a fully automated weekly pipeline that:
- Collects threat intel from 10 RSS feeds + CISA KEV each Sunday
- Uses Claude (claude-opus-4-6 with adaptive thinking) to extract new attack
  variants and map them to existing chokepoints
- Applies additive-only YAML patches (new Variations + EvolutionTimeline entries)
  to chokepoint files when confidence >= 70%
- Validates existing data accuracy every run:
    • MITRE ATT&CK ID deprecation/revocation check (via STIX)
    • Broken Intel reference link detection (HTTP 404 check)
    • Stale entry flagging (entries >90 days since LastUpdated)
    • Claude factual review per chokepoint against this week's articles
- Opens a GitHub PR with a structured Markdown report for human review
  before any changes are merged — never auto-merges

New files:
  scripts/update_ttps.py          — main pipeline script
  scripts/sources.yml             — intel source configuration
  .github/workflows/weekly-ttp-update.yml — Actions cron (Sundays 00:00 UTC)
  requirements-update.txt         — Python deps (anthropic, feedparser, requests)

Setup: add ANTHROPIC_API_KEY as a GitHub Actions repository secret.
Local test: python scripts/update_ttps.py --dry-run

https://claude.ai/code/session_014vs9nGxHZPgFYkbcZrRpjK
2026-03-12 02:15:06 +00:00
Claude d08dc8e657 feat: render attack chain pages with actor convergence matrix
Replaces GitHub-only links with fully rendered Jekyll pages for the
ransomware and infostealer attack chains. The centrepiece of each page
is an Actor Convergence Matrix — a table showing every tracked threat
actor as a row and each attack-chain stage as a column, with the
invariant chokepoint condition highlighted in a footer row.

Changes:
- _config.yml: remove attack-chains/ from exclude list so Jekyll
  renders the markdown files into site pages
- _includes/nav.html: point "Attack Chains" nav link to the site page
  (/attack-chains/) instead of the GitHub directory; add active-state
  class for current-page highlighting
- _layouts/attack-chain.html: new layout that renders breadcrumb,
  "Chokepoint Convergence Principle" callout, numbered stage-flow
  diagram, Actor Convergence Matrix (with invariant chokepoint footer
  row), and the existing markdown prose — all theme-aware via CSS vars
- assets/css/style.css: append .ac-* component classes (insight
  callout, stage pills, matrix table, index cards, index hero)
- attack-chains/index.md: new landing page listing both chains with
  styled cards linking to each rendered page
- attack-chains/ransomware.md: add Jekyll front matter with 5-actor ×
  5-stage YAML data (BlackBasta, LockBit 3.0, Akira, Alphv/BlackCat,
  Play) and invariant chokepoint conditions; add Play ransomware to the
  families section (n-day exploit entry vector)
- attack-chains/infostealers.md: add Jekyll front matter with 5-actor ×
  5-stage YAML data (RedLine, LummaC2, Vidar, StealC, Raccoon) and
  invariant chokepoint conditions; expand LummaC2 entry with ClickFix /
  LOLBin execution detail

https://claude.ai/code/session_01Y2t5fMHmVzoi2ocPs4oAxM
2026-03-11 14:30:55 +00:00
Claude 512c772559 feat(site): render EarlyDetections section on chokepoint pages
Two-part fix for EarlyDetections (ETW clipboard + IOK lure) not showing
on the web page:

scripts/aggregate.py:
- Add enrich_early_detections() helper that reads SigmaRule / IokRule
  file paths referenced in EarlyDetections entries and embeds the raw
  text as _rule_content in each entry dict
- Call it from load_chokepoints() alongside existing _sigma_* enrichment

_layouts/chokepoint.html:
- Add "Early Detection Layers" section between Detection Strategy and
  Evolution Timeline; loops over cp.EarlyDetections and renders each
  entry with Description, Log Sources, FP Rate, Use Case, Detection Logic,
  and the embedded rule (Sigma or IOK) in a syntax-highlighted code block
  with View on GitHub / Download / Copy buttons

https://claude.ai/code/session_017p1YPPCPfK5PvtKdgvcreb
2026-03-10 02:34:06 +00:00
Claude 8c016951be feat(clickfix): add ETW clipboard + IOK lure detections, EarlyDetections layer
New detection data sources targeting earlier kill chain stages than existing
Sysmon-based Research/Hunt/Analyst rules:

EarlyDetections section (new top-level key in clickfix-techniques.yml):
- Pre-Execution (ETW): browser clipboard write via Microsoft-Windows-Win32k
  SetClipboardData; fires before user pastes; covers all variants because
  clipboard seeding is an inescapable prerequisite
- Pre-Interaction (IOK): lure page fingerprint via phish.report IOK format;
  clipboard_api AND execution_hint co-occurrence is the stable invariant
  across all ClickFix variants regardless of visual design or threat actor

New files:
- sigma-rules/clickfix/etw-clipboard.yml: Sigma rule for ETW clipboard write
  detection (Microsoft-Windows-Win32k / OLE.Clipboard providers via SilkETW)
- iok-rules/clickfix/clickfix-lure.yml: IOK rule for lure page detection;
  detects navigator.clipboard.writeText + Run dialog / terminal instructions

Intel additions: Matt Graeber ETW gist, SilkETW, phish.report IOK docs + GitHub

https://claude.ai/code/session_017p1YPPCPfK5PvtKdgvcreb
2026-03-10 02:17:17 +00:00
Claude 32b275e37c feat(clickfix): add 4 new variants, fix timeline accuracy, update hunt rule
New variants added to Variations and EvolutionTimeline:
- WebDAV ClickFix (2025-Q1): mshta.exe + UNC WebDAV paths, fileless .NET
  assembly injection, steganography in PNG; LummaStealer/Xworm/AsyncRAT payloads
- InstallFix (2026-Q1): clones software install docs (Claude Code CLI etc.)
  via Google Ads malvertising; mshta.exe → Amatera infostealer
- Windows Terminal ClickFix (2026-Q1): Win+X→I lure, hex/XOR-encoded PS,
  wt.exe parent bypasses Run-dialog detections; MSBuild.exe LOLBin; Lumma Stealer
  (Microsoft Defender Experts disclosure, March 6 2026)
- DNS-based ClickFix / KongTuke (2026-Q1): nslookup staging via DNS Name field
  (not TXT), evades URL filtering; ModeloRAT payload (Microsoft, Feb 2026)

Accuracy fixes:
- Remove fabricated 2024-Q3 "FileFix Variant" timeline entry (wrong date,
  wrong description); correct FileFix entry already exists at 2025-Q2
- Fix DNS-based ClickFix FirstSeen: "2025-Q4" → "2026-Q1"
- Fix timeline ordering: nation-state entry sorted back to 2024-Q4 position

Hunt rule updates (sigma-rules/clickfix/hunt.yml):
- Add wt.exe / WindowsTerminal.exe as parent process in selection_parent_explorer
- Update description and references for Windows Terminal variant
- Add hunt notes for wt.exe and nslookup.exe pivots

https://claude.ai/code/session_017p1YPPCPfK5PvtKdgvcreb
2026-03-10 01:54:26 +00:00
Claude e3dc13b5cd feat(sigma-rules): add research/hunt/analyst rules for edr-bypass and web-shells
Creates six Sigma rules covering the two highest-priority detection chokepoints:

EDR Bypass Techniques (sigma-rules/edr-bypass/):
- research.yml: All non-Microsoft/unsigned kernel driver loads (Sysmon EID 6)
  for environment baselining; baseline before BYOVD hunt tuning
- hunt.yml: sc.exe/net.exe/taskkill.exe targeting named security agent
  services/processes; includes SIEM correlation query for driver load pivot
- analyst.yml: High-fidelity named security process termination + EDRSilencer
  WFP filter add detection; full response checklist + Sentinel KQL

Web Shell Persistence (sigma-rules/web-shells/):
- research.yml: All child processes from web server parents (w3wp.exe, httpd,
  nginx, java, php-cgi) for baseline inventory
- hunt.yml: Web server spawning shell interpreters or recon utilities; covers
  both active execution and script file drop in web-accessible directories
- analyst.yml: Web server parent + suspicious cmd/PowerShell command line
  (recon, encoded commands, downloaders); covers China Chopper, Godzilla,
  Behinder, LEMURLOOT, GLASSTOKEN, ProxyShell patterns

Paths match SigmaRule references in chokepoint YAML definitions.
All rules follow detection.maturity.research/hunt/analyst tag convention.

https://claude.ai/code/session_01Dhh3LC2SPpDcEB1sjiDybv
2026-03-08 21:05:06 +00:00
Claude c690e8ad0f fix(osint): improve OsintSources across all remaining chokepoint files
Applied the same methodology used for clickfix-techniques.yml to evaluate
and improve the OsintSources blocks in all five remaining chokepoint files.

renamed-rmm-tools.yml (moderate):
- Expanded URLScan filename query with support*.exe and verify*.exe pretexts
- Updated Shodan note to also cover SimpleHelp (CISA AA25-163A, June 2025)
- Replaced Censys AnyDesk cert query with SimpleHelp (AnyDesk certs were
  revoked after the Feb 2024 breach, making that query largely historical)
- Added VT Intelligence PE metadata query for renamed RMM binaries in the wild
- Added LOLRMM.io — the community catalog of RMM tool file/network indicators

remote-execution-tools.yml (significant):
- Removed port:445 country:US — returns millions of results with zero
  signal for hunting attack infrastructure; was an exposure audit query,
  not a threat hunting query
- Repositioned WinRM query with clearer notes about its scope (exposure
  audit, not attacker infra hunting)
- Added Shodan JARM fingerprint query for Cobalt Strike team servers —
  the correct approach for hunting C2 infra paired with Impacket/NetExec
- Added hunt.io for real-time C2 infrastructure mapping

ransomware-service-manipulation.yml (minor):
- Fixed ANY.RUN URL from general trends page to the actual public
  submissions feed with ransomware filter
- Added Ransomware.live for real-time ransomware group activity tracking
- VT Intelligence and GitHub queries were solid; kept as-is

web-shells.yml (minor):
- Expanded Shodan title query with FilesMan and Antak Webshell
- Expanded URLScan filename query with webshell.php and cmd.aspx
- Added Censys eval(base64_decode) query for live obfuscated PHP shells
- VT Intelligence tag:webshell query was the strongest in any file; kept

edr-bypass-techniques.yml (minor):
- Added LOLDrivers (loldrivers.io) — the canonical community catalog of
  vulnerable and malicious drivers used in BYOVD attacks; was absent
  entirely despite being the most important resource for this chokepoint
- All three existing queries were solid; kept as-is

https://claude.ai/code/session_01CeEB6yuJimygkCBi7ubSh3
2026-03-08 15:45:59 +00:00
Claude 478cd16e79 fix(clickfix): replace weak OSINT queries with high-signal infrastructure hunts
The previous OsintSources block had three problems:

1. URL keyword query (page.url:*clickfix* / *filefix*) was removed entirely.
   These are researcher-coined names — real threat actor infrastructure
   never uses them in URLs. The query only surfaces honeypots and
   researcher submissions, not actual malicious sites.

2. Bare clipboard API query (navigator.clipboard) had high FP rate because
   the API is common on legitimate sites. Replaced with three targeted queries
   that combine clipboard API presence with ClickFix-specific UI signals:
   deceptive page titles (verify/captcha/update), fake CAPTCHA text
   ("I am not a robot"), and keyboard execution instructions (Win+R, Ctrl+V).

3. VirusTotal Pastebin staging query is increasingly stale. Modern ClickFix
   campaigns (2025-2026) use DNS-based staging via nslookup (Microsoft
   disclosure Feb 2026) and encoded PowerShell droppers. Both are now
   covered. Legacy Pastebin note retained in the updated query's Notes field.

Added hunt.io as a third platform — it actively fingerprints ClickFix
infrastructure and is a proven community resource for this technique.

https://claude.ai/code/session_01CeEB6yuJimygkCBi7ubSh3
2026-03-08 15:19:26 +00:00
Claude 197082ec5f Apply 2025 SaaS design modernisation with Tailwind CSS (hybrid approach)
Adds Tailwind Play CDN alongside the existing CSS-variable colour system so
layout/typography/spacing are driven by utility classes while dark/light
theming continues via custom properties — keeping the dark default theme and
the toggle shipped in the previous commit.

Changes:
- _layouts/default.html: add Tailwind CDN script, Tailwind base on <body>,
  update footer to use Tailwind layout classes
- assets/css/style.css: strip all layout/spacing/typography rules that are
  now handled by Tailwind; retain colour variables, [data-theme="light"]
  overrides, JS-driven state classes (.filter-chip.active, .tab-btn.active,
  .tab-panel), [data-priority] card top-border selectors, pseudo-elements,
  and hover states referencing CSS vars; add .badge + detail-page colour rules
  for class names used in the newly updated chokepoint.html
- _includes/nav.html: replace custom layout classes with Tailwind flex/spacing
  utilities; keep .site-nav, .nav-logo, .nav-github for colour
- index.html: hero, search, filter chips, results meta, grid, no-results all
  use Tailwind layout utilities; functional IDs and data attributes unchanged
- _includes/chokepoint-card.html: Tailwind layout on card/link/flex containers;
  colour classes (priority-badge, card-title, etc.) remain for CSS vars
- _layouts/chokepoint.html: full Tailwind layout on article/header/sections;
  fix orphaned class mismatches (.data-table, .badge, .sigma-tabs etc.) that
  had no matching CSS rules; keep .tab-btn/.tab-panel/.copy-btn for JS

https://claude.ai/code/session_01WYiTax4PjLA9RC8JmHjLFG
2026-03-05 06:53:21 +00:00