Back to skill

Security audit

Sensitive Data Masker

Security checks across malware telemetry and agentic risk

Overview

This skill has a legitimate privacy purpose, but it stores restorable secrets and has gaps that can expose data or let masking fail silently.

Review before installing. Verify the hook actually masks a test message, fix the missing cryptography dependency and Python module-name mismatch, avoid sending secrets through command-line arguments, reduce or disable restoration retention where possible, and protect the local mapping database and encryption key like a secrets store.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill declares installation and command execution capabilities such as pip installs and `python3 -m spacy download ...`, but does not declare corresponding permissions. This creates a transparency and consent problem: a user or platform may underestimate the skill's ability to invoke shell commands and modify the local environment during install or operation.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The guide documents storing reversible mappings of sensitive data in a local JSON file for 7 days, which materially expands the attack surface beyond simple masking. If that file is accessed, copied, backed up, or mishandled, all masked secrets can be recovered in plaintext; this is especially concerning because the examples explicitly support later restoration for task execution.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The documentation shows restored secrets being inserted into shell commands and system configuration workflows, which is outside the expected scope of a masking skill and encourages insecure operational use of plaintext credentials. This can leak secrets via shell history, process arguments, logs, crash reports, or inadvertent writes to disk, turning a redaction utility into a secret-handling and execution bridge.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The document explicitly says original sensitive data will be stored encrypted, but the mapping-store example writes raw originals directly to SQLite and caches them in plaintext. In a skill whose purpose is PII masking, this creates a serious confidentiality gap because compromise of the local DB, backups, logs, or process memory exposes the very secrets the skill is supposed to protect.

Intent-Code Divergence

Low
Confidence
96% confidence
Finding
The child process is created with stderr set to 'ignore', but the code later attaches a listener to masker.stderr and relies on the error variable for diagnostics. In practice, masker.stderr will be null, causing the handler to throw when calling .on(...), which is then caught and silently bypasses masking; this creates a fail-open path where sensitive data may remain unredacted.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The file-level documentation promises 'encryption required' and 'no fallback', but the implementation later allows decryption failures to return the stored value unchanged. In a skill explicitly handling sensitive data, this mismatch can cause operators to assume plaintext can never be restored from storage when in fact legacy or malformed plaintext values may still be accepted and exposed.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The decrypt helper contains a plaintext compatibility path: if decryption fails, it returns the input unchanged. Because restored values are later emitted back into messages, any plaintext value in the database—whether from legacy data, manual tampering, or corruption—will be treated as valid sensitive content and disclosed, undermining the stated guarantee of encrypted-at-rest handling.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The code claims encrypted-only storage with no fallback, but EncryptionHelper.decrypt() returns the input unchanged on any decryption failure. That means corrupted, tampered, or plaintext legacy values are silently treated as valid restored secrets, defeating the documented fail-secure behavior and potentially allowing plaintext sensitive data to persist or be accepted unnoticed.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The examples encourage using restored plaintext secrets directly in command-line arguments, which are commonly exposed through shell history, process listings, telemetry, and logs. Because the skill's purpose is to protect sensitive data, showing unsafe handling patterns undermines that protection and may directly lead users to leak credentials during routine operations.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide demonstrates writing restored sensitive data to configuration files without warning about plaintext persistence on disk, backups, and file permission risks. This creates a realistic path for secret exposure because operators may copy the example directly, leaving credentials stored unencrypted in files or captured by system backups and audit tooling.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The design explicitly restores masked secrets before task execution but does not mention user notification, consent, or restrictions on what tools/actions may receive the restored data. In this context, that undermines the privacy guarantee of masking and can lead to unintended disclosure of passwords, tokens, or connection strings to downstream tools, plugins, shells, or logs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The design explicitly restores masked secrets immediately before task execution, which re-exposes sensitive values to downstream components, tools, logs, prompts, and execution environments. Without explicit user consent, scope restriction, or guarantees that only the minimum necessary secret is injected into a trusted sink, the masking layer becomes reversible secret handling rather than true protection.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The README explicitly describes a flow where user content is masked and then sent to an external API, but it does not warn users that their prompts or derived data leave the local environment. Even if secrets are redacted, masked content can still contain sensitive business context, partial identifiers, or imperfectly detected PII, creating a meaningful privacy and data-handling risk.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README explicitly describes a workflow where masked user content is sent to an API while token-to-original-value restoration mappings are stored locally for 7 days, but it does not clearly warn users about privacy implications, retention behavior, or the risk that local restoration data remains sensitive. Even if the API only receives masked text, the local mapping database can re-identify secrets and PII, so undocumented retention can mislead users into enabling a feature that materially affects data handling.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill documentation presents the masking flow as 'Safe' while also stating that original sensitive data is stored locally for 7 days and restored before task execution. That behavior materially changes the trust model: secrets are not merely redacted transiently, but persist in recoverable form, which increases exposure from local compromise, misconfiguration, backups, logs, or unintended reuse.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The configuration example sets encrypt_storage to false for a database containing reversible mappings of secrets, passwords, tokens, and other PII, without any warning. Even if storage is local, plaintext persistence makes compromise of the host, filesystem access, backups, or developer support artifacts much more likely to expose original sensitive values.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill masks data for upstream API use, but it also stores the original sensitive values in a reversible local SQLite mapping for 7 days and restores them before task execution. That means secrets are not merely redacted but retained in recoverable form, materially increasing exposure if the host is compromised, backups are accessed, logs leak paths, or another local component reads the database.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The command trigger `clear` is highly generic and can be invoked accidentally or collide with common user intent, especially in agent environments where short natural-language commands may be matched loosely. In a skill that manages local SQLite mappings and sensitive-data restoration state, an ambiguous destructive command increases the risk of unintended data deletion or state reset.

Vague Triggers

Medium
Confidence
83% confidence
Finding
The command `cleanup` is vague and does not clearly communicate whether it removes temporary cache, database records, logs, or restoration mappings. Because this skill stores sensitive-data mappings locally, an underspecified maintenance command can lead to accidental deletion, unintended retention changes, or misuse by an agent/user who misunderstands its scope.

VirusTotal

66/66 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
handler.en.js:32

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
handler.js:32

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
CHANNEL-MASKER-GUIDE.md:38