Found in the adversarial review of #120.
revision() returns an enclosing repository's HEAD for a checkout that is not a git repo but sits inside one
Where: scripts/fleet/roots.py:104
The docstring promises None outside git. But git -C root rev-parse HEAD walks up to any parent repository. A Mech directory that is a plain copy (for example a git archive export) placed under another work tree is recorded with the parent's SHA, and the parent's status decides +dirty. If the parent has the files committed, the result is a clean, unrelated 40-hex SHA that passes the regex test, and it also passes the audit test when the audit is derived from the stats (see the previous finding).
Failure scenario. An operator exports the Mechs with git archive into a snapshot directory inside some other git work tree and sets MECHS_ROOT there. Every Mech gets the outer repo's HEAD as its source_revision.
Evidence. Scratch probe: an outer repo at /private/tmp/claude-501/review-pr120/outer with a plain copy of CommunityMech's kb/communities under mechs/. The probe printed CommunityMech 422 6f3d95594a27f364bf31cd31da38cef488467076+dirty, which is the outer repo's HEAD. The same copy outside any repo printed CommunityMech 422 None.
Verifier (confirmed, low). The finding reproduces. roots.revision() (scripts/fleet/roots.py:89-107, rev-parse at about line 104) runs git -C root rev-parse HEAD, and git walks up to the nearest enclosing repository. So a Mech directory that is not a repo itself but sits inside another work tree gets that outer repo's HEAD. The outer repo's status also decides whether +dirty is added. The docstring says it returns "None outside git", and here it does not. When the outer tree is fully committed, the result is a clean, unrelated 40-hex SHA. It passes the provenance regex test, and it also passes the audit-equality test because the skill tells the operator to copy the audit SHAs from mech_stats.json.
Severity stays low. The defect is latent. The real MECHS_ROOT is not inside a repo, and every real Mech is its own git toplevel. The skill's documented snapshot uses one git clone per Mech, in a scratchpad that is not a repo. Its step-3 free check that revision equals the pin would also reject an outer-repo SHA. Triggering the bug takes an undocumented layout (plain exports placed inside another work tree) plus skipping step 3. If that happens, the page would publish wrong provenance, not wrong counts. The suggested fix is sound and cheap: return None unless rev-parse --show-toplevel resolves to realpath(root).
Suggested fix. Check that git -C root rev-parse --show-toplevel equals os.path.realpath(root) before trusting HEAD, and return None otherwise.
Found in the adversarial review of #120.
revision() returns an enclosing repository's HEAD for a checkout that is not a git repo but sits inside one
Where:
scripts/fleet/roots.py:104The docstring promises None outside git. But
git -C root rev-parse HEADwalks up to any parent repository. A Mech directory that is a plain copy (for example agit archiveexport) placed under another work tree is recorded with the parent's SHA, and the parent's status decides +dirty. If the parent has the files committed, the result is a clean, unrelated 40-hex SHA that passes the regex test, and it also passes the audit test when the audit is derived from the stats (see the previous finding).Failure scenario. An operator exports the Mechs with
git archiveinto a snapshot directory inside some other git work tree and sets MECHS_ROOT there. Every Mech gets the outer repo's HEAD as its source_revision.Evidence. Scratch probe: an outer repo at /private/tmp/claude-501/review-pr120/outer with a plain copy of CommunityMech's kb/communities under mechs/. The probe printed
CommunityMech 422 6f3d95594a27f364bf31cd31da38cef488467076+dirty, which is the outer repo's HEAD. The same copy outside any repo printedCommunityMech 422 None.Verifier (confirmed, low). The finding reproduces. roots.revision() (scripts/fleet/roots.py:89-107, rev-parse at about line 104) runs
git -C root rev-parse HEAD, and git walks up to the nearest enclosing repository. So a Mech directory that is not a repo itself but sits inside another work tree gets that outer repo's HEAD. The outer repo's status also decides whether +dirty is added. The docstring says it returns "None outside git", and here it does not. When the outer tree is fully committed, the result is a clean, unrelated 40-hex SHA. It passes the provenance regex test, and it also passes the audit-equality test because the skill tells the operator to copy the audit SHAs from mech_stats.json.Severity stays low. The defect is latent. The real MECHS_ROOT is not inside a repo, and every real Mech is its own git toplevel. The skill's documented snapshot uses one git clone per Mech, in a scratchpad that is not a repo. Its step-3 free check that revision equals the pin would also reject an outer-repo SHA. Triggering the bug takes an undocumented layout (plain exports placed inside another work tree) plus skipping step 3. If that happens, the page would publish wrong provenance, not wrong counts. The suggested fix is sound and cheap: return None unless
rev-parse --show-toplevelresolves to realpath(root).Suggested fix. Check that
git -C root rev-parse --show-toplevelequals os.path.realpath(root) before trusting HEAD, and return None otherwise.