Back to skill

Security audit

Avatar Runtime

Security checks for vulnerabilities and agentic risk

Overview

The skill’s avatar features are coherent, but it asks users to run an unpinned npm runtime that could change later and may receive API keys.

Install only after verifying the exact npm package identity and pinning a reviewed version. Run it in a sandbox first, avoid giving it production API keys, and treat any unpinned `npx avatar-runtime` command as code execution under your user account.

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

Error
Location
SKILL.md:87
Finding

Unpinned and Inconsistently Named Runtime Dependency

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 87–96
Vulnerability Type: Supply-chain risk from remote execution of an unpinned npm package
Risk Level: High

Vulnerable Code

bash
# zero-config (mock provider — no API key required)
AVATAR_PROVIDER=mock npx avatar-runtime

# with Live2D local bridge
npm run dev:live2d-cubism-bridge          # terminal A — bridge on :3755
AVATAR_PROVIDER=live2d LIVE2D_ENDPOINT=http://127.0.0.1:3755 npx avatar-runtime  # terminal B

# with VRM 3D avatar (free models from https://hub.vroid.com — place .vrm in assets/vrm/slot/)
npm run dev:vrm-bridge                    # terminal A — asset server on :3756
AVATAR_PROVIDER=vrm npx avatar-runtime   # terminal B

The same unpinned command also appears at SKILL.md:277 and SKILL.md:310. By contrast, references/WEB-EMBEDDING.md:35 identifies the package using the scoped name:

js
const AvatarWidget = require('@acnlabs/avatar-runtime/widget');

Technical Analysis

The documented npx avatar-runtime command may download and immediately execute the latest version of an unscoped npm package. Neither an exact version nor an artifact integrity value is specified. Consequently, the code reviewed by a user can differ from the code later resolved and executed by npm.

The unscoped executable name is also inconsistent with the scoped package name @acnlabs/avatar-runtime shown in the embedding reference. This creates package-name confusion risk: users may review or intend to trust the scoped package while npx resolves a different unscoped package.

npm package installation and runtime code can execute arbitrary code under the invoking user's account. Depending on provider configuration, the process may also inherit sensitive environment variables such as HEYGEN_API_KEY and KUSAPICS_API_KEY. The Skill's recommendation to review the source does not cryptographically bind that reviewed source to the do ...[truncated 1637 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the unscoped package command with the verified canonical scoped package and an exact version, for example:

    bash
    npx --yes @acnlabs/avatar-runtime@0.2.1
    
  2. Confirm that the package version matches the Skill documentation and verified upstream release before execution.

  3. Prefer a local, lockfile-controlled installation:

    bash
    npm install --save-exact @acnlabs/avatar-runtime@0.2.1
    npm ci
    

    Commit package-lock.json and preserve npm integrity metadata.

  4. Verify package publisher identity, npm provenance, release signatures where available, and the relationship between the registry artifact and the reviewed source repository.

  5. Run the package in a sandbox or container with:

    • A read-only or narrowly scoped filesystem.
    • No unnecessary host mounts.
    • Restricted outbound network access.
    • A non-privileged user.
    • Only the provider credentials required for the selected operation.
  6. Avoid exposing credentials globally in a shell session. Supply narrowly scoped, short-lived credentials only to a verified process, and rotate them if an untrusted package may have received them.

  7. Pin all referenced asset-download scripts and external assets to reviewed versions and cryptographic digests.

  8. Make the package name consistent throughout SKILL.md and references/WEB-EMBEDDING.md so the package executed is the same package users are instructed to review.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (14)

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 · SKILL.md (reported line 272)May include surrounding context.

bash
BASE=http://127.0.0.1:3721
SESSION=$(curl -s -X POST "$BASE/v1/session/start" \
  -H "content-type: application/json" \
  -d '{"personaId":"demo","form":"image"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

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 · SKILL.md (reported line 277)May include surrounding context.

md
-d '{"personaId":"demo","form":"image"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

# Face expression
curl -s -X POST "$BASE/v1/control/avatar/set" \
  -H "content-type: application/json" \
  -d '{"face":{"pose":{"yaw":0.2},"mouth":{"smile":0.7}},"emotion":{"label":"happy","valence":0.8}}'

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 · SKILL.md (reported line 325)May include surrounding context.

md
-H "content-type: application/json" \
  -d '{"personaId":"demo","form":"video"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

curl -s -X POST "$BASE/v1/input/text" \
  -H "content-type: application/json" \
  -d "{\"sessionId\":\"$SESSION\",\"text\":\"Hello! I am your AI companion.\"}"

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

The skill instructs users to execute npx avatar-runtime without pinning a specific version. Because npx resolves and downloads the latest package at runtime, a compromised publisher account, malicious new release, or dependency-chain attack could result in arbitrary code execution on the host. The skill context increases risk because first-run internet access is explicitly required and execution happens directly from fetched package contents.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

This is another unpinned npx avatar-runtime execution path. Unpinned runtime installation enables remote code execution if the upstream npm package or one of its install-time behaviors changes maliciously between runs. The warning text in the skill does not eliminate the vulnerability; it only acknowledges the risk while still prescribing the unsafe pattern.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The startup command AVATAR_PROVIDER=mock npx avatar-runtime still performs unpinned package retrieval/execution. Even though the provider is mock, the attack surface is the package fetch and execution itself, not the avatar provider selection. This is therefore a genuine supply-chain risk leading to arbitrary code execution.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

This command combines a local endpoint setting with unpinned npx avatar-runtime execution. The local endpoint does not reduce the danger from fetching and running an unversioned npm package at runtime, which remains a code execution vector if the package is tampered with upstream.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The VRM startup example also invokes npx avatar-runtime without a fixed version. Any future malicious or compromised release could be executed automatically by users following the documentation, making this a real supply-chain execution issue.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

bash
# start session
curl -s -X POST "$AVATAR_RUNTIME_URL/v1/session/start" \
  -H "content-type: application/json" \
  -d '{"personaId":"{{slug}}","form":"image"}'

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The quick-start section repeats the same unpinned runtime execution pattern. Documentation that encourages repeated direct npx execution materially increases the likelihood users will run unreviewed package updates, exposing systems to arbitrary code execution.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

bash
BASE=http://127.0.0.1:3721
SESSION=$(curl -s -X POST "$BASE/v1/session/start" \
  -H "content-type: application/json" \
  -d '{"personaId":"demo","form":"image"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
-d '{"personaId":"demo","form":"image"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

# Face expression
curl -s -X POST "$BASE/v1/control/avatar/set" \
  -H "content-type: application/json" \
  -d '{"face":{"pose":{"yaw":0.2},"mouth":{"smile":0.7}},"emotion":{"label":"happy","valence":0.8}}'

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The HeyGen example again relies on unpinned npx execution, now in a context where sensitive API credentials are also present in environment variables. If a malicious package version were fetched, it could exfiltrate those secrets in addition to executing arbitrary code, increasing the practical impact.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
-H "content-type: application/json" \
  -d '{"personaId":"demo","form":"video"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['sessionId'])")

curl -s -X POST "$BASE/v1/input/text" \
  -H "content-type: application/json" \
  -d "{\"sessionId\":\"$SESSION\",\"text\":\"Hello! I am your AI companion.\"}"

Static analysis

No suspicious patterns detected.