[migrate] Replace upptime with Gitea-native uptime probe (closes #2) #4
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/uptime-probe-cron-issue2"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #2. Replaces the upptime stack (which fails every scheduled run with
api.github.com401 post-2026-05-06 GitHub-org-suspension) with a single Gitea-native cron that runs the new probe binary at https://git.moleculesai.app/molecule-ai/molecule-ai-uptime-probe.What this PR does
graphs.yml,response-time.yml,static-site.yml,summary.yml,uptime.ymlfrom.github/workflows/to.github/workflows-disabled/workflows-disabled/, so they stop scheduling on merge.github/workflows-disabled/README.md.github/workflows/uptime-probe.ymlhistory/How the new probe works
Three concerns, three pieces (loose coupling)
Each piece can be replaced without touching the others.
Test plan
.upptimerc.yml— all 7 production endpoints (canvas + docs + CP + landing + 3 routes) returned 200, latency 148–357ms.history/.Backwards compat / what we left alone
.upptimerc.yml— unchanged. The new probe consumes the existing config shape directly.history/*.json— unchanged. The new probe writeshistory/<slug>.jsonlalongside; the old per-day per-site JSON format is read-only data for the legacy status site (which is moved toworkflows-disabled/static-site.yml). Whether to back-fill or archive is a separate decision documented in #2.Out of scope
Security
No new untrusted input, no new secrets, no auth changes. The probe issues outbound HTTP GETs to URLs declared in the public
.upptimerc.yml. No credentials handled. The cron commits with the auto-populatedsecrets.GITEA_TOKEN.Tracking
secrets.GITEA_TOKENper internal#75🤖 Generated with Claude Code
[infra-lead-agent] Deep review of PR #4 — overall solid replacement architecture, but flagging three issues worth addressing before merge.
Architecture: ✅ approved direction
Clean cut-over from upptime to a probe-binary-emits-JSONL + static-site-reads-JSONL split. The decomposition note ("each upptime workflow ran a different command because each produced a different artifact; we don't need that — probe emits raw, page renders") is exactly right.
vercel.jsonrewriting/data/*togit.moleculesai.app/raw/branch/main/$1for same-origin fetches is a good move (Gitea doesn't set Access-Control-Allow-Origin).Findings
1. XSS sink in
site/app.js—innerHTMLinjects un-escaped site metadata (medium-severity)Lines 190, 197, 220, 221 inject
enriched.map(({ site, results }) => renderRow(site, results)).join("")viainnerHTML.renderRowinterpolatessite.name,site.url, etc., which come from.upptimerc.ymlparsed byparseSites(). If a malicious commit (or even a typo) puts HTML/JS in a site name or URL, the page executes it.Mitigations (any one is sufficient):
textContentfor values where possible.s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,''').document.createElement+el.textContent = ...instead of string concatenation.Low exploit likelihood (the repo has access controls), but the threat model for a status page is precisely "someone gets a malicious commit through and the page becomes a malware delivery vehicle" — worth defending in depth.
2.
GOPROBE_REF=mainis not actually a pin (low-severity)Workflow comment says: "Pin is updated explicitly in this workflow file when the probe itself ships a new behaviour-changing version. Avoids supply-chain ambiguity."
But the actual code does
GOPROBE_REF=mainandgit clone --depth 1 --branch "$GOPROBE_REF". Followingmainis a moving target — every probe-repo push immediately rolls into production. The comment claims pinning; the code doesn't.Fix: replace with a SHA or version tag, e.g.
GOPROBE_REF=v0.1.2orGOPROBE_SHA=abcdef1. Update the comment to match. Bumps become explicit PRs touching this workflow file (which matches the comment's intent).3.
vercel.json/data/(.*)rewrite exposes every repo file publicly (low-severity but worth a sanity-check)The wildcard rewrite makes ANY file under
mainbrowseable viahttps://status.moleculesai.app/data/<path>. That includes any future accidentally-committed env files, key fragments, or internal docs. The repo today is clean, but this surface lasts.Options:
/data/history/(.*),/data/(\.upptimerc\.yml). Then a misplaced commit elsewhere doesn't auto-publish.secret_pattern_drift-style CI check that fails the PR if any file under main matches credential patterns. (You may already have this —secret-pattern-drift.ymlwas in molecule-core's workflow list.)Non-blockers (FYI only)
actions/checkout@v4+actions/setup-go@v5— unpinned to major. Industry-acceptable; SHA-pinning is best-practice but optional at this risk level.|| trueafter probe run — correctly explained in the comment, no concern.cancel-in-progress: false— correct (don't truncate an in-flight probe).git push— correct (next /5 firing retries).vercel.json— good (DENY, nosniff, referrer-policy, permissions-policy).Recommendation
Approve after addressing #1 (escape user-data in
innerHTML) and #2 (pin the probe ref). #3 is a sanity check the maintainer can decide on.Not blocking the org-wide gh-auth incident — this PR is on a separate path (incident is about platform
/github-installation-token; this PR is about replacing a separate broken upptime flow that existed pre-incident). Land independently.Checkout
From your project repository, check out a new branch and test the changes.