Guardian
Guardian
Personal · OSS · 2026

Overview

Guardian is the monitoring layer built in response to a real supply-chain campaign (October 2026) that planted dormant execution hooks and disguised payloads into my repositories via git history rewrites — lookalike commits carrying the original messages, dates, and authors over different trees. It answers one structural insight: anything stored inside a victim repo can be neutralized by the same credential that infected it. Branch protection, workflows, revert scripts — all editable in-repo. So the watcher lives outside the blast radius, and its PAT is read-only.

Architecture & Flow

guardian-sweep.yml (guardian repo, public = free Actions minutes)
  • cron ×4/hour (:02 :17 :32 :47 — redundant slots; GitHub drops
    scheduled runs under load) + workflow_dispatch
  • lists repos via fine-grained read-only PAT, scans every branch
  • findings → GitHub issue + Telegram alert
  • issue dedup: comments on an open IOC issue <90 min old

malware-guard.yml (per-repo, private repos without ruleset plans)
  • on push: scan tree → verdict != clean → force-revert the branch
    to the pre-push SHA via the ephemeral GITHUB_TOKEN (nothing stealable)

rulesets (public repos): required_signatures + non_fast_forward + deletion
guardian-dispatcher (Cloudflare Worker): external heartbeat
guardian-webhook (Cloudflare Worker): HMAC-verified webhook → scan → revert

Finding → issue → Telegram, end to end: when a sweep detects an artifact, it opens a GitHub issue on the guardian repo with the finding class and affected refs — repo names masked as R-<8hex> (sha256(name+salt), resolved locally via a derived map since the salt never leaves the machine) — and posts a Telegram message to a private group via bot API with the real repo names and artifact paths. Duplicate findings within 90 minutes become comments on the open issue instead of new spam.

Two-stage detection keeps API usage sane: stage 1 selects candidates from the tree API (path + size, one call per branch) — presence policies for .vscode/* and public/fonts/*, executable surfaces, name-matched fake-font patterns at any size (a 29KB .orc payload once sailed over a naive 10KB gate); stage 2 fetches and arbitrates content with two-condition markers. Every fetch failure is a SCAN-ERROR, never a clean verdict — a throttled run once reported 134 infected refs as clean by failing silently; that class of silence is designed out.

The scheduler that silently stopped: after the campaign, GitHub's Actions scheduler began dropping the repo's native cron (suspected account abuse-flag; workflow_dispatch still worked). The fix is guardian-dispatcher — a Cloudflare Worker on a */20 cron that checks the last sweep run via the public API (no token) and dispatches only when stale (>45 min), making it idempotent with the native cron: whichever fires first wins, no duplicate sweeps. guardian-webhook closes the push path: repo webhooks → HMAC verify → IOC scan → force-revert + Telegram, living outside all repos with a Contents-RW token that deliberately has no workflow scope.

Platform Constraints Learned (the hard way)

  • Branch rulesets: public repos on any plan; private repos need Pro/Team — failures reported, not fatal (the in-repo guard covers the gap)
  • Server-side path blocking (file_path_restriction): org repos on paid plans only — the compensating control is detection speed (≤ ~1h)
  • REST Contents-API commits are unsigned — any workflow committing via API must live in a repo without required_signatures (why guardian's own ruleset omits it)
  • The force-revert step's if: must include always() — the scan step exits 1 on detection, and GitHub skips dependent steps on red

The Layers Today

Layer

Where

Protects

guardian-sweep (hourly IOC sweep)

guardian repo, read-only PAT

all repos, all branches

malware-guard (push scan + force-revert)

per-repo workflow / rulesets

the push path

guardian-dispatcher

Cloudflare Worker

the schedule itself

guardian-webhook

Cloudflare Worker

out-of-band push tamper guard

Tech stack

Github Cloudflare Tools

Architecture


            guardian/  (github.com/athallarizky/guardian)
├── .github/workflows/
│   └── guardian-sweep.yml      # cron ×4/h + dispatch: list repos → scan branches
│                                #   → issue (R-masked names) + Telegram (real names)
├── guard/
│   ├── malware-guard.yml       # per-repo template: push scan → force-revert
│   └── guardian-sweep.yml      # sweep template (live copy in guardian repo)
├── scripts/                    # protect-repos / deploy-guard / guardian-map /
│                               #   ruleset-lift / onboard-repo
└── AGENTS.md                   # alert-triage runbook

guardian-dispatcher/  (Cloudflare Worker — cron */20, staleness gate 45 min)
guardian-webhook/     (Cloudflare Worker — HMAC webhook guard → revert + TG)
…