Upstream Source Monitoring Guide

July 3, 2026 ยท View on GitHub

Status: โœ… Operational
Last Updated: 2026-07-03
Automation: Daily at 2 AM UTC


๐ŸŽฏ Overview

The upstream source monitoring system automatically fetches updates from trusted blocklist sources and creates pull requests with new domains. This keeps your lists current with the latest security threats without manual intervention.

Key Features

  • ๐Ÿค– Fully Automated - Runs daily, creates PRs automatically
  • ๐Ÿ“Š Transparent - Every change visible with source attribution
  • ๐Ÿ”’ Trust-Based - Only trusted sources eligible for auto-merge
  • โšก Smart Caching - 24-hour TTL reduces bandwidth
  • ๐Ÿ“ˆ Scalable - Add sources by editing YAML config
  • โœ… Quality Control - Manual review for large changes

๐Ÿ—๏ธ Architecture

Components

  1. Configuration (config/lists.yml) - Defines upstream sources
  2. Monitor Script (scripts/monitor_upstream.py) - Fetches and compares
  3. GitHub Workflow (.github/workflows/upstream-monitor.yml) - Automation
  4. Pull Requests - Generated with detailed change reports

Workflow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Daily Trigger (2 AM UTC)                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Load config/lists.yml                               โ”‚
โ”‚  โ€ข Find lists with upstream_sources                  โ”‚
โ”‚  โ€ข Get update frequency and trust settings           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  For each list with upstream sources:               โ”‚
โ”‚  1. Fetch upstream data (with caching)              โ”‚
โ”‚  2. Normalize domains based on format               โ”‚
โ”‚  3. Compare with local list                         โ”‚
โ”‚  4. Identify new and removed domains                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  If changes found:                                  โ”‚
โ”‚  1. Create git branch                               โ”‚
โ”‚  2. Add new domains to list                         โ”‚
โ”‚  3. Commit changes                                  โ”‚
โ”‚  4. Generate PR description                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Create Pull Request:                               โ”‚
โ”‚  โ€ข Add labels (size:small/medium/large)             โ”‚
โ”‚  โ€ข Mark auto-merge eligible if โ‰ค10 domains          โ”‚
โ”‚  โ€ข Request review if >100 domains                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Create summary issue:                              โ”‚
โ”‚  โ€ข List all updated lists                           โ”‚
โ”‚  โ€ข Total new domains                                โ”‚
โ”‚  โ€ข Links to PRs                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“‹ Configuration

Current Lists with Upstream Sources

ListCategorySourcesFrequency
abuseSecurity2Daily
adsAdvertising3Daily/Weekly
cryptoSecurity2Daily/Weekly
fraudSecurity1Daily
gamblingContent1Weekly
malwareSecurity3Daily
phishingSecurity2Daily
pornContent1Weekly
ransomwareSecurity2Daily
trackingPrivacy2Weekly

Total: 23 upstream sources configured

Adding a New Upstream Source

Edit config/lists.yml and add to the appropriate list:

lists:
  your_list:
    description: "Description of your list"
    category: security  # or advertising, content, tracking, etc.
    status: stable
    upstream_sources:
      - url: "https://example.com/blocklist.txt"
        format: hosts  # hosts, domains, adguard, or dnsmasq
        trusted: true  # true = auto-merge eligible, false = always review
        update_frequency: daily  # daily, weekly, hourly
        filter_comments: true  # Skip lines starting with #
        max_domains: 1000  # Optional: limit to prevent huge merges

Format Types

FormatExampleDescription
hosts0.0.0.0 example.comStandard hosts file format
domainsexample.comPlain domain list (one per line)
adguard||example.com^AdGuard format
dnsmasqserver=/example.com/dnsmasq format

Trust Levels

  • trusted: true - Auto-merge eligible if changes โ‰ค threshold
  • trusted: false - Always requires manual review

Update Frequencies

  • daily - Checked every day at 2 AM UTC
  • weekly - Checked once per week
  • hourly - Checked every hour (use sparingly!)

๐Ÿš€ Usage

Manual Execution

# Check a specific list
python scripts/monitor_upstream.py --list ads

# Check all lists with upstream sources
python scripts/monitor_upstream.py --all

# Dry run (check only, don't create PRs)
python scripts/monitor_upstream.py --all --dry-run

