Back to skill

Security audit

experiment-framework

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent ML experiment runner, but it has broad credential exposure and an unsafe results path that users should review before installing.

Install only in an isolated environment and run only trusted experiment specs and source commits. Avoid the optional unpinned npx installer, use narrowly scoped temporary tokens, review bundles before publishing, avoid --repo-dir publishing until results_prefix containment is fixed, and do not run untrusted experiment commands with credentials in your shell environment.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
src/axiotic_experiments/github_store.py:40
Finding

Unvalidated results prefix permits filesystem path traversal, deletion, and overwrite

Content
View full analysis
Path: assert_no_secret_material(bundle_dir) destination = self.repo_dir / self.results_prefix / run_id destination.mkdir(parents=True, exist_ok=True) for source in bundle_dir.iterdir(): target = destination / source.name if source.is_dir(): if target.exists(): shutil.rmtree(target) shutil.copytree(source, target) elif source.is_file(): shutil.copy2(source, target) return destination ``` ### Technical Analysis The specification parser accepts `[github].results_prefix` without rejecting absolute paths or `..` path components. Calling `strip("/")` removes leading and trailing separators but does not neutralize traversal sequences. `GitHubResultStore.stage()` joins this attacker-controlled value to `repo_dir` and then performs directory creation, recursive deletion, and file copying. A value such as `../../victim` can cause the normalized destination to escape the intended repository. The recursive `shutil.rmtree(target)` operation makes this more severe than a simple arbitrary write: an existing direc ...[truncated 968 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/axiotic_experiments/github_store.py:19
Finding

Secret scanning can be bypassed before files are uploaded to GitHub

Content
View full analysis
None: for path in directory.rglob("*"): if not path.is_file() or path.stat().st_size > 5_000_000: continue try: text = path.read_text(encoding="utf-8") except UnicodeDecodeError: continue if any(pattern.search(text) for pattern in _TOKEN_PATTERNS): raise GitHubStoreError(f"credential-like material detected in {path}") ``` ```python def upload_bundle(self, bundle_dir: Path, *, run_id: str) -> str: assert_no_secret_material(bundle_dir) files = sorted(path for path in bundle_dir.iterdir() if path.is_file()) if not files: raise GitHubStoreError(f"result bundle is empty: {bundle_dir}") commit = "" for path in files: commit = self.upload_file(path, run_id=run_id) return commit def upload_file(self, source: Path, *, run_id: str) -> str: path = f"{self.results_prefix}/{run_id}/{source.name}" existing = self._request_json("GET", path, missing_ok=True) payload: dict[str, Any] = { "message": f"[{run_id}] publish {source.name}", "content": base64.b64encode(source.read_bytes()).decode(), "branch": self.branch, } ``` ### Technical Analysis The scanner deliberately skips files larger than 5 MB and files that are not valid UTF-8. Those same files remain eligible for upload. Its pattern set also recognizes only a small number of credential formats and does not detect generic password assignments, W&B keys, private ...[truncated 1198 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/axiotic_experiments/backends.py:188
Finding

Experiment commands and SSH targets receive all configured service credentials

Content
View full analysis
tuple[str, ...]: if profile.transport == "runpod": return BASE_CREDENTIALS + RUNPOD_CREDENTIALS return BASE_CREDENTIALS def resolve_credentials( profile: MachineProfile, environ: Mapping[str, str] | None = None, ) -> dict[str, str]: source = environ if environ is not None else os.environ names = required_credentials(profile) missing = [name for name in names if not source.get(name)] if missing: raise CredentialError( "missing runtime credential: " + ", ".join(sorted(missing)) ) return {name: source[name] for name in names} ``` ```python # src/axiotic_experiments/backends.py def launch_local( spec: ExperimentSpec, profile: MachineProfile, *, runtime_env: dict[str, str], credentials: dict[str, str], ) -> LaunchResult: workdir = _prepare_local_source(spec, profile) env = os.environ.copy() env.update(runtime_env) env.update(credentials) started = time.monotonic() process = subprocess.Popen( list(spec.run.command), cwd=workdir, env=env, start_new_session=True, ) ``` ```python def ssh_payload( spec: ExperimentSpec, profile: MachineProfile, *, runtime_env: dict[str, str], credentials: dict[str, str], ) -> dict[str, Any]: return { "run_id": spec.run.id, "command": list(spec.run.command), "env": {**runtime_env, **credentials}, "timeout_seconds": spec.execution.max_hours * 3600, ...[truncated 2279 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
README.md:15
Finding

Optional installation command relies on unpinned mutable remote tooling

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (58)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Hugging Face uploads and GitHub/Hugging Face validation behaviors materially expand the attack surface beyond local experiment management, especially if artifacts can contain checkpoints, dataset fragments, or embedded secrets. In this context, undeclared publication to public or misconfigured private repositories could result in irreversible data exposure.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
96% confidence
Finding

Copying the full process environment into a job that then executes attacker-controlled or user-controlled experiment commands is a classic secret overexposure problem. Any tokens present in the launcher's environment can become accessible to the experiment process, which is especially dangerous in a framework designed to run arbitrary ML workloads and remote code from repositories.

Content

Scanner excerpt · src/axiotic_experiments/backends.py (reported line 191)May include surrounding context.

python
credentials: dict[str, str],
) -> LaunchResult:
    workdir = _prepare_local_source(spec, profile)
    env = os.environ.copy()
    env.update(runtime_env)
    env.update(credentials)
    started = time.monotonic()

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 · src/axiotic_experiments/spec.py (reported line 203)May include surrounding context.

python
isinstance(key, str) and isinstance(value, (str, int, float, bool))
            for key, value in public_env_raw.items()
        ):
            raise SpecError("[execution].env must contain scalar public values")
        public_env = {key: str(value) for key, value in public_env_raw.items()}
        for key, value in public_env.items():
            if _SECRET_KEY.search(key.upper()):

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 · src/axiotic_experiments/spec.py (reported line 208)May include surrounding context.

python
isinstance(key, str) and isinstance(value, (str, int, float, bool))
            for key, value in public_env_raw.items()
        ):
            raise SpecError("[execution].env must contain scalar public values")
        public_env = {key: str(value) for key, value in public_env_raw.items()}
        for key, value in public_env.items():
            if _SECRET_KEY.search(key.upper()):

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 · src/axiotic_experiments/spec.py (reported line 212)May include surrounding context.

python
isinstance(key, str) and isinstance(value, (str, int, float, bool))
            for key, value in public_env_raw.items()
        ):
            raise SpecError("[execution].env must contain scalar public values")
        public_env = {key: str(value) for key, value in public_env_raw.items()}
        for key, value in public_env.items():
            if _SECRET_KEY.search(key.upper()):

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The README instructs users to install the skill via npx skills add AntreasAntoniou/experiment-framework without pinning a specific version or commit. This can lead to non-reproducible installs and creates a supply-chain risk where a later compromised or maliciously updated package/version is fetched and executed in the user's environment.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill metadata declares no explicit tool scope or permissions even though the skill description clearly implies shell execution, filesystem access, environment-variable use, and likely networked companion tooling. Missing scope declarations are dangerous because reviewers and calling agents cannot reliably constrain what the skill may access, increasing the chance of unauthorized file, secret, or network operations.

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 · src/axiotic_experiments/backends.py (reported line 136)May include surrounding context.

python
def _git_head(path: Path) -> str:
    completed = subprocess.run(
        ["git", "-C", str(path), "rev-parse", "HEAD"],
        check=False,
        capture_output=True,

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 · src/axiotic_experiments/backends.py (reported line 154)May include surrounding context.

python
workdir = Path(profile.remote_checkout(spec.run.id)).expanduser()
        if not (workdir / ".git").is_dir():
            workdir.parent.mkdir(parents=True, exist_ok=True)
            subprocess.run(
                ["git", "clone", "--no-checkout", spec.source.clone_url, str(workdir)],
                check=True,
            )

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 · src/axiotic_experiments/backends.py (reported line 158)May include surrounding context.

python
["git", "clone", "--no-checkout", spec.source.clone_url, str(workdir)],
                check=True,
            )
        subprocess.run(
            [
                "git",
                "-C",

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 · src/axiotic_experiments/backends.py (reported line 170)May include surrounding context.

python
],
            check=True,
        )
        subprocess.run(
            ["git", "-C", str(workdir), "checkout", "--detach", spec.source.commit],
            check=True,
        )