Back to skill

Security audit

Remnawave Robot

Security checks for vulnerabilities and agentic risk

Overview

This is a real admin account-management tool, but it handles credentials and subscription links unsafely and includes test scripts that can send access information to fixed email addresses.

Install only after review by someone responsible for the Remnawave and mail accounts. Remove or rotate the exposed subscription URLs, remove hard-coded test recipients and automatic test-email sending, stop printing secrets, correct the plaintext credential-storage disclosure, enforce valid TLS certificates, and restrict logs before using this with real users.

Vulnerability Patterns
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • 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 (6)

T04 · Embedded Malicious Code

Error
Location
test-email.js:24
Finding

Hard-Coded Subscription Credential Is Sent to Fixed Email Recipients

Content
View full analysis
{ ``` The repair script invokes this mail-delivery script automatically after SMTP verification: ```bash if [ $? -eq 0 ]; then echo "" echo "✅ SMTP 配置正确!" echo "" echo "📧 测试发送邮件..." node test-email.js ``` ### Technical Analysis The diagnostic workflow embeds a live-looking Remnawave subscription URL directly in an outgoing email and sends it to fixed recipients. Based on the surrounding project behavior, subscription URLs are access-bearing values used to retrieve VPN configuration. They should therefore be handled as secrets. SMTP connectivity can already be checked with `transporter.verify()`. Sending a real message containing an access-bearing URL is unnecessary for the stated repair operation. The recipient and copied recipient are not supplied or confirmed by the operator. ### Attack Path 1. An operator configures valid SMTP credentials through `setup.js`. 2. The operator follows the documented SMTP repair process and runs `fix-zoho-smtp.sh`. 3. The script verifies the SMTP connection. 4. When verification succeeds, the script automatically executes `node test-email.js`. 5. `test-email.js` authenticates with the ...[truncated 698 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
fix-zoho-smtp.sh:11
Finding

SMTP Repair Script Prints the Plaintext Password to the Terminal

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
setup.js:85
Finding

SMTP Password Is Stored in Plaintext Despite an Encryption Claim

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
create-account.js:104
Finding

Administrative API Traffic Supports Disabled TLS Certificate Validation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
create-account.js:328
Finding

Sensitive Subscription URLs and Personal Data Are Written to Weakly Protected Logs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
test-smtp-direct.js:20
Finding

SMTP Diagnostic Script Sends Unsolicited Email to Hard-Coded Recipients

Content
View full analysis
`, to: 'jung@bydfi.com', cc: 'crads@codeforce.tech', subject: `【VPN】账号已创建 - 运维组 Crads`, text: '测试邮件', html: '

测试邮件

账号:jung_pc

' }; console.log('📧 发送邮件...'); const info = await transporter.sendMail(mailOptions); ``` ### Technical Analysis The script is named and presented as an SMTP test, but it performs an actual external email delivery. It uses the operator's configured SMTP credentials and sends to two recipients embedded in source code. The operator cannot select the destination and is not asked to confirm the transmission. A connectivity test should verify authentication and transport availability without sending mail. The current behavior creates an unnecessary external side effect and can be abused to make operators send messages from their own accounts. ### Attack Path 1. An operator configures an SMTP account. 2. The operator runs `test-smtp-direct.js` expecting a connection test. 3. The script loads the stored SMTP credentials. 4. It authenticates to the configured mail server. 5. It sends a real message to the hard-coded primary and copied recipients. 6. The mail provider attributes the message to the operator's account. ### Impact Assessment The behavior can cause unauthorized communications, expose sender identity and operational information, consume SMTP quotas, trigger monitoring alerts, and damage sender reputation. Repeated execution may be treated as abusive or unsolicited mail by the provider or recipients. ]]>
Remediation
View remediation
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (55)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This document includes user-specific account names, email addresses, and live-looking subscription URLs in plaintext without any access-control, redaction, or handling guidance. If the file is accessible to unauthorized users, those links and identifiers could enable account misuse, unauthorized service access, phishing, or privacy violations, especially because the context is operational support for real user accounts.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · create-account.js (reported line 38)May include surrounding context.

js
fs.mkdirSync(logMonthDir, { recursive: true });
}

