AI-curated security research feed — auto-updated daily, deployed to GitHub Pages. Supports GitHub Copilot or Claude as the AI classifier backend.
Fork this repo, add your feeds, and get your own daily security feed at https://<you>.github.io/daily-security-feed/ with optional Discord/Slack notifications.
- Fork this repository.
- Delete
state/processed_urls.json— it contains the upstream's seen URLs and will prevent your fork from fetching articles that were already processed here. - Enable GitHub Pages in your fork:
Settings → Pages → Source → GitHub Actions. - Edit
feeds/feeds.yamlwith the RSS/Atom feeds you want to follow. - Add the required secrets and variables.
- Set up your AI backend — either Copilot or Claude.
- Open Actions and run
daily-security-feed-botmanually to seed the first batch. - Your site will be live at
https://<you>.github.io/daily-security-feed/after the first run.
flowchart TD
A["⏰ Cronjob — Daily at 05:00 Asia/Amman · UTC+3"]:::trigger
B["Fetch & scrape new articles from RSS feeds"]:::fetch
C["Filter & classify with AI keep research, assign priority"]:::classify
D["Write markdown posts to site/_posts/"]:::write
E["Commit & push → Jekyll rebuilds GitHub Pages"]:::persist
F["Post digest to Discord"]:::notify
G["Post digest to Slack"]:::notify
H(["⚠ On failure — send error alert to Discord + Slack"]):::failure
I(["📅 Monthly — remind to rotate secrets"]):::monthly
A --> B --> C --> D --> E
E --> F & G
E -.-> H
A -.-> I
classDef trigger fill:#1f3a5f,stroke:#3b82f6,color:#e2e8f0
classDef fetch fill:#1a3a2a,stroke:#22c55e,color:#e2e8f0
classDef classify fill:#2a1a3a,stroke:#a855f7,color:#e2e8f0
classDef write fill:#3a2a1a,stroke:#f97316,color:#e2e8f0
classDef persist fill:#1a2a3a,stroke:#38bdf8,color:#e2e8f0
classDef notify fill:#3a1a1a,stroke:#ef4444,color:#e2e8f0
classDef failure fill:#1a1a1a,stroke:#f87171,color:#f87171,stroke-dasharray:4 4
classDef monthly fill:#1a1a1a,stroke:#fbbf24,color:#fbbf24,stroke-dasharray:4 4
Secrets (Settings → Secrets and variables → Actions → Secrets):
| Secret | Required | Description |
|---|---|---|
COPILOT_TOKEN |
If using Copilot | Fine-grained PAT with Copilot Requests: Read permission |
ANTHROPIC_API_KEY |
If using Claude | Anthropic API key |
DISCORD_WEBHOOK_URL |
No | Discord channel webhook for notifications |
SLACK_WEBHOOK_URL |
No | Slack incoming webhook for notifications |
Variables (Settings → Secrets and variables → Actions → Variables):
| Variable | Example | Description |
|---|---|---|
CLASSIFIER_BACKEND |
copilot or claude |
AI backend for classification (default: copilot) |
CLAUDE_MODEL |
claude-sonnet-4-20250514 |
Claude model ID — only used when backend is claude |
NOTIFY_CHANNELS |
both, discord, or slack |
Where to send notifications (default: both) |
SKIP_CLASSIFY |
true or false |
Skip AI classification — publish all fetched articles (default: false) |
PAGES_URL |
https://you.github.io/daily-security-feed/ |
GitHub Pages site URL — included as a "Browse feed" link in Discord and Slack notifications |
Note
Copilot requires an active GitHub Copilot Pro subscription on the repo owner's account. Claude requires an Anthropic API key with sufficient credits.
Create COPILOT_TOKEN as a fine-grained personal access token:
- Go to GitHub
Settings→Developer settings→Fine-grained personal access tokens. - Create a token for the account that owns the Copilot entitlement used by this pipeline.
- Grant the minimum permission required:
Copilot Requests: Read. - Set a short expiration date and store the token only in
Repo → Settings → Secrets and variables → ActionsasCOPILOT_TOKEN. - Re-run the workflow after adding it to verify classification works.
Do not use a classic PAT here. Keep the token scoped only for Copilot requests.
To use Claude instead of Copilot:
- Get an API key from the Anthropic Console.
- Add
ANTHROPIC_API_KEYtoRepo → Settings → Secrets and variables → Actions → Secrets. - Set the repo variable
CLASSIFIER_BACKENDtoclaude. - Optionally set
CLAUDE_MODELto a specific model ID (default:claude-sonnet-4-20250514). - Re-run the workflow to verify classification works.
| What | Where |
|---|---|
| Feed list | feeds/feeds.yaml — add/remove RSS/Atom URLs |
| Articles per run | MAX_ARTICLES env var (workflow default: 30) |
| Entries per feed | ENTRIES_PER_FEED env var (default: 5) |
| Max article age | MAX_ARTICLE_AGE_DAYS env var (default: 7) — skip entries older than this |
| AI system prompt | prompts/classify.md |
| Site theme | site/_config.yml and site/_layouts/ |
Feed content is untrusted input. A malicious article can include indirect prompt-injection text that tries to coerce the classifier into revealing secrets or following attacker instructions.
- Keep
COPILOT_TOKEN,ANTHROPIC_API_KEY,DISCORD_WEBHOOK_URL, andSLACK_WEBHOOK_URLonly in GitHub Actions secrets. - Use least-privilege credentials only. Do not reuse repo-admin, org-admin, or broadly scoped API tokens.
- Rotate the Copilot PAT, Anthropic API key, and notification webhooks regularly.
- Re-run the pipeline after rotation to verify the new secrets work.
This project processes untrusted RSS/Atom content and passes it to an AI classifier. We implement multiple layers of defense against indirect prompt injection:
- Pre-classifier scanning (
pipeline/injection_scanner.py) — a heuristic engine that normalises text through 8 layers (HTML entities, URL encoding, Unicode NFKD, zero-width characters, homoglyphs, leetspeak, base64 decoding) and matches against injection patterns in 14 languages before content ever reaches the AI. All prompt-interpolated fields (content, title, URL, feed, published date) are scanned. Articles that match are quarantined and never sent to the classifier. - In-prompt defenses (
prompts/classify.md) — explicit instructions telling the AI to treat all article content as data, never as instructions. - Output validation — JSON extraction ignores non-JSON output from the classifier.
- Input sanitization — newlines and control characters are stripped from all fields before prompt interpolation.
- Path traversal guards — date fields used in filenames are validated against strict format patterns.
- Least-privilege credentials — the Copilot PAT is scoped to
Copilot Requests: Readonly; the Anthropic API key is used solely for classification requests.
Caution
These defenses reduce risk but do not guarantee complete protection. Prompt injection is an open research problem with no known universal solution. By using this project, you acknowledge that:
- No heuristic scanner can catch every possible injection technique. Adversaries may find bypasses.
- AI models can behave unpredictably when processing adversarial input regardless of system prompt hardening.
- The maintainers of this project provide these security measures on a best-effort basis and accept no liability for any damage, data exposure, credential leakage, or other harm arising from the use of this software.
- You are responsible for securing your own secrets, tokens, and infrastructure.
Use at your own risk. Review the code, scope your credentials tightly, rotate secrets regularly, and monitor your pipeline runs.
Built and maintained by Zeyad AbuLaban (@zAbuQasem · LinkedIn).
If you fork or adapt this project, a link back is appreciated but not required.