Skip to content

templates/assembly-root/scripts/validate-pins.py: a .github/workflows/ directory that this user cannot list or search ends the run in a PermissionError traceback, exit 1, where a workflow file it cannot open is a workflow-unreadable refusal, exit 2 #434

Closed

Description

@brettheap

(lane openRepoShape-2, 2026-10-12T17:33Z)

Found while finishing PR #359's branch (the fix for #359, a workflow FILE that is not UTF-8 or that this user cannot open). Not claimed.

What is wrong. _workflow_refs (templates/assembly-root/scripts/validate-pins.py:170-196) still lets a PermissionError escape when the .github/workflows/ DIRECTORY, not a file in it, cannot be opened: workflows.is_dir() (:184), workflows.iterdir() (:186) and the is_file() stat on each child (:187) are unguarded. main() handles Refusal only, so the run ends in a traceback, exit 1, which is the code this validator uses for a finding. #359 refuses a FILE this user cannot open (workflow-unreadable); #383 and PR #403 do both the file and the directory for bump-leg.py.

Probed on the #359 branch's template (no git, no network, no gh), by calling _workflow_refs on a root holding one UTF-8 legs.yml:

mode result
.github/workflows/ 000 (cannot be listed) PermissionError escapes
.github/workflows/ r-- (listable, not searchable: is_file() stats each child) PermissionError escapes
.github/ r-- (workflows/ cannot be statted) PermissionError escapes
.github/workflows/ 755 (control) returns

The probe is impl359-validate-pins-workflow-utf8/tools/probe-unlistable-directory.py in the lane's attachments, with its log. The is_file() calls on the pin and the manifest (:210, :366, :497, :677) have the same shape and were not probed.

What it should do. Refuse by name, exit 2, in the words #359's workflow-unreadable uses (.github/workflows: cannot be listed (Permission denied)), with a remediation that says to restore read and search access, then run the same command again. It is a pinned template copy, so the change moves scripts/validate-pins.py's digest for every project already cut, as #359's does.

How to test. Beside tests/test_validate_pins_unreadable_workflow.py, a scaffolded root and a chmod on the directory, restored in a finally; skip on Windows and when os.geteuid() == 0 (tests/test_family_add_refusals.py:677). Each row above exits 2 with the refusal id and the path, and no Traceback.

Lane: openreposhape-2 (openRepoShape-2)

Activity

  1. added this to the v1.1.0 milestone on Oct 15, 2026
  2. brettheap commented on Oct 15, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-4, session 11c6c0ef-495a-4a05-94cf-811b7b0a1012@Eagle, 2026-10-15T23:03:44Z, for #434

    Logged in lanes/log/openRepoShape-4.md at ac2f51a79fc09f97443d587984735a2bee064c89.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#434:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#434"`, kept where the row or its body names `#434`:
       none
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `434` as a whole token:
       none
    
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

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions