Back to skill

Security audit

LYGO Joy Loop Protocol

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent and consent-scoped, but its install and helper script leave review-worthy paths for running unpinned or unverified code.

Install only in a LYGO stack checkout you control. Prefer a pinned ClawHub installer or verify package provenance first, set LYGO_STACK_ROOT to a trusted absolute path, and only run plant commands after explicit consent and after confirming the target planter file is the expected LYGO stack script.

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)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:50
Finding

Mutable ClawHub Installer Dependency Is Executed Without Version Pinning

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:50
Vulnerability Type: Supply-chain risk from a mutable third-party installer
Risk Level: Medium

Vulnerable Code:

bash
npx clawhub@latest install deepseekoracle/lygo-joy-loop

Technical Analysis

The documented installation procedure invokes clawhub@latest through npx. The latest tag is mutable, so the package code executed during installation can differ from the version that existed when this Skill was audited. No exact package version or integrity digest is provided.

This creates an unsafe dependency boundary: control of the package, its publishing account, or its dependency chain could allow changed code to execute when a user follows the official installation instructions. The flagged curl | bash text in references/SECURITY.md:54 is not an executable instruction—it explicitly identifies that pattern as forbidden—and is therefore not a vulnerability.

Attack Path

  1. An attacker compromises the clawhub package publishing process, maintainer account, or relevant dependency chain.
  2. The attacker publishes a modified release and assigns it to the mutable latest tag.
  3. A user follows the documented installation command.
  4. npx retrieves and runs the modified package.
  5. Malicious installer behavior executes under the privileges of the user running the command.

Impact Assessment

A compromised installer could execute arbitrary code with the installing user's privileges. Depending on that user's permissions, this could expose accessible files and credentials, alter local repositories or configuration, install modified Skill content, or execute additional processes. The documented command does not request sudo, so no direct operating-system privilege escalation is established by the audited content.

Remediation
View remediation

Remediation Suggestions

  • Replace clawhub@latest with an exact, reviewed package version.
  • Publish and document an expected package integrity hash or a lockfile-backed installation process.
  • Avoid mutable tags in security-sensitive installation instructions.
  • Verify the package publisher and provenance before installation.
  • Where supported, use signed releases and verify signatures before executing installer code.
  • Document a non-executing download-and-inspect workflow for users who require stronger supply-chain assurance.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/plant_joy_loop.py:10
Finding

Environment-Controlled Stack Root Selects an Unverified Python Program for Execution

Content
View full analysis

Vulnerability Details

File Locations: scripts/_stack_paths.py:5-9; scripts/plant_joy_loop.py:10-22
Vulnerability Type: Unvalidated executable path derived from an environment variable
Risk Level: Medium

Path Source (scripts/_stack_paths.py:5-9):

python
def stack_root() -> Path:
    env = os.environ.get("LYGO_STACK_ROOT")
    if env:
        return Path(env)
    return Path(__file__).resolve().parents[4]

Execution Sink (scripts/plant_joy_loop.py:10-22):

python
ROOT = stack_root()
if os.environ.get("LYGO_JOY_PLANT_CONSENT") != "yes":
    print(
        "Refusing plant: human consent required. "
        "After the user agrees, run with LYGO_JOY_PLANT_CONSENT=yes "
        "or call stack tools/joy_loop_planter.py --i-consent directly.",
        file=sys.stderr,
    )
    raise SystemExit(2)
cmd = [sys.executable, str(ROOT / "tools" / "joy_loop_planter.py"), "--i-consent"]
raise SystemExit(subprocess.call(cmd, cwd=ROOT))

Technical Analysis

stack_root() accepts LYGO_STACK_ROOT without resolving or validating it. The planting wrapper then constructs tools/joy_loop_planter.py beneath that path and executes it with the current Python interpreter.

The consent check prevents invocation unless LYGO_JOY_PLANT_CONSENT equals yes, but it does not authenticate the selected repository or executable. The wrapper does not verify that:

  • the root is an absolute, expected LYGO repository;
  • the target is a regular file rather than an unexpected link;
  • required repository markers are present;
  • the planter matches a trusted version or digest.

The argument-list form of subprocess.call does not invoke a shell and therefore avoids shell metacharacter injection. The vulnerability instead concerns attacker-influenced executable selection.

Attack Path

  1. An attacker creates or controls a directory containing a malicious `tools/joy_loop_planter.p ...[truncated 1108 chars]
Remediation
View remediation

Remediation Suggestions

  • Require LYGO_STACK_ROOT to be an absolute path and normalize it with Path.resolve(strict=True).
  • Verify that the resolved root is a directory and contains expected, trusted LYGO repository markers.
  • Resolve the planter path separately and ensure it remains beneath the validated root.
  • Require the planter to be a regular file and reject unexpected symbolic-link traversal where appropriate.
  • Verify the planter against an approved digest, signed manifest, or trusted repository revision before execution.
  • Fail closed when validation is inconclusive.
  • Retain the argument-list subprocess invocation and avoid introducing shell=True.
  • Retain the explicit consent gate, but treat consent and executable authenticity as separate requirements.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (9)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/SECURITY.md (reported line 54)May include surrounding context.

md
| Class | Allowed | Forbidden |
|-------|---------|-----------|
| Subprocess | `python tools/joy_loop_*.py` under stack root | `curl \| bash`, arbitrary shell, `sudo` |
| Network (skill default) | **None** from skill scripts | Exfiltration, remote Ollama override |
| Network (user `--serve` / `--dashboard`) | **127.0.0.1** only unless user binds otherwise | Agents must not expose ports publicly without user request |
| Git / ClawHub | **Human-only** | Agent `git push`, `clawhub publish` without explicit user ask |

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using 'npx clawhub@latest install ...' pulls and executes the newest published package at install time, creating a supply-chain risk. If the package is compromised or a malicious version is published, users may run attacker-controlled code before any local safeguards in this skill apply.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · references/SECURITY.md (reported line 32)May include surrounding context.

md
- Optional **`git_head`** short hash of your repo

It does **not** include API keys, env vars, or user PII by design.  
**If you push the repo to GitHub Pages, this JSON can become world-readable.**  
Agents must **warn the user** before any command that updates the snapshot if a push might follow.

## Declared filesystem scope (least privilege)

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The installation guidance uses npx clawhub@latest install ..., which pulls the latest package version at execution time rather than a pinned, reviewed version. That creates a supply-chain risk: a compromised upstream package or breaking update could execute unexpected code on the user's machine during install.

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 · scripts/plant_joy_loop.py (reported line 22)May include surrounding context.

python
)
    raise SystemExit(2)
cmd = [sys.executable, str(ROOT / "tools" / "joy_loop_planter.py"), "--i-consent"]
raise SystemExit(subprocess.call(cmd, cwd=ROOT))

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The docstring on L02 describes the file purely as a mirror/delegator to the stack joy_loop_planter. In practice, lines L13-L20 add additional behavior by refusing execution unless a specific consent environment variable is set, so the documentation understates and partially misstates the script's actual intent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.