Back to skill

Security audit

AgentChat

Security checks for vulnerabilities and agentic risk

Overview

This messaging skill appears purpose-built, but it has review-level issues around installing the wrong package name and handling a private key unsafely.

Review carefully before installing. Do not run the documented global install command unless the package name and version are corrected to the reviewed package. Avoid entering a real nsec on the command line, and do not use this with an important Nostr identity unless key storage is changed to a secure credential store or a permission-hardened file. Treat public relay use as public metadata exposure even when message contents are encrypted.

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)

T09 · Insecure Skill Coding Practices

Error
Location
src/index.ts:38
Finding

Nostr Private Key Stored in a Plaintext Configuration File Without Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: src/index.ts:38-55, with the sensitive value populated at src/index.ts:129-134
Vulnerability Type: Plaintext storage of sensitive authentication material
Risk Level: High

Vulnerable Code

ts
const CONFIG_PATH = join(homedir(), ".agent-chat", "config.json");

function loadConfig(): Config {
  if (existsSync(CONFIG_PATH)) {
    return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
  }
  throw new Error("Config not found. Run: agent-chat login <nsec>");
}

function saveConfig(config: Config): void {
  const dir = join(homedir(), ".agent-chat");
  import("fs").then(fs => {
    if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
  });
}

The configuration written by this function contains the supplied private key:

ts
const config: Config = {
  npub,
  nsec,
  relays: [],
};

saveConfig(config);

Technical Analysis

The login command places the complete Nostr private key (nsec, or a hexadecimal equivalent) in the configuration object. saveConfig serializes that object directly to ~/.agent-chat/config.json.

Neither the configuration directory nor the file is created with an explicit restrictive permission mode. Their effective permissions therefore depend on the process umask and any pre-existing filesystem objects. On a permissively configured multi-user system, another local account or process may be able to read the private key.

The implementation also does not inspect or reject a pre-existing symbolic link at the configuration path. Consequently, local filesystem manipulation may redirect the write to another user-writable target when the CLI executes with greater privileges.

Attack Path

  1. A victim runs agent-chat login <nsec>.
  2. The CLI serializes the supplied private key into `~/.agent-chat/config.j ...[truncated 1141 chars]
Remediation
View remediation

Remediation Suggestions

  • Prefer an operating-system credential store or hardware-backed secret provider instead of a plaintext JSON file.
  • If file storage is unavoidable, create ~/.agent-chat with mode 0700 and the configuration file with mode 0600.
  • Open the destination using flags that prevent following symbolic links where supported, and verify that the destination is a regular file owned by the current user.
  • Write through a securely created temporary file in the same protected directory, set its permissions explicitly, and atomically rename it into place.
  • Validate and reject insecure permissions on pre-existing directories and files.
  • Separate public configuration such as relay URLs from private key material.
  • Document key rotation and revocation procedures for users whose configuration file may have been exposed.
  • Add automated tests that verify directory permissions, file permissions, symbolic-link handling, and failure behavior.

T08 · Insecure Dependencies

Error
Location
SKILL.md:15
Finding

Installation Instructions Reference a Different and Unpinned npm Package

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:15-17; conflicting package identity at package.json:2
Vulnerability Type: Dependency confusion and unsafe package installation guidance
Risk Level: High

Vulnerable Code

The installation instructions specify an unscoped package:

markdown
## Installation

```bash
npm install -g agent-chat
text

However, the audited project declares a different, scoped package identity:

