fix(redfix): B-redfix-8 exposure UNDERSTATED — password is served by TWO published commits (2ad38f5 + e64d8e7), not one; oauth2 token is NOT in git history (0/3099 blobs)
Closes the gap in Adversary wake #57's break-it probe, which covered dashboard/reports/Drone logs but not the public git mirror -- the surface B-redfix-8 is about. - password sha16 3fcea78925015fc9 -> 2 blobs, 2 commits, both ancestors of origin/main. Scrubbing2ad38f5alone would leavee64d8e7serving the live credential. STATUS corrected. - oauth2 token sha16 9c44a1aea2ecb389 -> 0/3099 blobs. Filesystem-only exposure. - Probe hygiene: awk is absent here; awk-based blob lists give a vacuous 0. Positive control (password must return 2) is now mandatory and documented. Operator-scope, no gate impact, no VETO; DONE stands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018XE43k4DaeMXHMK51wBUu2
This commit is contained in:
@ -62,21 +62,56 @@ re-checked first-hand.
|
||||
Phase DoD is met, but **one HIGH item is open and only an operator can close it.** It does not block `##
|
||||
DONE` (no DoD item depends on it) and is recorded in full in BACKLOG-redfix.md.
|
||||
|
||||
**WHAT.** The live Gitea bot password (`GITEA_PASSWORD` in `/srv/cc-ci/.testenv`) was committed in
|
||||
`14c7dee` (`machine-docs/BACKLOG-redfix.md`), pushed to `origin/main`, and is served **in cleartext to the
|
||||
**WHAT.** The live Gitea bot password (`GITEA_PASSWORD` in `/srv/cc-ci/.testenv`) was committed to
|
||||
`machine-docs/BACKLOG-redfix.md`, pushed to `origin/main`, and is served **in cleartext to the
|
||||
unauthenticated public internet** by the public mirror. It is push-capable to `recipe-maintainers/*`. HEAD
|
||||
and the redaction commit `e99e2b3` are clean; only the historical commit `14c7dee` serves it. Redaction
|
||||
cannot unpublish it — the value is permanent in history and in every clone.
|
||||
and the redaction commit `e99e2b3` are clean. Redaction cannot unpublish it — the value is permanent in
|
||||
history and in every clone.
|
||||
|
||||
**CORRECTED (wake #58, 2026-07-09):** an earlier version of this entry said "**only** the historical commit
|
||||
`14c7dee` serves it." That **understated the exposure**. An exhaustive scan of all **3099** blobs in the
|
||||
object db (`git cat-file --batch-all-objects`, literal-value match) finds the password in **two distinct
|
||||
blobs**, carried by **two published commits** — both ancestors of `origin/main`, so both are mirror-served:
|
||||
|
||||
| commit | blob | `machine-docs/BACKLOG-redfix.md` size |
|
||||
|---|---|---|
|
||||
| `14c7dee` | `fd21fcb8ac02bff9917531c8175a29e450c41b19` | 33408 |
|
||||
| `223cc16` | `bcc31b55860f782056ba3ccdf13165191bd329b5` | 34353 |
|
||||
|
||||
Neither blob is reachable from HEAD. Scrubbing only `14c7dee` would leave `223cc16` serving the credential.
|
||||
|
||||
**WHERE.** `git.autonomic.zone/recipe-maintainers/cc-ci` →
|
||||
`/raw/commit/14c7dee/machine-docs/BACKLOG-redfix.md`
|
||||
`/raw/commit/14c7dee/machine-docs/BACKLOG-redfix.md` **and**
|
||||
`/raw/commit/223cc16/machine-docs/BACKLOG-redfix.md`
|
||||
|
||||
**HOW to confirm exposure** (unauthenticated fetch; a raw blob at a fixed sha is immutable, so served size
|
||||
must equal object size):
|
||||
|
||||
git cat-file -s 14c7dee:machine-docs/BACKLOG-redfix.md # → 33408
|
||||
git cat-file -s 223cc16:machine-docs/BACKLOG-redfix.md # → 34353
|
||||
|
||||
An unauthenticated fetch of the raw URL returning **HTTP 200 / 33408 bytes** is the leak, not an error page.
|
||||
An unauthenticated fetch of **either** raw URL returning **HTTP 200** at the matching byte count is the
|
||||
leak, not an error page.
|
||||
|
||||
**Exhaustive-scan reproduction** (names/counts only; never prints the value). The `awk`-free form matters —
|
||||
`awk` is absent on the orchestrator and an `awk`-based blob list yields an **empty** list, i.e. a vacuous
|
||||
`0 hits`:
|
||||
|
||||
git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)' \
|
||||
| grep '^blob ' | cut -d' ' -f2 > /tmp/blobs # → 3099 lines; assert >100 before trusting
|
||||
# then literal-match each blob against a chmod-600 sentinel; positive control MUST return 2
|
||||
|
||||
**Positive control is mandatory.** Any scan of this repo that reports **0** password-bearing blobs is a
|
||||
**broken probe**, not a clean repo — the correct answer is **2**.
|
||||
|
||||
**The `oauth2` token (the second exposed credential) does NOT appear in git history.** Same exhaustive scan,
|
||||
same run, literal match against the live token (`sha256[:16]=9c44a1aea2ecb389`, extracted root-only to a
|
||||
`chmod 600` file, then `shred`-removed): **0 of 3099 blobs.** The 271 history blobs matching the string
|
||||
`oauth2:` are `scripts/recipe-mirror-sync.sh:39`'s `https://oauth2:${TOKEN}@…` **variable interpolation**
|
||||
plus machine-docs **prose citing the sha16 sentinel** — no literal value. So the token's exposure is
|
||||
**filesystem-only** (A-redfix-1: world-readable `.git/config` copies); it is **not** on the public mirror.
|
||||
The password's exposure is **both** filesystem **and** public mirror. The two credentials differ in blast
|
||||
radius; the operator remedy must not treat them as symmetric.
|
||||
|
||||
**HOW to confirm it is still the live credential** (commits to the value without republishing it).
|
||||
Run this **on the orchestrator** — `/srv/cc-ci/.testenv` lives there, **not** on `cc-ci`:
|
||||
|
||||
Reference in New Issue
Block a user