Back to skill

Security audit

Nadmail

Security checks for vulnerabilities and agentic risk

Overview

NadMail is a coherent email-and-wallet skill, but it needs Review because it handles wallet secrets and financial actions with some weak safeguards.

Install only if you are comfortable giving this skill access to a NadMail wallet identity, storing a NadMail auth token locally, and sending email/inbox data to api.nadmail.ai. Use a dedicated low-balance wallet, do not rely on the local emo-buy cap as a hard financial limit, avoid entering wallet passwords in recorded/shared terminals, and update dependencies before serious use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/register.js:84
Finding

Wallet path validation can escape the user's home directory

Content
View full analysis
MAX_WALLET_FILE_SIZE) { console.error(`Security: Wallet file too large (${stat.size} bytes, max ${MAX_WALLET_FILE_SIZE})`); process.exit(1); } if (!stat.isFile()) { console.error('Security: Path must point to a regular file'); process.exit(1); } } catch (e) { // File doesn't exist — let the caller handle it } return resolved; } ``` The validated path is subsequently read as a private key: ```javascript const walletArg = getArg('--wallet'); if (walletArg) { const walletPath = validateWalletPath(walletArg.replace(/^~/, process.env.HOME)); if (fs.existsSync(walletPath)) { console.log(`Using wallet file: ${walletPath}`); const key = fs.readFileSync(walletPath, 'utf8').trim(); ``` ### Technical Analysis The containment check uses: ```javascript resolved.startsWith(home) ``` String-prefix comparison does not establish that one filesystem path is a child of another. For example, if `$HOME` is `/home/alice`, a path such as `/home/alice-backup/key` begins with the same string and passes the check even though it is outside `/home/alice`. The implem ...[truncated 1766 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.js:34
Finding

Wallet encryption passwords are entered with terminal echo enabled

Content
View full analysis
{ rl.question(question, answer => { rl.close(); resolve(answer.trim()); }); }); } ``` It uses that prompt for both password entry and confirmation: ```javascript let password; while (true) { password = await prompt('\nSet encryption password (min 8 chars, must include letter + number): '); const validation = validatePassword(password); if (validation.valid) break; console.error('Invalid password:'); validation.errors.forEach(e => console.error(` - ${e}`)); } const confirmPwd = await prompt('Confirm password: '); ``` The registration script uses the same echoing prompt implementation: ```javascript function prompt(question) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); return new Promise(resolve => { rl.question(question, answer => { rl.close(); resolve(answer.trim()); }); }); } ``` It then requests the decryption password through that prompt: ```javascript const password = process.env.NADMAIL_PASSWORD || await prompt('Enter wallet password: '); ``` ### Technical Analysis Node.js `readline.question()` echoes typed input to the configured output stream by default. The code does not replace the terminal output handler, disable echo, or use a dedicated secret-input library. As a result, encryption and decryption passwords are visibly displayed while entered. This undermines protection of the AES-256-GCM-encrypted private key because possession of both `~/.nadmail/private ...[truncated 1419 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send.js:74
Finding

Daily financial spending limit is mutable and vulnerable to concurrent bypass

Content
View full analysis
EMO_DAILY_CAP) { return { allowed: false, spent_today: tracker.total, remaining: Math.max(0, EMO_DAILY_CAP - tracker.total), cap: EMO_DAILY_CAP, }; } return { allowed: true, spent_today: tracker.total, remaining: EMO_DAILY_CAP - tracker.total, cap: EMO_DAILY_CAP, }; } ``` Spending is recorded through a separate read-modify-write operation: ```javascript function recordEmoSpend(emoAmount) { const today = new Date().toISOString().slice(0, 10); let tracker = { date: today, total: 0 }; try { if (fs.existsSync(EMO_TRACKER_FILE)) { tracker = JSON.parse(fs.readFileSync(EMO_TRACKER_FILE, 'utf8')); if (tracker.date !== today) { tracker = { date: today, total: 0 }; } } } catch { tracker = { date: today, total: 0 }; } tracker.total += emoAmount; fs.writeFileSync(EMO_TRACKER_FILE, JSON.stringify(tracker, null, 2), { mode: 0o600 }); } ``` The transaction is checke ...[truncated 3027 chars]
Remediation
View remediation
0 ? configuredCap : DEFAULT_EMO_DAILY_CAP; ``` 7. Include both the standard micro-buy and optional emo-buy in displayed and authoritative spending controls if the cap is intended to represent total financial exposure. 8. Reconcile local records against server-side transaction history after timeouts or malformed responses. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (36)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description centers on NadMail as an email platform with registration, email sending, and investment-related messaging features. This code chunk instead performs wallet provisioning and secure local key management. While a wallet may be a supporting prerequisite for a Monad/crypto-based service, the actual behavior here is materially different from the declared end-user purpose: it creates and encrypts a wallet, stores files in ~/.nadmail, cleans up legacy sensitive files, prints a mnemonic, and logs audit entries. Those are significant operational capabilities not reflected in the declared description, and the advertised email/micro-investing features are absent from the code shown.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/register.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/send.js "friend@nadmail.ai" "Hello!" "Nice to meet you"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/send.js "friend@nadmail.ai" "Hello!" "Nice to meet you"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/send.js "friend@nadmail.ai" "Hello!" "Nice to meet you"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/send.js "friend@nadmail.ai" "Hello!" "Nice to meet you"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/send.js "friend@nadmail.ai" "Hello!" "Nice to meet you"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `audit.js` | View audit log | No |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `audit.js` | View audit log | No |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `audit.js` | View audit log | No |

