Skip to content

fix(source-control): keep a sibling file from shadowing a standard-library module in the merge gate's Python #10788

Closed

Description

@kyle-sexton

Problem

An independent security review of #10737 reported this scenario. The merge gate's Python runs from plugins/source-control/skills/babysit-prs/scripts/, and Python puts the script's own directory first on sys.path. So a file in that directory named after a standard-library module (for example json.py) would be imported in place of the standard-library module.

Running the gate Python with -I or -P would block that, but it would also stop the gate's sibling imports (babysit_util, babysit_gh and the rest), which rely on the script directory being on the path. This predates #10737 and is not fixed there.

Acceptance criteria

  • No file in the gate scripts' directory can shadow a standard-library module that the gate imports, and the gate's sibling imports still resolve.
  • A test fails if such a file is added. For example, it could list the directory against sys.stdlib_module_names.

Safety constraints

  • Do not drop the sibling imports the gate relies on.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  2. github-actions commented on Oct 28, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Small
    Complexity: Low
    Uncertainty: Known
    Flags: none
    Blocked by: none

    Understood: a file in the babysit-prs scripts directory named after a standard-library module (such as json.py) could shadow that module, because the script directory comes first on sys.path. Running Python with -I or -P would break the sibling imports, so the request is to add a test that fails when any entry in that directory shares a name with a stdlib module. Gate invocation and imports stay as they are. The refinement comment already lists the acceptance criteria, and nothing further is needed from you. No duplicates found.

    Automated triage, applied by the lanes App.

  3. added
    area: securitySecurity-relevant: vulnerability, hardening, or disclosure follow-up.
    priority: mediumReal value, no hard deadline; normal backlog flow.
    on Oct 28, 2026
  4. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 28, 2026
  5. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: no trusted-human acceptance criteria: a listed human must put the confirmed - [ ] criteria in the body or post them as their own comment, or, on an issue a listed human filed, intake's newest refinement comment must hold them unedited. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  6. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: the issue is at status: ready.

  7. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    and removed
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 28, 2026
  8. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.

    Intended outcome: Add a test that fails when any module or package in the babysit-prs scripts directory shares a name with a standard-library module, leaving the gate's sibling imports and invocation unchanged.

    Acceptance criteria

    • A new test under plugins/source-control/skills/babysit-prs/scripts/tests/ lists the immediate entries of the scripts directory (not tests/) and passes on the current tree.
    • The test takes each *.py file stem and each subdirectory name, and asserts none is in sys.stdlib_module_names.
    • The test fails with a message naming the offending entry when a stdlib-named file such as json.py is added to the scripts directory, shown by a check on a temp copy or temp directory rather than by editing the real directory.
    • The test also fails for a subdirectory or package named like a stdlib module such as json/ or logging/.
    • No gate script is changed to run Python with -I or -P, and babysit-python.sh still execs py -3, python3 or python with the script path unchanged.
    • The sibling imports in babysit_merge.py (babysit_util, babysit_gh, babysit_state and the rest) still resolve, and the existing babysit-prs test suite still passes.
    • The test file name is not itself a stdlib module name, and the test runs under the repo's existing babysit-prs Python test command with no new dependency.

    Sources read

    • plugins/source-control/skills/babysit-prs/scripts/babysit-python.sh:9-26: probes py -3, python3, python and execs it with the given arguments, with no -I or -P flag
    • plugins/source-control/skills/babysit-prs/scripts/babysit_merge.py:140-212: imports stdlib modules (json, os, re, pathlib and others) and then sibling modules (babysit_util, babysit_gh and others) that rely on the script directory being on sys.path
    • plugins/source-control/skills/babysit-prs/scripts/: the directory listing has no file named after a stdlib module today, and no existing test references sys.stdlib_module_names (grep found none in plugins/source-control)
    • refine-data/context.json: no candidate is a duplicate or a fix; none of the candidates concern stdlib shadowing

    Automated refinement by the lanes App. Intake triages the issue again with it.

  9. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    admission-deferredAdmitted but waiting for WIP room; the hourly work-unblock sweep labels it agent-ready.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    admission-deferredAdmitted but waiting for WIP room; the hourly work-unblock sweep labels it agent-ready.
    on Oct 28, 2026
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

    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.area: securitySecurity-relevant: vulnerability, hardening, or disclosure follow-up.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions