Back to skill

Security audit

ML Run Provenance

Security checks for vulnerabilities and agentic risk

Overview

The skill itself is a scoped local ML provenance guide, but its documented install path uses an unpinned npx command that can execute mutable third-party code.

Use the clone or a commit-pinned/publisher-verified install route instead of the unpinned npx command when possible, and avoid running installers with elevated privileges. Treat run metadata as potentially sensitive and require explicit approval before any tracker upload, backfill, deletion, or paid training run.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
README.md:22
Finding

Unpinned Third-Party Package Is Executed During Installation

Content
View full analysis

Vulnerability Details

File Location: README.md, line 22
Vulnerability Type: Unpinned executable dependency and supply-chain risk
Risk Level: Medium

Vulnerable Code

sh
npx skills add AntreasAntoniou/ml-run-provenance --skill ml-run-provenance

Technical Analysis

The documented installation command invokes the third-party skills npm package through npx without specifying an exact package version or verifying an integrity hash. Depending on the local npm configuration and cache state, npx can retrieve and execute the currently resolved package release.

Consequently, the code executed during installation is not limited to the contents of this audited repository and can change after this repository has been reviewed. The repository does not contain, pin, or otherwise constrain the implementation of the skills executable.

This creates a supply-chain exposure: compromise of the npm package, its publisher account, its dependency graph, or the package resolution source could cause users following the documented command to execute attacker-controlled code.

Attack Path

  1. An attacker compromises the resolved skills npm package, its publisher account, or one of its install-time dependencies.
  2. The attacker publishes a malicious release that remains compatible with the documented command.
  3. A user follows the installation instructions and runs the unpinned npx skills add ... command.
  4. npx resolves and downloads the malicious package version.
  5. The downloaded package executes with the privileges and environment of the installing user.
  6. The malicious package could access files and credentials available to that user, modify the installed Skill, or install additional attacker-controlled content.

Impact Assessment

Successful exploitation could provide arbitrary code execution with the permissions of the user performing the installation. The accessible scope may include th ...[truncated 484 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the installer to an exact reviewed version, for example by using an explicit package-name@x.y.z reference supported by npx.
  2. Document the expected npm publisher, registry, package identity, and reviewed version so users can verify package provenance.
  3. Use npm lockfile and integrity metadata where the installation workflow supports them.
  4. Prefer a non-executing installation path based on a reviewed, commit-pinned Git checkout or signed release archive.
  5. Provide checksum or signature verification instructions for release artifacts.
  6. Advise users not to run the installer with administrator privileges and to execute it in a restricted environment where practical.
  7. Periodically review the pinned installer and its transitive dependencies before updating the documented version.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Context Leakage

High
Category
Data Exfiltration
Confidence
75% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

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

md
# ML run provenance

Treat provenance as a trainer output alongside checkpoints and metrics. A cryptic run directory or dashboard title does not preserve campaign intent. Capture context at run birth and distinguish recorded facts from reconstructed metadata.

This package provides a protocol and a local JSON validator, **not** a trainer integration, tracker adapter, classifier, backfill service, or guarantee of reproducibility. Those project-specific pieces must be implemented and tested where needed. No other private repository or skill is required.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill references executable behavior via a local validator command and discusses project-local implementation pieces, yet it declares no explicit tool scope or permissions boundary. In an agent environment, missing tool restrictions can let a model assume broader file or shell access than intended, increasing the chance of unauthorized local reads, writes, or command execution during use.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_metadata.py (reported line 73)May include surrounding context.

python
path = pathlib.Path(temporary) / "record.json"
            content = json.dumps(synthetic_record())
            path.write_text(content)
            result = subprocess.run([sys.executable, str(SCRIPT), str(path), "--strict"], capture_output=True, text=True)
            self.assertEqual(result.returncode, 0, result.stderr)
            self.assertEqual(path.read_text(), content)
            path.write_text('{"run_id":"PRIVATE_TEST_VALUE", "run_id":"duplicate"}')

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_metadata.py (reported line 77)May include surrounding context.

python
self.assertEqual(result.returncode, 0, result.stderr)
            self.assertEqual(path.read_text(), content)
            path.write_text('{"run_id":"PRIVATE_TEST_VALUE", "run_id":"duplicate"}')
            result = subprocess.run([sys.executable, str(SCRIPT), str(path)], capture_output=True, text=True)
            self.assertEqual(result.returncode, 2)
            self.assertNotIn("PRIVATE_TEST_VALUE", result.stderr)
            path.write_text("{}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_metadata.py (reported line 81)May include surrounding context.

python
self.assertEqual(result.returncode, 0, result.stderr)
            self.assertEqual(path.read_text(), content)
            path.write_text('{"run_id":"PRIVATE_TEST_VALUE", "run_id":"duplicate"}')
            result = subprocess.run([sys.executable, str(SCRIPT), str(path)], capture_output=True, text=True)
            self.assertEqual(result.returncode, 2)
            self.assertNotIn("PRIVATE_TEST_VALUE", result.stderr)
            path.write_text("{}")

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_metadata.py:13