Known Vulnerable Dependency: ws==8.17.1 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
97% confidence
Finding

The lockfile pins ws to version 8.17.1, and the supplied advisory data indicates this version is affected by an uninitialized memory disclosure and a memory-exhaustion denial-of-service issue. Even though ws is an indirect dependency via ethers, it can still be reachable anywhere the skill uses websocket-based blockchain connections, which is plausible for a Monad/email-on-chain integration.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill documentation describes use of environment variables, local credential files, and remote API calls, but it does not declare any tool scope such as permissions or allowed-tools. For an agent skill, undeclared access to env and network increases the risk that a caller grants broader capabilities than expected, especially because the skill handles wallet secrets and bearer tokens.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The skill instructs agents to transmit authentication tokens and blockchain transaction hashes to an external API. Any skill that sends sensitive identifiers off-host creates exposure to token theft, account misuse, metadata leakage, or interaction with an untrusted service if the endpoint or transport assumptions are wrong.

Content

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

  1. Submit the transaction hash:
    bash
    curl -X POST https://api.nadmail.ai/api/credits/buy \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"tx_hash": "0xYOUR_TX_HASH"}'
    

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The skill instructs agents to transmit authentication tokens and blockchain transaction hashes to an external API. Any skill that sends sensitive identifiers off-host creates exposure to token theft, account misuse, metadata leakage, or interaction with an untrusted service if the endpoint or transport assumptions are wrong.

Content

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

  1. Submit the transaction hash:
    bash
    curl -X POST https://api.nadmail.ai/api/credits/buy \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"tx_hash": "0xYOUR_TX_HASH"}'
    

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The documented balance-check request sends a bearer token to an external API, which means the skill depends on remote service trust and proper token handling. In an agent setting, this can leak credentials through process history, logs, or overly broad network permissions if not tightly controlled.

Content

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

Check Balance

bash
curl https://api.nadmail.ai/api/credits \
  -H "Authorization: Bearer YOUR_TOKEN"

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

text
~/.nadmail/
├── private-key.enc   # Encrypted private key (AES-256-GCM, chmod 600)
├── wallet.json       # Wallet info (public address only)
├── token.json        # Auth token (chmod 600)
├── emo-daily.json    # Daily emo-buy spending tracker (chmod 600)

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

text
~/.nadmail/
├── private-key.enc   # Encrypted private key (AES-256-GCM, chmod 600)
├── wallet.json       # Wallet info (public address only)
├── token.json        # Auth token (chmod 600)
├── emo-daily.json    # Daily emo-buy spending tracker (chmod 600)

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

text
~/.nadmail/
├── private-key.enc   # Encrypted private key (AES-256-GCM, chmod 600)
├── wallet.json       # Wallet info (public address only)
├── token.json        # Auth token (chmod 600)
├── emo-daily.json    # Daily emo-buy spending tracker (chmod 600)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 308)May include surrounding context.

md
- Website: https://nadmail.ai
- API: https://api.nadmail.ai
- API Docs: https://api.nadmail.ai/api/docs

---

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code sends an authorization token to a remote API to retrieve inbox contents, which necessarily involves transmitting sensitive mailbox data. While the file has a basic usage comment, it does not explicitly warn users that running the script contacts a remote service and accesses private email data.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal, suspicious.potential_exfiltration

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/inbox.js:14

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/register.js:22

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/send.js:22

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/register.js:169

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/inbox.js:42

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/send.js:135