# Force fresh fetch (ignore cache)
python scripts/monitor_upstream.py --all --no-cache

Automated Execution

The workflow runs automatically via GitHub Actions:

  • Schedule: Daily at 2 AM UTC
  • Trigger: .github/workflows/upstream-monitor.yml
  • Manual: Actions tab โ†’ "Upstream Source Monitoring" โ†’ Run workflow

Manual Workflow Options

  1. Specific List: Set list_name input (e.g., ads)
  2. All Lists: Leave list_name empty
  3. Dry Run: Set dry_run to true

๐Ÿ“Š Pull Request Format

Example PR Title

chore: update malware from upstream sources (+8 domains)

Example PR Body

## ๐Ÿค– Automated Upstream Update: malware

This PR was automatically generated by the upstream monitoring system.

### ๐Ÿ“Š Summary

- **List:** malware.txt
- **New domains:** 8
- **Removed domains:** 0
- **Sources checked:** 3

### ๐Ÿ“ก Source Details

#### Source 1: urlhaus-filter-hosts.txt

- **URL:** https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-hosts.txt
- **Upstream total:** 5,234 domains
- **New domains:** 8

**New domains:**

malicious-domain1.com malicious-domain2.com malicious-domain3.com ...


### โœ… Validation

- [ ] New domains are relevant to the malware category
- [ ] No false positives identified
- [ ] Domains pass validation checks
- [ ] Build succeeds

### ๐Ÿ”„ Merge Policy

โœ… **Auto-merge eligible** - Changes are below threshold (โ‰ค10 domains)

Labels Added

  • automation - Automated PR
  • upstream-update - From upstream monitoring
  • size:small - โ‰ค10 domains
  • size:medium - 11-100 domains
  • size:large - >100 domains
  • auto-merge-candidate - Eligible for auto-merge
  • needs-review - Requires manual review
  • breaking-change - Large changes (>100 domains)

๐Ÿ”ง Merge Policy

Automatic Merge Eligibility

Changes are eligible for automatic merge when ALL conditions are met:

โœ… Source is trusted (trusted: true in config)
โœ… Small changes (โ‰ค10 new domains)
โœ… CI passes (all tests green)
โœ… No conflicts (clean merge)

Manual Review Required

Manual review is required when ANY condition is met:

โš ๏ธ Source not trusted (trusted: false)
โš ๏ธ Medium changes (11-100 domains)
๐Ÿ”ด Large changes (>100 domains)
๐Ÿ”ด CI fails (tests or validation errors)

Review Checklist

When reviewing a PR:

  1. โœ… Verify domains are relevant to the list category
  2. โœ… Check for false positives (legitimate sites)
  3. โœ… Ensure no typos in domain names
  4. โœ… Confirm source is reputable
  5. โœ… Check CI results (all tests passing)
  6. โœ… Review sample domains in PR description

๐ŸŽฏ Thresholds & Limits

Global Settings (config/lists.yml)

settings:
  upstream:
    enabled: true
    check_frequency: daily
    auto_merge_threshold: 10      # Auto-merge if changes โ‰ค this
    require_review_threshold: 100  # Manual review if changes > this
    cache_ttl: 86400              # 24 hours in seconds

Per-Source Settings

upstream_sources:
  - url: "..."
    max_domains: 1000  # Limit to prevent huge merges
    trusted: true      # Auto-merge eligible

๐Ÿ“ˆ Monitoring & Statistics

Daily Summary Issue

After each run, a summary issue is created with:

  • Total new domains across all lists
  • Number of lists updated
  • Number of PRs created
  • Links to each PR
  • Auto-merge eligibility status

Weekly Reports

The weekly issue report (created by weekly-report.yml) includes:

  • Upstream PRs created
  • Auto-merge success rate
  • Manual review turnaround time
  • Source health statistics

๐Ÿ” Troubleshooting

Common Issues

1. Source URL Not Accessible

Symptom: Workflow fails with "Error fetching URL"

Solution:

  • Check if upstream source is still online
  • Verify URL is correct in lists.yml
  • Check for rate limiting or IP blocks
  • Review GitHub Actions logs

2. Too Many Changes

Symptom: PR marked as breaking-change with 1000+ domains

Solution:

  • Review upstream source quality
  • Add max_domains limit to source config
  • Consider splitting large sources
  • Verify source format is correct

