Back to skill

Security audit

Network Speed Test

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed command-line network speed tester, with a bounded-looking default but an unbounded custom test-size option users should handle carefully.

Install only if you are comfortable with a skill that sends test traffic to Cloudflare and opens TCP connections to public DNS IPs. Use default or modest --size values, especially on metered or shared networks, because very large custom sizes can consume significant bandwidth and memory.

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
scripts/speed_test.py:72
Finding

Unbounded Test Size Can Cause Memory and Network Resource Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/speed_test.py:72-75, scripts/speed_test.py:226, and scripts/speed_test.py:250-253
Vulnerability Type: Uncontrolled resource consumption
Risk Level: Medium

Vulnerable Code

python
def measure_upload(size_bytes=5_000_000, timeout=30):
    """Measure upload speed using Cloudflare speed test endpoint."""
    data = b"0" * size_bytes
    try:
python
parser.add_argument("--size", type=float, default=10, help="Test file size in MB (default: 10)")
python
if do_download:
    results["download"] = run_download_test(args.size, args.json)

if do_upload:
    results["upload"] = run_upload_test(max(args.size / 2, 1), args.json)

The supplied value is subsequently converted into a byte count without any upper-bound or finite-number validation:

python
size_bytes = int(size_mb * 1_000_000)

Technical Analysis

The --size argument accepts an unrestricted floating-point value. The value controls both the requested download size and the size of the upload body.

For an upload, measure_upload() constructs the entire request body as one in-memory byte string:

python
data = b"0" * size_bytes

A sufficiently large value can therefore cause excessive memory allocation. This allocation occurs before the function's try block, so allocation failures such as MemoryError are not handled by its exception handler.

The same argument controls how much data is requested from the external download endpoint. An excessive value can consume substantial network bandwidth and execution time. Non-finite values such as NaN or infinity may also cause an unhandled failure during integer conversion.

The issue requires control over the program's command-line arguments. It does not independently grant additional system privileges or permit arbitrary code execution.

Attack Path

  1. An attacker or untrusted automation mechanism obtains the ability to influence arguments passed to ` ...[truncated 1239 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define a conservative maximum permitted test size based on expected operational needs.
  2. Reject values that are zero, negative, non-finite, or above the configured maximum.
  3. Implement validation directly in the argument parser so invalid input fails before network or memory operations begin.
  4. Avoid constructing the complete upload payload in memory. Use a bounded streaming or chunked upload mechanism where supported.
  5. Move any unavoidable allocation inside explicit exception handling and report resource failures cleanly.
  6. Consider applying separate limits to download and upload tests because their resource characteristics differ.

Example validation:

python
import math

MAX_TEST_SIZE_MB = 100.0

def valid_size(value):
    try:
        size = float(value)
    except ValueError as exc:
        raise argparse.ArgumentTypeError("size must be a number") from exc

    if not math.isfinite(size):
        raise argparse.ArgumentTypeError("size must be finite")
    if size <= 0 or size > MAX_TEST_SIZE_MB:
        raise argparse.ArgumentTypeError(
            f"size must be greater than 0 and no more than {MAX_TEST_SIZE_MB} MB"
        )
    return size

parser.add_argument(
    "--size",
    type=valid_size,
    default=10.0,
    help=f"Test file size in MB, up to {MAX_TEST_SIZE_MB} (default: 10)",
)

The upload implementation should additionally transmit bounded chunks rather than allocating b"0" * size_bytes as one object.

Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly performs outbound network activity to multiple public endpoints, but the manifest does not declare any explicit tool scope or permissions for that capability. This weakens least-privilege controls and transparency, making it easier for a network-capable skill to be run in environments where users or policy engines cannot clearly assess or restrict its external communications.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.