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## 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
## 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
Content
```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'])")
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
-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}}'
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
-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.\"}"
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

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.

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.

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.

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.

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.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# start session
curl -s -X POST "$AVATAR_RUNTIME_URL/v1/session/start" \
  -H "content-type: application/json" \
  -d '{"personaId":"{{slug}}","form":"image"}'
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

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.

External Transmission

Medium
Category
Data Exfiltration
Content
```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'])")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
-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}}'
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

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.

External Transmission

Medium
Category
Data Exfiltration
Content
-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.\"}"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.