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## 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
## 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## 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 ``` ``` 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
## 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.

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.

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.

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.

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.

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.

Missing User Warnings

High
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.

Missing User Warnings

Medium
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.

Missing User Warnings

Medium
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.

Missing User Warnings

Medium
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.

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.

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.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"keywords": ["nostr", "agent", "chat", "messaging"],
  "license": "MIT",
  "dependencies": {
    "nostr-tools": "^2.7.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
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.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"nostr-tools": "^2.7.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
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.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }
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.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"devDependencies": {
    "@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }
}
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.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"@types/node": "^20.0.0",
    "tsx": "^4.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  }
}
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.

Static analysis

No suspicious patterns detected.