Thanks to visit codestin.com
Credit goes to github.com

Skip to content

scripts/generate_catalog.py: non-deterministic demo_command from unsorted glob('*.py') #263

Description

@manuelcorpas

Symptom

Skill PRs that touch only their own folder still land with demo_command rewrites in skills/catalog.json for unrelated skills. Recently observed in:

The rewrites are not malicious — every target --demo file pre-exists on main. They are a side effect of regenerating the catalog on a different filesystem.

Root cause

scripts/generate_catalog.py:331:

scripts = [f for f in skill_dir.glob("*.py") if f.name != "__init__.py" and f.name != "api.py"]
if scripts:
    demo_command = f"python {scripts[0].relative_to(CLAWBIO_DIR)} --demo"

Path.glob() returns filesystem-order, not sorted-order. The outer loop on line 299 is sorted(SKILLS_DIR.iterdir()) (deterministic), but this inner glob is not. For any skill that:

  1. Has no entry in FOLDER_TO_ALIAS, so cli_alias is None
  2. Has ≥2 candidate .py files (most non-trivial skills)

…the scripts[0] pick will flip between contributors' machines, causing the catalog regen to silently rewrite demo_command for that skill.

skill_dir.rglob("*.py") on line 319 is also unsorted, but only feeds a boolean has_script so it's harmless.

Fix

One-line change:

scripts = [f for f in sorted(skill_dir.glob("*.py")) if f.name != "__init__.py" and f.name != "api.py"]

(Optional belt-and-braces: also sort skill_dir.rglob("*.py") on line 319.)

Impact

Once landed, future skill PRs stop carrying spurious catalog rewrites and reviewers can trust the catalog.json diff to reflect only the skill being added/changed.

Detection

pr-audit reports unrelated demo_command rewrites as a LOW-severity scope-creep finding. Surfaced by the 2026-05-23 batch audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions