Back to skill

Security audit

Phy Pre Commit Gen

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent pre-commit configuration generator with normal repo-read and config-write behavior, though users should review generated hooks and avoid broad output paths.

Install only if you want an agent-assisted pre-commit config generator. Prefer --dry-run first, keep the default .pre-commit-config.yaml output path, use --overwrite only after reviewing the current file, and review generated hook repos and autoupdate diffs before running hooks on all files or in CI.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pre_commit_gen.py:532
Finding

Unrestricted Output Path Allows Writes Outside the Target Project

Content
View full analysis

Vulnerability Details

File Location: scripts/pre_commit_gen.py, lines 532-539; related argument definition at lines 486-487
Vulnerability Type: Path traversal and arbitrary file write
Risk Level: Medium

Vulnerable Code:

python
ap.add_argument("--output", "-o", default=".pre-commit-config.yaml",
                help="Output file (default: .pre-commit-config.yaml)")
python
out_path = root / args.output
if out_path.exists() and not args.overwrite:
    print(f"\n⚠️  {out_path} already exists.")
    print("   Use --overwrite to replace, or --audit to check the existing file.")
    print("   Use --dry-run to preview the generated config.")
    sys.exit(0)
out_path.write_text(yaml_output + "\n", encoding="utf-8")

Technical Analysis

The user-controlled --output value is joined to the project root without validating that the resulting path remains within that root. Python's pathlib permits both relevant escape mechanisms:

  • If args.output is absolute, root / args.output resolves to the absolute path and effectively discards root.
  • If it contains parent-directory components such as ../, the resulting path can reference a location outside the target project.

The destination is not resolved and checked against root before write_text() is called. Consequently, the script can create a new file outside the project. If --overwrite is also supplied, it can replace an existing file wherever the invoking account has write permission.

Attack Path

  1. An attacker influences the arguments supplied by an Agent, automation process, or user invoking the skill.
  2. The attacker supplies a traversal or absolute output path, such as:
    bash
    python3 scripts/pre_commit_gen.py /project \
      --output ../../writable-target.yaml \
      --overwrite
    
  3. The script constructs out_path without containment validation.
  4. The generated YAML is written ...[truncated 1174 chars]
Remediation
View remediation

Remediation Suggestions

Resolve and validate the output path before writing:

python
root = Path(args.target).resolve()

requested = Path(args.output)
if requested.is_absolute():
    print("Error: --output must be relative to the project root", file=sys.stderr)
    sys.exit(2)

out_path = (root / requested).resolve()
try:
    out_path.relative_to(root)
except ValueError:
    print("Error: --output must remain inside the project root", file=sys.stderr)
    sys.exit(2)

Additional hardening should include:

  1. Reject absolute output paths and paths that resolve outside root.
  2. Use exclusive creation, such as mode x, when overwrite was not explicitly requested.
  3. Verify that the destination's parent directories do not traverse symlinks outside the project if the threat model includes attacker-controlled repository contents.
  4. For overwrite operations, verify the final resolved path again immediately before writing.
  5. Consider restricting output to the exact filename .pre-commit-config.yaml unless custom destinations are required.

T08 · Insecure Dependencies

Note
Location
SKILL.md:46
Finding

Unpinned Installation and Automatic Hook Updates Weaken Supply-Chain Controls

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 46-49 and 238-244
Vulnerability Type: Unsafe dependency installation and automatic third-party revision updates
Risk Level: Low

Vulnerable Documentation:

bash
pip install pre-commit
pre-commit install          # activate for this repo
pre-commit autoupdate       # update all hook revs to latest
pre-commit run --all-files  # run on existing code
bash
pre-commit autoupdate
git add .pre-commit-config.yaml
git commit -m "chore: update pre-commit hook revisions"

Technical Analysis

The documentation instructs users to install pre-commit without a version constraint and then run pre-commit autoupdate. The unpinned pip install selects whichever release the package index currently serves rather than a reviewed version.

