● Zion Boggan
repos/Cyclops V2/orchestrator/feed.py
zionboggan.com ↗
76 lines · python
History for this file →
1
"""
2
Cyclops v2 - fresh-target feed (anti "beaten to the punch").
3
 
4
Hunt code that is DAYS old, before anyone else has looked. Watches GitHub
5
releases/tags for a curated set of high-value repos per archetype and enqueues
6
freshly-released versions for analysis. New code = unexplored sinks = novel CVEs,
7
not sibling-CVE rediscovery.
8
 
9
No auth needed for public release feeds (unauthenticated GitHub API, low rate).
10
If GH_TOKEN is set it's used to raise the rate limit.
11
"""
12
import os, sys, json, time, urllib.request
13
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "memory"))
14
from memory import Memory
15
 
16
WATCH = {
17
    "ml-model-loaders": [
18
        "ggml-org/llama.cpp", "microsoft/onnxruntime", "huggingface/safetensors",
19
        "pytorch/pytorch", "comfyanonymous/ComfyUI", "gradio-app/gradio",
20
        "huggingface/transformers", "vllm-project/vllm",
21
    ],
22
    "ai-agent-mcp": [
23
        "open-webui/open-webui", "FlowiseAI/Flowise", "n8n-io/n8n",
24
        "langchain-ai/langchain", "run-llama/llama_index",
25
    ],
26
    "devops-infra": [
27
        "grafana/grafana", "go-gitea/gitea", "jenkinsci/jenkins",
28
        "argoproj/argo-cd", "minio/minio", "metabase/metabase",
29
    ],
30
    "memory-unsafe-parsers": [
31
        "DaveGamble/cJSON", "libarchive/libarchive", "madler/zlib",
32
        "nlohmann/json", "tafia/quick-xml",
33
    ],
34
}
35
 
36
API = "https://api.github.com/repos/{}/releases/latest"
37
 
38
def _get(url):
39
    req = urllib.request.Request(url, headers={"User-Agent": "cyclops-v2"})
40
    tok = os.environ.get("GH_TOKEN")
41
    if tok:
42
        req.add_header("Authorization", f"Bearer {tok}")
43
    with urllib.request.urlopen(req, timeout=20) as r:
44
        return json.loads(r.read().decode())
45
 
46
def poll(max_age_days=21):
47
    m = Memory()
48
    now = time.time()
49
    fresh = []
50
    for archetype, repos in WATCH.items():
51
        for repo in repos:
52
            try:
53
                rel = _get(API.format(repo))
54
            except Exception as e:
55
                print(f"[feed] {repo}: {e}")
56
                continue
57
            tag = rel.get("tag_name", "")
58
            pub = rel.get("published_at", "")
59
            if not pub:
60
                continue
61
            age = (now - time.mktime(time.strptime(pub, "%Y-%m-%dT%H:%M:%SZ"))) / 86400
62
            key = f"feed:seen:{repo}:{tag}"
63
            if m.r.sismember("cyclops:feed_seen", key):
64
                continue
65
            m.r.sadd("cyclops:feed_seen", key)
66
            if age <= max_age_days:
67
                job = {"repo": f"github.com/{repo}", "archetype": archetype,
68
                       "tag": tag, "released_at": pub, "age_days": round(age, 1)}
69
                m.enqueue("targets", job)
70
                fresh.append(job)
71
                print(f"[feed] FRESH {repo} {tag} ({age:.1f}d old) -> queued")
72
    print(f"[feed] {len(fresh)} fresh targets queued")
73
    return fresh
74
 
75
if __name__ == "__main__":
76
    poll(int(sys.argv[1]) if len(sys.argv) > 1 else 21)