```json
{
  "name": "@wangwuww/agent-chat",
  "version": "0.0.1",
  "description": "Nostr-based Agent messaging CLI (Agent's WeChat)"
}

Technical Analysis

The documented command installs agent-chat, while the audited project identifies itself as @wangwuww/agent-chat. npm treats these as distinct package names. A user following the documentation may therefore install an unrelated package rather than the reviewed project.

The command also omits a version, so npm resolves the current release associated with the unscoped name at installation time. The effective installed code can consequently differ from both this repository and the version that was audited.

Global npm installation is security-sensitive because package lifecycle scripts, if present in the resolved package or its dependencies, may execute during installation under the permissions of the invoking user.

Attack Path

  1. A user trusts SKILL.md and runs npm install -g agent-chat.
  2. npm resolves the unscoped agent-chat package rather than the declared @wangwuww/agent-chat package.
  3. An unrelated or malicious package is downloaded from the configured npm registry.
  4. Any lifecycle scripts in the resolved package execute during installation, subject to npm configuration.
  5. The installed global executable can subsequently access the user's files, environment variables, credentials, and network resources under the user's privileges.

Exploitation depends on the unscoped package b ...[truncated 820 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace the command with the exact declared package name and a reviewed version, such as:
    bash
    npm install -g @wangwuww/agent-chat@0.0.1
    
  • Verify control of the scoped npm package and ensure the published artifact corresponds to the audited source and commit.
  • Publish provenance and integrity information, and document how users can verify the downloaded artifact.
  • Avoid recommending elevated installation unless it is strictly necessary.
  • Consider documenting npx or a local installation workflow that pins the package version and reduces global exposure.
  • Add a release check that compares installation commands in documentation against the name and version fields in package.json.
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 (17)

Known Vulnerable Dependency: vitest==1.6.1 — 1 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed)

Critical
Category
Supply Chain
Confidence
90% confidence
Finding

Vitest 1.6.1 is reported as allowing arbitrary file read and execution when the Vitest UI server is listening. That is a critical issue because test UI servers are often run by developers with broad local file access, so exploitation could expose sensitive files or execute code in a developer environment.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vitest==1.6.1 — 1 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed)

Critical
Category
Supply Chain
Confidence
94% confidence
Finding

The project includes vitest in a version range associated with a critical advisory allowing arbitrary file read and code execution when the Vitest UI server is listening. Although this is a devDependency, exploitation could compromise developer workstations or CI runners if the vulnerable UI mode is enabled, exposing secrets, source code, or enabling arbitrary command execution.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
80% confidence
Finding

The lockfile includes nanoid 3.3.11, which is flagged for multiple denial-of-service and integer handling issues. Even though this appears to be a transitive development dependency via PostCSS/Vite tooling, malformed or attacker-controlled input in affected code paths could crash or hang processes that consume it.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
84% confidence
Finding

PostCSS 8.5.6 is reported with several advisories including arbitrary file read, incomplete fix issues, and output encoding/XSS concerns. Because this package is used by Vite in the toolchain, the practical risk is mainly in development/build workflows, but if attacker-controlled CSS or sourcemap content is processed, the impact can include file disclosure or unsafe output generation.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: rollup==4.57.1 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Rollup 4.57.1 is flagged for arbitrary file write via path traversal, which is a serious class of issue when build tooling handles attacker-influenced paths or archives. In this skill context it is likely a development dependency rather than runtime code, which reduces exposure somewhat, but compromise of build or developer environments remains plausible.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vite==5.4.21 — 3 advisory(ies): CVE-2026-39365 (Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling); CVE-2026-53571 (vite: `server.fs.deny` bypass on Windows alternate paths); CVE-2026-53632 (launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows)

High
Category
Supply Chain
Confidence
91% confidence
Finding

Vite 5.4.21 has multiple advisories including path traversal and Windows-specific filesystem and UNC path issues. This is particularly relevant because Vite commonly runs local dev servers, so if developers use the skill in a vulnerable environment, local file access or credential leakage risks may be exposed.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The login flow stores the user's Nostr private key (nsec) in plaintext in ~/.agent-chat/config.json, with no warning, no access-control hardening, and no encryption at rest. Anyone with local access to the account, malware, backups, or accidental file exposure can recover the key and fully impersonate the user, decrypt direct messages, and send signed events as that identity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill promotes encrypted messaging and file transfer over public Nostr relays without warning that third-party relays can observe metadata such as sender, recipient routing patterns, timing, relay usage, and possibly retained ciphertext or uploaded content. Users may incorrectly assume end-to-end encryption eliminates all privacy risk, which can lead to unsafe sharing of sensitive information over untrusted public infrastructure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation instructs users to log in with an nsec private key directly on the command line, which risks exposing the secret through shell history, process listings, terminal logging, and screenshots. Because this is authentication material for a messaging identity, compromise of the key could let an attacker impersonate the user and decrypt or send messages as that identity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The send operation publishes events to remote WebSocket relays, which is a network transmission of user-provided message data and metadata. While the command purpose implies messaging, the code does not disclose which external relays are contacted or that message traffic is sent to third-party servers.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The lockfile pins esbuild 0.27.3, which has a disclosed issue affecting the development server on Windows and can allow arbitrary file read in that specific mode. This is a real supply-chain risk, but the impact is limited here because this is a dependency manifest and there is no evidence in this file alone that the vulnerable dev server is exposed or used in production.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.21.5 — 1 advisory(ies): GHSA-67mh-4wv8-2f99 (esbuild enables any website to send any requests to the development server and r)

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The nested esbuild 0.21.5 used under Vite is also associated with a real advisory affecting the development server, allowing unintended requests to reach it. This is a genuine issue, though lower severity in this context because it is part of the dev toolchain and there is no sign in this file of deliberate exploitation logic.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The production dependency uses a caret version range, which permits installation of newer minor and patch releases than were originally reviewed. This increases supply-chain risk because future upstream releases could introduce malicious code, regressions, or newly disclosed vulnerabilities without an explicit update decision by the maintainer.

Content

Scanner excerpt · package.json (reported line 24)May include surrounding context.

json
"keywords": ["nostr", "agent", "chat", "messaging"],
  "license": "MIT",
  "dependencies": {
    "nostr-tools": "^2.7.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The development dependency is unpinned, so builds and local tooling may resolve to newer versions than expected. Even though this package is not shipped at runtime, compromised or breaking dev-tool updates can affect development, testing, or release pipelines.

Content

Scanner excerpt · package.json (reported line 27)May include surrounding context.

json
"nostr-tools": "^2.7.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The tsx development tool is referenced with a caret range, allowing unreviewed upstream updates into the development environment. This creates a low-severity supply-chain exposure because developer machines or CI may execute changed code during builds or local runs.

Content

Scanner excerpt · package.json (reported line 28)May include surrounding context.

json
},
  "devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
80% confidence
Finding

The TypeScript compiler dependency is not pinned to an exact version, so toolchain behavior may change between installs. While primarily a development concern, unexpected compiler changes or a compromised upstream release can still impact build integrity and downstream artifacts.

Content

Scanner excerpt · package.json (reported line 29)May include surrounding context.

json
"devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
84% confidence
Finding

The vitest dependency is specified with a caret range, which allows automatic adoption of newer releases in development and CI environments. This is a low-severity supply-chain issue on its own, though it becomes more concerning here because the same package is also flagged with a critical advisory.

Content

Scanner excerpt · package.json (reported line 30)May include surrounding context.

json
"@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }
}

Static analysis

No suspicious patterns detected.