The generated configuration initially contains explicit hook revisions, but pre-commit autoupdate replaces those revisions with newer upstream versions. Immediately following this operation with pre-commit run --all-files causes newly selected third-party hook code to be downloaded and executed in the developer environment without an intervening review step.

A tag-based revision is also weaker than an immutable commit hash when an upstream repository permits tags to be moved. This is not evidence that any listed dependency is malicious; the risk arises from allowing externally controlled dependency versions to change after the skill itself has been reviewed.

Attack Path

  1. A package-index account or upstream hook repository is compromised, or an upstream project publishes a malicious or unexpectedly unsafe release.
  2. A user follows the documented command pip install pre-commit, receiving the currently available unreviewed version.
  3. The user runs pre-commit autoupdate, replacing reviewed revisions in the generated configuration with current upstream revisions.
  4. The user runs `pre-commit ...[truncated 993 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin pre-commit to a reviewed version:
    bash
    python3 -m pip install "pre-commit==REVIEWED_VERSION"
    
  2. Use a lock file with hashes or pip's hash-checking mode where practical.
  3. Do not make pre-commit autoupdate a mandatory step before initial execution.
  4. Run autoupdate in a dedicated maintenance workflow that produces a reviewed pull request.
  5. Review revision changes and upstream release notes before executing updated hooks.
  6. Where supported, pin hooks to immutable commit hashes rather than mutable tags.
  7. Execute third-party hooks in a restricted CI environment with minimal credentials, filesystem access, and network permissions.
  8. Separate dependency-update jobs from trusted release or deployment jobs.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (6)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 280)May include surrounding context.

md
| `phy-dep-upgrade` | Keeps dependencies up-to-date (pre-commit hooks check quality) |
| `phy-dockerfile-audit` | Hadolint is included as a pre-commit hook when Dockerfiles detected |
| `phy-lock-file-auditor` | Detects lock file issues (complementary to pre-commit integrity checks) |
| `phy-env-doctor` | Discovers .env refs — pairs with detect-secrets hook |

---

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill describes reading the project and writing or overwriting .pre-commit-config.yaml, but it does not declare any permissions or allowed-tools scope. That under-specification can cause agents or users to grant broader file access than necessary, increasing the blast radius if the skill is misused or combined with other instructions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill explicitly supports --overwrite and arbitrary --output paths, which enables persistent modification of repository files. Even though the intended use is legitimate config generation, these write capabilities can alter developer workflows and persist changes across sessions if invoked without tight path restrictions or confirmation.

Content

Scanner excerpt · SKILL.md (reported line 35)May include surrounding context.

md
# Audit an existing .pre-commit-config.yaml
python3 ~/.claude/skills/phy-pre-commit-gen/scripts/pre_commit_gen.py . --audit

# Overwrite an existing config
python3 ~/.claude/skills/phy-pre-commit-gen/scripts/pre_commit_gen.py . --overwrite

# Write to a specific path

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The module docstring says the tool has 'Zero external dependencies — pure Python stdlib only,' which describes the implementation but reads as a broader safety/scope claim. In practice, the generated config references many external GitHub hook repos, and the CLI instructs users to run pip install pre-commit and pre-commit autoupdate, while Rust/Terraform notes require local tools; this creates a meaningful documentation-to-behavior mismatch.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest frames the skill as a pure-Python analyzer/generator with zero external dependencies, but the generated output includes Rust hooks using repo: local, language: system, and shell-style entries like cargo fmt -- and cargo clippy -- -D warnings. While the script itself does not execute them, it is adding system-command-based capabilities into the produced pre-commit configuration, which is not explicitly justified in the manifest's stated scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code performs a filesystem write operation via write_text, which can modify repository configuration. While the script documents generation behavior and warns when the target file already exists, it does not ask for explicit user confirmation immediately before writing the file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.