Back to skill

Security audit

EmoClaw

Security checks for vulnerabilities and agentic risk

Overview

Review before installing: the skill is mostly coherent and disclosed, but its setup, training, and daemon utilities include real local safety risks.

Install only in a disposable or backed-up project until setup is fixed, because it can replace pyproject.toml. Review bootstrap.source_files and memory_patterns before extraction, inspect extracted_passages.jsonl before any Anthropic labeling, and avoid --yes unless automation is intentional. Do not resume training from untrusted .pt checkpoints. Run the daemon as a normal user, not root, and prefer pinned dependencies or a reviewed lockfile.

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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
engine/emotion_model/scripts/train.py:112
Finding

Unsafe PyTorch Checkpoint Deserialization Permits Arbitrary Code Execution

Content
View full analysis

Vulnerability Details

File Location: engine/emotion_model/scripts/train.py:112-126
Vulnerability Type: Unsafe deserialization of an attacker-controlled PyTorch checkpoint
Risk Level: High

Vulnerable Code

python
def _load_training_checkpoint(path: Path) -> dict:
    """Load a rich training checkpoint, validating dimensions."""
    checkpoint = torch.load(path, map_location="cpu", weights_only=False)

    # Validate dimension compatibility
    saved_dims = checkpoint.get("config_num_dims")
    if saved_dims is not None and saved_dims != config.NUM_EMOTION_DIMS:
        raise RuntimeError(
            f"Checkpoint was trained with {saved_dims} emotion dimensions "
            f"but current config has {config.NUM_EMOTION_DIMS}. "
            f"You must retrain from scratch or update your config."
        )

    return checkpoint

The checkpoint path can be supplied through the training command:

python
elif args.resume is not None:
    resume_from = args.resume

Technical Analysis

torch.load() with weights_only=False permits pickle-based object deserialization. Pickle is not a safe format for untrusted input because serialized objects can define reduction behavior that invokes arbitrary Python callables during loading.

The --resume command-line argument accepts a user-selected checkpoint path. Consequently, a checkpoint obtained from an untrusted source can execute code as soon as _load_training_checkpoint() calls torch.load(). The dimension validation occurs after deserialization and therefore cannot prevent execution.

