Skip to content

roots.revision() returns an enclosing repository's HEAD for a directory that is not itself a repository #124

Description

@realmarcin

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions