Back to skill

Security audit

Secure Communicator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed encryption helper, but its security claims materially overstate a weak custom cipher that users are told to trust for sensitive communications.

Review before installing. The skill does not appear to steal data or persist on the system, but it should not be relied on to protect sensitive secrets over insecure channels. Prefer a tool using standard authenticated encryption, and be careful that --output paths may overwrite files and that plaintext passed on the command line may be stored in shell history.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/theijssen-cipher.js:31
Finding

Custom Repeating-XOR Encryption Lacks Cryptographic Authentication

Content
View full analysis

Vulnerability Details

File Location: scripts/theijssen-cipher.js:31-44, scripts/theijssen-cipher.js:128-152
Vulnerability Type: Insecure custom cryptographic construction
Risk Level: High

Vulnerable Code

js
function tripleXOR(data, key) {
    const [key1, key2, key3] = splitKey(key);
    const result = Buffer.alloc(data.length);
    
    for (let i = 0; i < data.length; i++) {
        let byte = data[i];
        byte ^= key1[i % key1.length];
        byte ^= key2[i % key2.length];
        byte ^= key3[i % key3.length];
        result[i] = byte;
    }
    
    return result;
}
js
function encryptWithKey(data, keyFile) {
    const key = fs.readFileSync(keyFile);
    
    // Create metadata
    const metadata = JSON.stringify({
        filename: 'data.bin',
        mimeType: 'application/octet-stream',
        timestamp: Date.now()
    });
    const metadataBuffer = Buffer.from(metadata, 'utf8');
    
    // Stage 1: Encrypt payload
    const encryptedPayload = tripleXOR(data, key);
    
    // Stage 2: Encrypt metadata
    const encryptedMetadata = tripleXOR(metadataBuffer, key);
    
    // Stage 3: Combine and encrypt package
    const payloadLength = Buffer.from(encryptedPayload.length.toString().padStart(10, '0'), 'utf8');
    const packageData = Buffer.concat([
        payloadLength,
        encryptedPayload,
        encryptedMetadata
    ]);
    const encryptedPackage = tripleXOR(packageData, key);
    
    return APP_VERSION + ':' + encryptedPackage.toString('base64');
}

Technical Analysis

The implementation uses a custom repeating-XOR construction instead of a reviewed authenticated-encryption algorithm. Applying XOR three times does not create three independent cryptographic layers: it is algebraically equivalent to XOR with a single combined repeating keystream.

