Back to skill

Security audit

LYGO Living Mesh (Layer D)

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent with its mesh-verification purpose, but it delegates execution to unverified local Python tools selected from an environment or working-directory root, which creates a real local tool-hijacking risk.

Install only if you trust the referenced LYGO protocol stack and can keep LYGO_STACK_ROOT pointed at a trusted, non-shared directory. Avoid running these wrappers from untrusted working directories, and treat gossip/join commands as network operations that should be invoked deliberately.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/_stack_invoke.py:13
Finding

Unverified External Tool Resolution Allows Local Tool Hijacking

Content
View full analysis

Vulnerability Details

File Location: scripts/_stack_invoke.py, lines 13–37
Vulnerability Type: Untrusted local tool discovery and execution
Risk Level: Medium

Vulnerable Code

python
def stack_root() -> Path:
    env = os.environ.get("LYGO_STACK_ROOT", "").strip()
    if env:
        return Path(env).resolve()
    for p in HERE.parents:
        if (p / "tools" / "collect_living_mesh_badge.py").is_file():
            return p
        if (p / "tools" / "verify_all_kernel_layers.py").is_file():
            return p
        if (p / "docs" / "network_builder" / "IMMUTABLE_ANCHORS.json").is_file():
            return p
    return Path.cwd()


def invoke(tool_name: str, argv: list[str] | None = None) -> int:
    stack = stack_root()
    tool = stack / "tools" / tool_name
    if not tool.is_file():
        print(
            f'{{"verdict":"ERROR","reason":"missing_tool","tool":"{tool_name}","stack":"{stack}","hint":"set LYGO_STACK_ROOT"}}',
            file=sys.stderr,
        )
        return 2
    cmd = [sys.executable, str(tool), *(argv if argv is not None else sys.argv[1:])]
    return subprocess.call(cmd, cwd=str(stack))

Technical Analysis

Every advertised wrapper delegates its operation to a Python script located outside the audited package. The stack directory can be selected through the LYGO_STACK_ROOT environment variable, inferred from ancestor directories using marker files, or taken directly from the current working directory.

Before execution, the implementation verifies only that the selected path is a regular file. It does not establish that the stack directory is trusted or that the target script is an authentic LYGO component. There is no validation of file ownership, permissions, expected version, cryptographic digest, digital signature, or approved installation root.

Consequently, a malicious or compromised local directory can provide files with ...[truncated 2712 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use an explicitly configured trusted installation root

    • Remove the Path.cwd() fallback.
    • Avoid heuristic ancestor discovery based solely on marker-file existence.
    • Resolve tools only from an installation directory established and protected by the package manager or administrator.
  2. Validate paths before execution

    • Canonicalize the root and target with Path.resolve(strict=True).
    • Confirm that the tool remains beneath the approved root after resolution.
    • Reject symbolic links or other path redirections when they are not explicitly required.
    • On supported systems, verify that the directory and tool are not writable by untrusted users.
  3. Verify tool authenticity

    • Maintain an allowlist of expected tool names and cryptographic SHA-256 digests.
    • Verify a signed manifest before invoking any external tool.
    • Reject unknown versions or hash mismatches rather than continuing with a warning.
  4. Bundle security-critical implementations

    • Prefer shipping the actual implementations within the audited Skill package.
    • If external integration is necessary, expose a versioned API with explicit compatibility and integrity checks instead of executing arbitrary filesystem scripts.
  5. Harden environment-based configuration

    • Do not trust LYGO_STACK_ROOT in privileged, automated, or untrusted execution contexts.
    • Require an explicit command-line configuration or administrator-controlled configuration file.
    • Emit the resolved canonical executable path and verified version before execution.
  6. Apply least privilege

    • Run delegated tools without unnecessary credentials or sensitive environment variables.
    • Restrict filesystem and network access through an appropriate sandbox where feasible.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior centers on mesh gossip and verification, but the detected behavior includes arbitrary execution of Python tools, stack-root discovery via environment/filesystem probing, and generic command dispatch. That mismatch is dangerous because users and orchestrators may trust the declared narrow purpose while the skill can execute broader local actions, enabling abuse of the host environment or execution of unintended scripts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises shell and environment-driven operation but does not declare an explicit tool scope or permissions boundary. In an agent ecosystem, that omission can let the runtime grant broader-than-necessary execution capability, increasing the chance of command execution, environment leakage, or unintended chaining with other tools.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
|--------|---------|
| Egg exfil via gossip | Summaries only — roots + status; no payloads |
| Remote force-merge | Local authority; FORK_VISIBLE never auto-merges |
| Join without consent | `--i-consent` / `LYGO_MESH_JOIN_CONSENT` required |
| Quarantine ignored | Sentinel exit 3; join refused on local QUARANTINE |
| Wide-area exposure | Operator TLS + pin; no auto open ports |
| Skill supply chain | Install from deepseekoracle; LYGO Sovereign License v2.0 |

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/_stack_invoke.py (reported line 37)May include surrounding context.

python
)
        return 2
    cmd = [sys.executable, str(tool), *(argv if argv is not None else sys.argv[1:])]
    return subprocess.call(cmd, cwd=str(stack))


if __name__ == "__main__":

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The script builds a command from a user-supplied tool name and executes it via subprocess.call. Although the module docstring states that it invokes a tools script, there is no explicit runtime disclosure, confirmation, or warning that another Python program will be executed from the detected stack root.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.