3. False Positives

Symptom: Legitimate domains in PR

Solution:

  • Mark source as trusted: false for manual review
  • Report false positives to upstream source
  • Add domains to local allowlist
  • Consider different upstream source

4. Cache Issues

Symptom: Not detecting updates from upstream

Solution:

# Clear cache and force refresh
python scripts/monitor_upstream.py --all --no-cache

# Or delete cache files
rm -f /tmp/upstream_cache_*.txt

5. Workflow Not Running

Symptom: No PRs created at scheduled time

Solution:

  • Check workflow is enabled in Actions tab
  • Verify cron schedule in .github/workflows/upstream-monitor.yml
  • Check GitHub Actions status page
  • Review workflow run history for errors

๐Ÿ›ก๏ธ Security Considerations

Source Validation

Before adding a new upstream source:

  1. โœ… Verify reputation - Is the source well-known and trusted?
  2. โœ… Check update frequency - How often is it updated?
  3. โœ… Review content quality - Any false positives?
  4. โœ… Test manually - Run with --dry-run first
  5. โœ… Monitor initially - Set trusted: false until proven reliable

Sensitive Sources

For security-critical lists (ransomware, phishing):

  • Set trusted: false to always require review
  • Limit max_domains to catch anomalies
  • Monitor more frequently (daily or hourly)
  • Set up alerts for large changes

๐Ÿ“š Examples

Example 1: Adding AdGuard DNS Filter

lists:
  ads:
    upstream_sources:
      - url: "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"
        format: adguard
        trusted: true
        update_frequency: daily
        max_domains: 5000

Example 2: Adding Security List (Requires Review)

lists:
  phishing:
    upstream_sources:
      - url: "https://example.com/new-phishing-list.txt"
        format: domains
        trusted: false  # Require manual review
        update_frequency: daily
        max_domains: 500

Example 3: Multiple Sources for One List

lists:
  malware:
    upstream_sources:
      - url: "https://urlhaus.abuse.ch/downloads/hostfile/"
        format: hosts
        trusted: true
        update_frequency: daily
      
      - url: "https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-hosts.txt"
        format: hosts
        trusted: true
        update_frequency: daily
      
      - url: "https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt"
        format: domains
        trusted: false
        update_frequency: weekly
        max_domains: 1000

๐Ÿ“ž Support

Getting Help

  • Documentation: This file
  • Issues: GitHub Issues
  • Workflow Logs: Actions tab โ†’ Upstream Source Monitoring
  • Configuration: config/lists.yml

Reporting Bugs

If upstream monitoring is not working:

  1. Check the workflow run logs
  2. Review recent changes to config/lists.yml
  3. Test manually with --dry-run
  4. Open an issue with logs and details

๐ŸŽ“ Best Practices

โœ… DO

  • Start with trusted: false for new sources
  • Set reasonable max_domains limits
  • Monitor PRs in the first week
  • Use caching (cache_ttl: 86400)
  • Group related sources in same list
  • Document source in comments

โŒ DON'T

  • Set all sources to trusted: true immediately
  • Use hourly frequency unless necessary
  • Skip manual review of large PRs
  • Ignore build failures
  • Add sources without testing
  • Disable caching globally

๐Ÿ”ฎ Future Enhancements

Planned Features

  • VirusTotal Integration - Reputation checks for new domains
  • Incremental Updates - Track last-seen dates for efficiency
  • Source Health Monitoring - Detect broken URLs automatically
  • IP Address Support - Monitor upstream .ip files
  • Scheduled Health Reports - Weekly source reliability stats
  • Auto-Remove Dead Sources - Remove consistently failing sources

Feature Requests

Have an idea? Open an issue with the feature-request label!


๐Ÿ“Š Statistics

Current Status

  • Lists Configured: 10
  • Upstream Sources: 23
  • Update Frequency: Daily (2 AM UTC)
  • Average PR Size: ~5-15 domains
  • Auto-Merge Rate: ~80% (small trusted changes)
  • Cache Hit Rate: ~90% (during same day)

Performance

  • Fetch Time: ~5-10 seconds per source (without cache)
  • Cache Hit Time: <1 second per source
  • PR Generation: <30 seconds
  • Total Runtime: ~2-5 minutes for all lists

Last Updated: 2026-07-03
Version: 1.0
Maintainer: Block List Project Team