type: decision
status: active
timestamp: 2026-06-24
tags: [decision, policy, mirror, private, secrets, security]

Private repos are excluded from the 9-host mirror cron

Mirror cron excludes private repos via isPrivate + name list

Private repos excluded from mirror cron

Decision

The 9-host mirror cron in .github/workflows/mirror-all.yml MUST NOT push private repos to public mirror hosts. Two filters in series:

  1. gh list isPrivate filter — the gh repo list calls in the discover step filter by isPrivate == false. Public repos only.
  2. Explicit name EXCLUDE list — even if a repo is mis-flagged as public, its name in this hardcoded list drops it. Defense in depth.

The current exclude list (in mirror-all.yml):

["secrets", "Recovery-codes", "recovery-codes", "envpact-secrets"]

What’s covered by this exclusion

RepoOwnerWhy excluded
chirag127/secretschirag127Brand-family secrets store (env files, recovery codes, backups). Private.
chirag127/secretschirag127Personal secrets store. Private.
chirag127/Recovery-codeschirag127Personal 2FA codes. Private + air-gapped from secrets.
chirag127/envpact-secretschirag127envpact per-project vault. Private.

Adding a new private repo to the family

Order matters:

  1. Create the repo as private on GitHub.
  2. Verify the discover step’s isPrivate == false filter catches it (it should — automatic).
  3. Add the repo’s NAME to the EXCLUDE array in mirror-all.yml even though step 2 already handles it. Belt-and-suspenders.
  4. THEN add as a submodule to the umbrella if desired.

Reversing step 3 + step 4 is the most likely way to leak. Always exclude FIRST, submodule SECOND.

Why filter + exclude both

Single-layer filtering breaks if:

The name-list catches all three. Cost of maintaining two filters: 0 (just add the name when creating). Cost of a leak: catastrophic.

What’s NOT in scope of this rule

Cross-refs


Edit on GitHub · Back to index