Attack Path

  1. An attacker creates a malicious .pt checkpoint containing a pickle reduction payload.
  2. The attacker distributes the checkpoint as a pretrained or resumable Emoclaw training artifact.
  3. A user runs:
    bash
    python -m emotion_model.scripts.train --resume attacker.pt
    
  4. `_load_training_checkpoint ...[truncated 683 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace the unsafe load with torch.load(path, map_location="cpu", weights_only=True).
  • Store non-tensor resume metadata, such as epoch numbers and validation metrics, in JSON or another non-executable format.
  • If optimizer state cannot be loaded safely, document that only inference weights can be imported from external sources.
  • Restrict resumable checkpoints to a user-owned checkpoint directory with restrictive permissions.
  • Cryptographically verify trusted checkpoints before loading them.
  • Clearly warn users never to load untrusted PyTorch or pickle-based artifacts.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/daemon.sh:21
Finding

Predictable and Unvalidated PID File Can Cause Unrelated Processes to Be Signaled

Content
View full analysis

Vulnerability Details

File Location: scripts/daemon.sh:21-55
Vulnerability Type: Insecure temporary PID file and improper process identity validation
Risk Level: High

Vulnerable Code

bash
PIDFILE="/tmp/emotion-daemon.pid"

do_stop() {
    if [ ! -f "$PIDFILE" ]; then
        echo "No PID file found. Daemon may not be running."
        return 1
    fi

    local pid
    pid=$(cat "$PIDFILE")

    if kill -0 "$pid" 2>/dev/null; then
        echo "Stopping emotion daemon (PID $pid)..."
        kill "$pid"
        rm -f "$PIDFILE"
        echo "Daemon stopped."
    else
        echo "Daemon not running (stale PID file). Cleaning up."
        rm -f "$PIDFILE"
    fi
}

The start operation also writes to the predictable path without exclusive creation or ownership validation:

bash
local pid=$!
echo "$pid" > "$PIDFILE"

Technical Analysis

The PID file has a fixed, system-wide name under /tmp. The script does not verify file ownership, reject symbolic links, create the file exclusively, validate the PID as a strictly positive integer, or confirm that the PID belongs to the Emoclaw daemon.

A local attacker can create or replace the file while the daemon is not running. The subsequent stop or restart action trusts its contents and supplies them directly to kill. A selected positive PID can target another process owned by the invoking user. Special negative process-group values may broaden the set of signaled processes, depending on shell and operating-system behavior.

Attack Path

  1. The daemon is not running and /tmp/emotion-daemon.pid is absent.
  2. Another local user or compromised process creates that path.
  3. The attacker writes the PID of an unrelated victim process, or a specially chosen process-group value, into the file.
  4. The victim invokes:
    bash
    bash scripts/daemon.sh stop
    
    or:
    bash
    bash scri
    

...[truncated 769 chars]

Remediation
View remediation

Remediation Suggestions

  • Store the PID file under a private runtime directory such as $XDG_RUNTIME_DIR/emoclaw/.
  • Create the runtime directory with mode 0700 and the PID file with mode 0600.
  • Use exclusive, symlink-resistant file creation.
  • Validate the value against ^[1-9][0-9]*$ before using it.
  • Invoke process tools with explicit option termination, such as kill -- "$pid".
  • Verify that the target process command line or executable corresponds to emotion_model.daemon.
  • Prefer a service manager or a process supervisor that maintains process identity securely.
  • Use an agent-specific PID filename if multiple agents may run concurrently.

T09 · Insecure Skill Coding Practices

Warning
Location
engine/emotion_model/daemon.py:47
Finding

Unbounded Unix-Socket Request Reading Enables Local Denial of Service

Content
View full analysis

Vulnerability Details

File Location: engine/emotion_model/daemon.py:47-72
Vulnerability Type: Unbounded request accumulation and missing socket timeout
Risk Level: Medium

Vulnerable Code

python
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server.bind(socket_path)
server.listen(1)
os.chmod(socket_path, 0o660)

try:
    while True:
        conn, _ = server.accept()
        try:
            data = b""
            while True:
                chunk = conn.recv(4096)
                if not chunk:
                    break
                data += chunk

            request = json.loads(data.decode("utf-8"))

Technical Analysis

The daemon reads data until the client closes its connection. It imposes no maximum message size, read deadline, total connection timeout, or framing requirement.

Repeated data += chunk operations retain the complete request in memory and repeatedly allocate larger byte strings. A socket client can therefore consume increasingly large amounts of memory by sending an oversized request. Alternatively, a client can send partial data and keep the connection open indefinitely.

Because requests are processed serially and the listen backlog is only one, a single slow client can prevent legitimate inference requests from being handled. The socket mode is 0660, so exploitation is available to the socket owner and members of its assigned group.

Attack Path

  1. A local process obtains access to the Unix socket through owner or group permissions.
  2. It connects to the daemon.
  3. It continuously transmits data without closing the connection, or sends a partial JSON document and stalls.
  4. The daemon either accumulates the entire stream in memory or blocks indefinitely in recv().
  5. Legitimate clients cannot obtain inference responses.
  6. With a sufficiently large stream, the daemon or other processes may be terminated by memory exhaust ...[truncated 306 chars]
Remediation
View remediation

Remediation Suggestions

  • Define a strict maximum request size, such as 64 KiB.
  • Reject the connection immediately when accumulated data exceeds the limit.
  • Set a short per-connection read timeout with conn.settimeout().
  • Use length-prefixed messages or newline-delimited JSON rather than reading until disconnection.
  • Process multiple clients safely or ensure one stalled client cannot block the service.
  • Validate peer credentials where supported by the operating system.
  • Limit message text and context lengths before model inference.
  • Return a structured error for malformed or oversized requests without logging sensitive request content.

T08 · Insecure Dependencies

Warning
Location
engine/pyproject.toml:1
Finding

Setup Automatically Installs Mutable and Unpinned Dependencies

Content
View full analysis

Vulnerability Details

File Location: engine/pyproject.toml:1-19
Additional Location: scripts/setup.py:79-95
Vulnerability Type: Unpinned supply-chain dependencies and automatic package installation
Risk Level: Medium

Vulnerable Code

toml
[build-system]
requires = ["setuptools>=68.0"]
build-backend = "setuptools.build_meta"

[project]
name = "emotion_model"
version = "1.0.0"
description = "Persistent emotional state model for AI agents"
requires-python = ">=3.10"
dependencies = [
    "torch>=2.0.0",
    "sentence-transformers>=2.2.0",
    "numpy>=1.24.0",
    "pyyaml>=6.0",
]

[project.optional-dependencies]
dev = ["pytest>=7.0"]
bootstrap = ["anthropic>=0.30.0"]

Setup resolves and installs these dependencies automatically:

python
result = subprocess.run(
    [str(pip), "install", "-e", str(REPO_ROOT)],
    capture_output=True,
    text=True,
)
if result.returncode != 0:
    print(f"  ERROR: pip install failed:\n{result.stderr}")
    sys.exit(1)

print("  Installing dev dependencies (pytest)...")
subprocess.run(
    [str(pip), "install", "pytest"],
    capture_output=True,
    text=True,
)

Technical Analysis

All declared packages use open-ended lower bounds. No lock file, hashes, upper bounds, or constrained package index are provided. As a result, two installations performed at different times may resolve materially different direct and transitive dependencies.

Python package installation can execute build-backend and installation logic. A compromised future release, malicious transitive package, dependency-confusion condition, or compromised package index could therefore introduce code that was never reviewed as part of this Skill.

The setup process also installs pytest unconditionally even though it is only a development dependency, unnecessarily increasing the production dependency surface.

Attack Path

...[truncated 1022 chars]

Remediation
View remediation

Remediation Suggestions

  • Produce a reviewed lock file containing exact direct and transitive versions.
  • Require hashes for downloaded artifacts, for example through pip --require-hashes.
  • Pin or tightly constrain the build backend as well as runtime packages.
  • Use a trusted, explicitly configured package index.
  • Regenerate locks through a controlled dependency-update process with security review.
  • Run dependency vulnerability and provenance scanning in continuous integration.
  • Remove unconditional pytest installation from production setup.
  • Separate development, bootstrap, and inference environments where practical.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.py:43
Finding

Setup Can Overwrite an Existing Root Project Configuration Without Confirmation

Content
View full analysis

Vulnerability Details

File Location: scripts/setup.py:43-53
Vulnerability Type: Unsafe overwrite of an existing project build configuration
Risk Level: Medium

Vulnerable Code

python
if PACKAGE_DIR.exists() and (PACKAGE_DIR / "config.py").exists():
    print(f"  Engine already exists at {PACKAGE_DIR.relative_to(REPO_ROOT)}")
elif BUNDLED_ENGINE.exists():
    print(f"  Copying bundled engine to {PACKAGE_DIR.relative_to(REPO_ROOT)}...")
    shutil.copytree(BUNDLED_ENGINE, PACKAGE_DIR, dirs_exist_ok=True)
    # Copy pyproject.toml to repo root (above emotion_model/) — matching
    # the engine/ layout where setuptools finds the emotion_model package.
    if BUNDLED_PYPROJECT.exists():
        shutil.copy2(BUNDLED_PYPROJECT, REPO_ROOT / "pyproject.toml")
    print("  Engine installed.")

Technical Analysis

During a fresh engine installation, shutil.copy2() writes the bundled pyproject.toml directly to the repository root. The code does not check whether the destination already exists, request confirmation, preserve a backup, or merge the project definitions.

A root pyproject.toml commonly controls dependencies, packaging, build backends, test settings, formatting, and other development tools. Replacing it can silently change the behavior of later builds and package installations.

This is a destructive setup flaw rather than an intentional tool-hijacking mechanism: the copied file is visible and bundled with the Skill, and no evidence of a hidden malicious replacement was found.

Attack Path

  1. A user has an existing Python repository with a root pyproject.toml.
  2. The repository does not yet contain the copied emotion_model/config.py.
  3. The user runs the Emoclaw setup script.
  4. Setup copies the engine and unconditionally replaces the root pyproject.toml.
  5. Existing package metadata and tooling configuration are lost.
  6. Subsequent pip, build, test, or rele ...[truncated 449 chars]
Remediation
View remediation

Remediation Suggestions

  • Abort with a clear error when the destination pyproject.toml already exists.
  • Never overwrite an existing project configuration without explicit confirmation.
  • Create a timestamped backup before any approved replacement.
  • Prefer installing the bundled engine from its own package directory instead of copying its build configuration to the host repository root.
  • If integration is necessary, provide documented merge instructions or a narrowly scoped automated merge.
  • Add tests covering installation into repositories that already contain Python project metadata.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises substantive emotion-model behavior: persistent/evolving emotional state, memory influence, decay between sessions, and training on identity files. The provided code does none of that. It only adjusts Python's import path in a conftest.py file, which is a testing/support utility. While such setup code could support a larger emotion model package, this specific chunk's actual behavior is materially different from the declared primary purpose and contains no implementation of the advertised capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description emphasizes a runtime system that maintains and evolves an AI's emotions over conversations and sessions. However, this code chunk only performs offline data preprocessing for training: it reads labeled examples from specific JSONL files, checks schema validity, normalizes fields, and splits data into train/val outputs. There is no implementation of emotional state tracking, memory accumulation, decay, self-calibration, identity-file ingestion, or any conversational runtime behavior. This is a materially different primary purpose from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk is a conventional model training utility, not a runtime system that maintains or evolves an agent's emotional state from memories across conversations. It reads labeled training/validation datasets, encodes text, uses previous emotion as an input feature, computes weighted MSE against target emotion vectors, and saves checkpoints. While this is related to emotion modeling in a broad sense, it does not implement the key behaviors emphasized in the description: persistent emotion shaped by the agent's own memories, decay between sessions, self-calibration over time, or identity-file-driven emotional fingerprinting. Therefore the declared description materially overstates and mischaracterizes what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a stateful emotional engine that learns from memories, persists and decays across sessions, and can be trained on identity files. The supplied code does none of that. It takes an already-existing emotion vector, derives simple high/low tags, optionally loads phrase templates from YAML, and returns a random descriptive phrase matching the tags. While this may support presenting an emotional state in words, it does not implement the core declared behavior of building or evolving the emotional state itself. Therefore the code chunk materially differs from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description promises a functional emotional system for an AI agent that changes over time based on memories and conversations. The code shown does not implement any such emotional state logic. Instead, it prepares training/input data by extracting passages from repository files for a downstream labeling pipeline. While this may support the broader project, the actual chunk’s primary purpose is data extraction and redaction, not building or operating an evolving emotional model. Therefore the declared description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description presents a runtime emotional system for an AI agent: emotions built from memories, evolving over time, decaying between sessions, and shaped by identity files. The supplied code does not implement any of that behavior. Instead, it loads configuration, reads extracted passages from disk, constructs a prompt for emotion-dimension scoring, calls the Anthropic API to label each passage, and saves the results as JSONL. It also offers dry-run and review worksheet generation. This is a training-data preparation/annotation script, not an emotion engine. Additionally, the script transmits passage text to an external API, which is a meaningful capability not reflected in the declared permissions. Therefore the declared description does not accurately represent the actual behavior of this code chunk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · assets/emoclaw.yaml (reported line 201)May include surrounding context.

yaml
- '(?i)sk-ant-[a-zA-Z0-9_-]{20,}'          # Anthropic API keys
    - '(?i)(?:api[_-]?key|token|secret|password|credential)\s*[:=]\s*\S+'
    - '(?i)bearer\s+[a-zA-Z0-9._~+/=-]+'       # Bearer tokens
    - 'ghp_[a-zA-Z0-9]{36}'                     # GitHub personal access tokens
    - '(?i)ssh-(?:rsa|ed25519)\s+\S+'           # SSH keys

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 · engine/emotion_model/encoder.py (reported line 42)May include surrounding context.

python
"""Encode message with optional recent conversation context.

        Context is truncated from the left (keeping the most recent part)
        and prepended to capture conversational flow.
        """
        if context:
            context = context[-max_context_chars:]

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/daemon.sh (reported line 72)May include surrounding context.

sh
echo "Emotion daemon is running (PID $(cat "$PIDFILE"))"
    else
        echo "Emotion daemon is not running"
        [ -f "$PIDFILE" ] && rm -f "$PIDFILE"
    fi
}

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/label.py (reported line 15)May include surrounding context.

python
python scripts/label.py
    python scripts/label.py --config path/to/emoclaw.yaml
    python scripts/label.py --review          # Generate human review worksheet
    python scripts/label.py --dry-run         # Show prompt without calling API
"""

from __future__ import annotations

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
98% confidence
Finding

The skill documents capabilities that include shell execution, file reads/writes, environment variable access, and optional network access, but it declares no explicit tool scope or permissions. That increases the chance an agent platform grants broader access than operators expect, especially because the skill reads local memory/identity files and can transmit extracted passages to an external API during labeling.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill recommends passive collection of ongoing conversation messages and correction events for retraining, creating a retention pipeline for potentially sensitive user content. In the context of an agent trained on identity and memory files, this increases privacy risk, data accumulation, and the chance that secrets or personal data are stored locally or later sent for labeling/retraining.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code persists emotional/conversational state to disk via save_state(self.state, self.state_path) without any disclosure, consent check, or indication in this component that users are informed their interactions are being retained across sessions. In the context of a skill explicitly designed to build memories and evolving emotions from conversations, silent persistence increases privacy risk because sensitive behavioral or conversational data may be stored longer than users expect.

Content

No source excerpt is available for this finding.

Insecure deserialization: torch.load() without weights_only=True

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This is a true vulnerability: torch.load(..., weights_only=False) uses Python pickle deserialization, which can execute arbitrary code during load if the checkpoint file is attacker-controlled or tampered with. In this training script, --resume accepts a user-supplied path and the auto-resume path loads from disk without any trust validation, so a malicious checkpoint could lead to code execution on the host running training.

Content

Scanner excerpt · engine/emotion_model/scripts/train.py (reported line 115)May include surrounding context.

python
def _load_training_checkpoint(path: Path) -> dict:
    """Load a rich training checkpoint, validating dimensions."""
    checkpoint = torch.load(path, map_location="cpu", weights_only=False)

    # Validate dimension compatibility
    saved_dims = checkpoint.get("config_num_dims")

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

python
print(f"  {name}")
    print(f"{'=' * 60}\n")

    result = subprocess.run(cmd, cwd=str(REPO_ROOT))

    if result.returncode != 0:
        print(f"\nERROR: {name} failed (exit code {result.returncode})")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script extracts passages from identity and memory files, then persists them to a JSONL file on disk. Even though optional redaction exists, it is pattern-based and may miss sensitive personal data, so the tool can silently create a secondary plaintext dataset containing private material. In this skill’s context, the source inputs are explicitly identity/memory files, which makes accidental exposure more likely and increases the sensitivity of the output.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script transmits passage contents, including source file names, headings, and up to 1200 characters of text, to Anthropic's external API for labeling. If extracted passages contain sensitive memories, identity files, prompts, or personal data, this creates a real data exfiltration/privacy risk beyond purely local processing, even though the script does present a consent prompt first.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest frames the skill as maintaining and evolving an internal emotional fingerprint based on conversations and identity files. Pulling a third-party API key from the environment and invoking a hosted model introduces external-service dependency and credential use that are not apparent from that purpose statement.

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

python
print(f"  Venv already exists at {VENV_DIR.relative_to(REPO_ROOT)}")
    else:
        print(f"  Creating venv at {VENV_DIR.relative_to(REPO_ROOT)}...")
        subprocess.run(
            [sys.executable, "-m", "venv", str(VENV_DIR)],
            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 · scripts/setup.py (reported line 82)May include surrounding context.

python
pip = VENV_DIR / "Scripts" / "pip.exe"  # Windows fallback

    print("  Installing emotion_model package (editable)...")
    result = subprocess.run(
        [str(pip), "install", "-e", str(REPO_ROOT)],
        capture_output=True,
        text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
84% confidence
Finding

The setup script installs an additional package from the package index without pinning or clear necessity for core setup. This expands the supply-chain attack surface during installation and causes networked code retrieval/execution beyond what users would reasonably expect from first-time setup of the skill.

Content

Scanner excerpt · scripts/setup.py (reported line 94)May include surrounding context.

python
# --- Install dev dependencies ---
    print("  Installing dev dependencies (pytest)...")
    subprocess.run(
        [str(pip), "install", "pytest"],
        capture_output=True,
        text=True,

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally pull in vulnerable or incompatible releases, especially for a security-sensitive package like torch that has a history of advisories.

Content

Scanner excerpt · engine/emotion_model/requirements.txt (reported line 1)May include surrounding context.

text
torch>=2.0.0
sentence-transformers>=2.2.0
numpy>=1.24.0

Unverifiable Dependency: torch has 16 known advisory(ies) (CVE-2025-2953 (PyTorch susceptible to local Denial of Service); CVE-2022-45907 (PyTorch vulnerable to arbitrary code execution); CVE-2025-32434 (PyTorch: `torch.load` with `weights_only=True` leads to remote code execution) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

Torch has multiple known advisories, and because the requirement is not pinned, it is impossible to determine from this manifest whether the installed version includes fixes. In an ML-focused skill, this matters more because torch commonly interacts with model loading and native code, increasing the potential blast radius if a vulnerable build is resolved.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The sentence-transformers dependency is unpinned, so installations are not reproducible and may drift to newer releases with unreviewed behavior or transitive dependency changes. This creates supply-chain risk and makes it harder to verify whether deployed environments are affected by future package issues.

Content

Scanner excerpt · engine/emotion_model/requirements.txt (reported line 2)May include surrounding context.

text
torch>=2.0.0
sentence-transformers>=2.2.0
numpy>=1.24.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

Using numpy with only a minimum version allows package resolution to vary by installation time and environment. That increases the chance of introducing vulnerable or unstable versions and reduces the ability to attest to a known-safe build.

Content

Scanner excerpt · engine/emotion_model/requirements.txt (reported line 3)May include surrounding context.

text
torch>=2.0.0
sentence-transformers>=2.2.0
numpy>=1.24.0

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
engine/emotion_model/tests/test_model.py:74