Back to skill

Security audit

Checksum

Security checks for vulnerabilities and agentic risk

Overview

This checksum skill is mostly a normal local utility, but its docs overstate verification support and its recursive directory mode can read outside the selected folder through symlinks.

Review before installing. Use it for generating local hashes only, not for automated integrity verification, because checksum-file verification is not implemented. Avoid running recursive mode on untrusted directories or directories that may contain symlinks, and prefer sha256 or sha512 over the default md5 for security-sensitive integrity checks.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:30
Finding
Recursive Directory Hashing Follows Symbolic Links Outside the Requested Root<![CDATA[ ## Vulnerability Details **File Location**: `index.js:30-47` **Vulnerability Type**: Symbolic-link traversal and uncontrolled recursive traversal **Risk Level**: Medium ### Vulnerable Code ```js const results = {}; async function scan(currentDir) { const list = fs.readdirSync(currentDir); // Sort to ensure deterministic order if we were hashing the dir itself (future) list.sort(); for (const file of list) { if (file === '.git' || file === 'node_modules') continue; const fullPath = path.join(currentDir, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { if (recursive) await scan(fullPath); } else { const hash = await hashFile(fullPath, algo); // Store relative path const relativePath = path.relative(dirPath, fullPath); results[relativePath] = hash; } } } ``` ### Technical Analysis The recursive scanner uses `fs.statSync()` to determine whether each entry is a directory. Unlike `fs.lstatSync()`, `fs.statSync()` follows symbolic links and returns information about the link's target. Consequently, a symbolic link located beneath the user-selected directory can point to a directory outside that root. The scanner then recursively processes the external directory without checking its canonical path against the canonical path of the requested root. The implementation also does not maintain a set of previously visited directories. A symbolic link that points to an ancestor directory or otherwise creates a cycle can therefore cause repeated recursive traversal until an operating-system limit or another runtime failure is reached. Exploitation requires an attacker to create or influence entries in a directory that the user later scans. The vulnerable code does not grant new operating-system privileges: access remains limited to files readable by the Node.js process. ### Attack Path 1. An attacker gains the abili ...[truncated 1694 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Inspect directory entries with `fs.lstatSync()` or `fs.readdirSync(currentDir, { withFileTypes: true })` so symbolic links can be identified without following them. 2. Skip symbolic links by default when recursively hashing a directory. 3. If following symbolic links is an intentional feature: - Resolve the requested root once with `fs.realpathSync()`. - Resolve each candidate target with `fs.realpathSync()`. - Use `path.relative()` to verify that the resolved target remains beneath the resolved root. - Reject a target when the relative result is `..`, begins with `..${path.sep}`, or is absolute. 4. Maintain a visited-directory set using canonical paths or filesystem device/inode identities to prevent recursive cycles. 5. Handle race conditions between inspection and access. Where practical, use descriptor-based operations and avoid relying exclusively on separate check-then-use filesystem calls. 6. Add regression tests covering: - A symlink to a directory outside the selected root; - A symlink to a file outside the selected root; - A symlink to the selected directory itself; - A symlink to an ancestor directory; and - Multiple links forming a cycle. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill’s manifest and documentation overstate security-relevant capabilities by claiming checksum verification support while the feature is only planned, and they inconsistently describe supported algorithms. In a security utility, this can mislead users into trusting integrity-validation workflows that are not actually implemented, causing false assurance and potential acceptance of tampered files.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes a utility for generating and verifying checksums from a file, but the code only computes hashes for a file or directory and prints them. The only reference to verification is a '--verify' argument marked as a placeholder, with no verification logic implemented anywhere.

Description-Behavior Mismatch

Low
Confidence
88% confidence
Finding
The documentation presents the skill as suitable for verifying downloads and file integrity, but also states verification is only planned. For a checksum tool, this discrepancy can cause operators or downstream agents to assume integrity checks exist when they do not, leading to skipped validation and unsafe trust decisions.

Intent-Code Divergence

Low
Confidence
80% confidence
Finding
The SKILL.md documentation contradicts itself about supported algorithms. The features section claims support for sha512, but the command usage sections only advertise md5, sha1, and sha256, creating ambiguity about actual behavior and intended scope.

Description-Behavior Mismatch

Low
Confidence
93% confidence
Finding
The manifest explicitly states support for MD5, SHA1, and SHA256 only, while the code's allowed algorithm list includes 'sha512'. This is a direct description-behavior mismatch because the implementation exposes broader capability than the manifest advertises.