The same key file is reused for the pay ...[truncated 2656 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace tripleXOR with a reviewed authenticated-encryption algorithm:
    • AES-256-GCM; or
    • XChaCha20-Poly1305.
  2. Generate a fresh cryptographically random nonce for every encrypted message. Store the nonce alongside the ciphertext; it does not need to be secret.
  3. Authenticate all metadata as either encrypted content or additional authenticated data.
  4. Derive a fixed-size encryption key from the key file using a reviewed KDF. Use HKDF when the key file already contains high-entropy random bytes, or a password-hardening KDF such as Argon2id or scrypt when accepting passwords.
  5. Define a versioned binary envelope containing the algorithm identifier, KDF parameters, salt where applicable, nonce, ciphertext, and authentication tag.
  6. Reject decryption before returning or writing any plaintext when authentication-tag verification fails.
  7. Add tests covering ciphertext modification, incorrect keys, nonce uniqueness, truncated input, malformed envelopes, and cross-message key reuse.
  8. Update SKILL.md to stop describing the current XOR construction as suitable for sensitive communication. Clearly mark legacy XOR data as unauthenticated and provide a migration path to a new format version.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/theijssen-cipher.js:21
Finding

Incorrect Key Splitting Disables the Third XOR Component

Content
View full analysis

Vulnerability Details

File Location: scripts/theijssen-cipher.js:21-27
Vulnerability Type: Cryptographic implementation error
Risk Level: Medium

Vulnerable Code

js
function splitKey(key) {
    const partSize = Math.floor(key.length / 3);
    return [
        key.slice(0, partSize),
        key.slice(partSize, partSize * 2),
        key.slice(partSize * 3)
    ];
}

Technical Analysis

The third key component begins at partSize * 3, but it should begin at partSize * 2. Bytes between offsets partSize * 2 and partSize * 3 are therefore omitted.

When the key length is divisible by three, partSize * 3 equals the key length and key.slice(partSize * 3) returns an empty buffer. The subsequent expression is then evaluated with an empty key:

js
byte ^= key3[i % key3.length];

Here, key3.length is zero, i % 0 produces NaN, and indexing the buffer returns undefined. JavaScript bitwise coercion converts that value to zero, so the third XOR operation has no cryptographic effect.

If the key length is not divisible by three, the third component contains only the one- or two-byte remainder. This creates an extremely short repeating component rather than the documented third of the key. In both cases, a substantial portion of the supplied key file is ignored.

Attack Path

  1. A user generates or supplies a key whose byte length is divisible by three. The documented default of 1500 KB produces 1,536,000 bytes, which is divisible by three.
  2. splitKey creates two key portions of equal length and an empty third portion.
  3. Every call to tripleXOR silently performs only the first two effective XOR operations.
  4. An attacker analyzing captured ciphertext can disregard the advertised third key component and target the reduced repeating-XOR construction.
  5. Users may incorrectly assess the strength of the scheme based on the full key-file size and the claimed t ...[truncated 664 chars]
Remediation
View remediation

Remediation Suggestions

The preferred remediation is to remove this custom XOR construction and migrate to authenticated encryption.

If the function must temporarily remain for legacy-format compatibility:

  1. Correct the third slice:
    js
    function splitKey(key) {
        if (!Buffer.isBuffer(key) || key.length < 3) {
            throw new Error('Key must contain at least three bytes');
        }
    
        const partSize = Math.floor(key.length / 3);
        return [
            key.slice(0, partSize),
            key.slice(partSize, partSize * 2),
            key.slice(partSize * 2)
        ];
    }
    
  2. Explicitly reject empty key components before performing modulo operations.
  3. Add unit tests for key lengths divisible by three and key lengths with remainders of one and two.
  4. Add compatibility test vectors that verify exact encryption and decryption behavior.
  5. Version any incompatible correction so existing ciphertext is not silently interpreted using a different algorithm.
  6. Treat this correction only as a legacy compatibility fix; it does not resolve the fundamental weaknesses of repeating XOR or the absence of authentication.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill makes strong 'secure communication' claims while describing a custom triple-XOR scheme that is not a modern, authenticated cryptographic design. In this context, users are explicitly encouraged to protect sensitive data over insecure channels, so overstating security can cause users to rely on weak protection and expose confidential data; the finding is even more dangerous if the implementation also embeds decryption material in output as noted by static analysis.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The helper encrypt/decrypt functions contradict the skill’s advertised security model by generating per-message keys, embedding those keys directly in the package, and ignoring the user-supplied key file entirely. If these functions are used by other code or future refactors, encrypted data is effectively recoverable by anyone with the ciphertext, creating a severe confidentiality failure under a misleading 'secure communicator' label.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The active CLI path does not implement the advertised 'triple-layer XOR encryption algorithm' in any meaningful security sense; it repeatedly XORs with the same key, which algebraically collapses to a single XOR operation. This mismatch is dangerous because users are induced to trust a stronger, bespoke 'triple-layer' design for protecting sensitive messages over insecure channels when the actual protection is much weaker and nonstandard.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill encourages users to transmit sensitive information over insecure channels as though encryption alone solves the problem, but it does not clearly warn about metadata exposure, integrity/authentication gaps, key-exchange risks, or endpoint compromise. Given the stated use case, this omission can mislead users into unsafe operational practices and overconfidence in protection provided by the tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented commands write encrypted, decrypted, and generated key material to user-specified output paths without warning about overwriting files, insecure locations, shell history leakage, or leaving sensitive plaintext/key files on disk. In a tool intended for handling secrets, omission of these operational safety warnings increases the chance of accidental disclosure or destruction of sensitive data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Decrypted data is written directly to a user-supplied path with no overwrite protection, path validation, or confirmation. In an agent or automated workflow, a crafted output path could clobber arbitrary local files, causing data loss or replacing sensitive files with attacker-controlled plaintext.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code performs file writes for generated keys and encrypted/decrypted output via fs.writeFileSync. Although the writes are intentional CLI functionality, there is no explicit warning in the usage text or surrounding comments that these operations will create or overwrite files, so user disclosure is minimal.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.