// 从 .env 读取 Token
function getRemnawaveToken() {
  try {
    const envContent = fs.readFileSync(ENV_FILE, 'utf-8');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · setup.js (reported line 94)May include surrounding context.

js
fs.mkdirSync(logMonthDir, { recursive: true });
}

// 从 .env 读取 Token
function getRemnawaveToken() {
  try {
    const envContent = fs.readFileSync(ENV_FILE, 'utf-8');

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

Referencing ../../.env is a credential-access pattern because it reaches outside the script’s local scope to harvest a bearer token from a shared environment file. In a deletion tool, this is especially sensitive: compromise or misuse of the script yields both credential exposure and an authenticated destructive API capability.

Content

Scanner excerpt · delete-account.js (reported line 15)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');

function getRemnawaveToken() {

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The script is designed to access a credential source (.env) and use the recovered token for authenticated API requests. In a skill environment, direct filesystem secret harvesting is a credential-access behavior that is more dangerous than ordinary configuration loading because it can be repurposed to consume unrelated secrets from shared project roots.

Content

Scanner excerpt · get-squads.js (reported line 15)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');

function getRemnawaveToken() {

Known Vulnerable Dependency: nodemailer==8.0.2 — 10 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2 (Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote den); GHSA-8m3c-c648-2xjj (Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disable) +7 more

High
Category
Supply Chain
Confidence
99% confidence
Finding

The lockfile pins nodemailer to version 8.0.2, and the finding cites multiple published advisories affecting that exact dependency version. Because package-lock.json governs installed artifacts, this is a real supply-chain risk: vulnerable mail parsing/header handling code can expose the application to denial of service, header injection, or security control bypasses if untrusted email fields or content are processed.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: nodemailer==8.0.2 — 10 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2 (Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote den); GHSA-8m3c-c648-2xjj (Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disable) +7 more

High
Category
Supply Chain
Confidence
99% confidence
Finding

The package explicitly depends on nodemailer 8.0.2, which is flagged with multiple known advisories, including header injection, denial-of-service, and file/content access bypass issues. Because this skill appears to automate account management and email workflows, vulnerable email handling is especially relevant and could enable message manipulation, service disruption, or abuse of privileged processing paths.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · add-to-squad.js (reported line 15)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · create-account.js (reported line 24)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · search-account.js (reported line 15)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · setup.js (reported line 17)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · sync-squads.js (reported line 15)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · test-config.js (reported line 16)May include surrounding context.

js
const path = require('path');

const CONFIG_DIR = path.join(__dirname, 'config');
const ENV_FILE = path.join(__dirname, '../../.env');
const REMNAWAVE_CONFIG = path.join(CONFIG_DIR, 'remnawave.json');
const SQUADS_CONFIG = path.join(CONFIG_DIR, 'remnawave-squads.json');

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The report includes direct subscription URLs for specific accounts in clear text, effectively exposing bearer-style access artifacts to anyone who can read, copy, forward, index, or archive the document. Because this is an operational report rather than a secret-management system, the surrounding context makes the exposure more dangerous: reports are commonly shared broadly, retained long-term, and handled with weaker access controls than live credentials.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The primary description and much of the usage documentation are presented in Chinese, with no indication that other languages are supported or that the locale is intentionally restricted. The policy requires avoiding language or locale constraints unless the user is given a choice or the restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The markdown file lists node delete-account.js as a supported command, but provides no warning that deleting an account may be destructive or irreversible. Under the markdown-specific missing-warning rule, skills should disclose behaviors that could affect user data or system integrity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The natural-language content throughout the skill file forces a specific language experience for users, and there is no indication that Chinese is optional or that the skill is intended only for a Chinese-speaking or region-specific audience. This matches the policy category for language or locale constraints without user opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file header documents this script as a utility to add a user to a group, but the implementation also directly reads a parent-directory .env file to extract an API token. With no manifest declaring credential access, this is an additional capability not justified by the stated purpose in the code documentation alone.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script accesses a sensitive credential by reading REMNAWAVE_API_TOKEN from a local .env file. Although the file header describes the usage, it does not warn that the skill will access credentials, and there is no explicit disclosure at runtime about this sensitive operation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script's description, usage guidance, and runtime messages are written in Chinese, and it also formats dates using the zh-CN locale. There is no indication that this is a region-specific tool or that users can opt into another language, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script persistently writes sensitive account data, including email address, UUIDs, and especially the subscription URL, into Markdown log files. Subscription URLs often function as bearer-style secrets for VPN/proxy access, so storing them in logs increases exposure through backup systems, shared disks, or overly broad file permissions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file's natural-language description and usage text are written only in Chinese, indicating a fixed language/locale experience. There is no user opt-in, alternative locale, or documented justification that this skill is intentionally region-specific, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script reads an API bearer token from a parent-directory .env file, giving it access to broader local credentials than its documented CLI purpose alone suggests. In an agent/skill context, this increases the blast radius because a destructive action script can silently couple account deletion with secret access, and pathing outside the skill directory may expose unrelated environment secrets.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · fix-zoho-smtp.sh (reported line 35)May include surrounding context.

sh
echo "✅ 文件权限正确 (600)"
else
    echo "⚠️  文件权限:$PERMS (建议:600)"
    chmod 600 $SMTP_CONFIG
    echo "✅ 已修复权限为 600"
fi

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The header comment says the script queries user squads, but the implementation also fetches and prints the user's UUID and subscription URL. This mismatch is risky because it causes collection and disclosure of additional sensitive identifiers beyond the stated purpose, which can surprise operators and leak account-related data.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.