Back to skill

Security audit

文件下载服务器

Security checks for vulnerabilities and agentic risk

Overview

This skill does file sharing as advertised, but it can publicly expose files and open firewall ports by default without strong safeguards.

Install only if you are comfortable with a temporary unauthenticated public file server. Use it only on a tightly controlled directory containing non-sensitive files, prefer binding to 127.0.0.1 unless public access is explicitly needed, avoid automatic firewall opening, remove any firewall rules after use, stop daemon processes promptly, and do not use generated pages with untrusted filenames or descriptions.

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

Error
Location
scripts/start_server.py:17
Finding
Unauthenticated directory server listens on all network interfaces<![CDATA[ ## Vulnerability Details **File Location**: `scripts/start_server.py:17-28, 52-65` **Vulnerability Type**: Public unauthenticated file exposure **Risk Level**: High ### Vulnerable Code ```python parser.add_argument("directory", help="要分享的文件目录路径") parser.add_argument("--port", type=int, default=4000, help="服务器端口(默认: 4000)") parser.add_argument("--daemon", action="store_true", help="后台运行") parser.add_argument("--bind", default="0.0.0.0", help="绑定地址(默认: 0.0.0.0)") args = parser.parse_args() # 检查目录是否存在 if not os.path.isdir(args.directory): print(f"❌ 错误:目录不存在: {args.directory}") sys.exit(1) # 切换到目标目录 os.chdir(args.directory) ``` ```python # 显示下载链接 print("\n📥 下载链接:") print(f" 主页: http://{args.bind}:{args.port}/") print(f" (如果从外部访问,请使用服务器公网IP)") print("="*60) # 构建命令 cmd = [ sys.executable, "-m", "http.server", str(args.port), "--bind", args.bind ] ``` ### Technical Analysis The server uses Python's built-in `http.server` module to expose the selected directory. It binds to `0.0.0.0` by default, making it reachable through every network interface, and it implements no authentication, authorization, expiring links, source-address restrictions, or file allowlist. The only path validation verifies that the supplied path is a directory. It does not reject sensitive locations such as a home directory, workspace root, source repository, configuration directory, or filesystem root. Python's standard directory server also provides directory listings when no index page is present and serves files recursively beneath the selected root. Although public file sharing is the declared purpose of the Skill, public exposure is enabled by default rather than through an explicit opt-in. This violates least-privilege principles and makes an operator path-selection error immediately network-accessible. ### Attack Path 1. An operator invokes the Skill with a directory containing both intended downloads and sensitive files, or mistakenly selects ...[truncated 1029 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the default bind address to `127.0.0.1`. 2. Require an explicit option such as `--public` before permitting a non-loopback bind address. 3. Display the resolved directory and require interactive confirmation before public exposure. 4. Reject dangerous sharing roots by default, including `/`, user home directories, workspace roots, and known credential or configuration directories. 5. Copy explicitly selected files into a newly created, restricted staging directory instead of serving an arbitrary existing directory tree. 6. Disable directory listings and expose only an allowlist of intended files. 7. Add authentication or cryptographically random, short-lived download tokens. 8. Support expiration and automatic server shutdown after a configured time or download count. 9. Run the server under a dedicated unprivileged account with access only to staged files. 10. Log access without recording credentials or sensitive query parameters. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/open_port.py:13
Finding
Unrestricted firewall ACCEPT rules are inserted without lifecycle cleanup<![CDATA[ ## Vulnerability Details **File Location**: `scripts/open_port.py:13-35`; also present in `scripts/start_server.py:38-47` **Vulnerability Type**: Unsafe firewall modification **Risk Level**: High ### Vulnerable Code From `scripts/open_port.py`: ```python parser = argparse.ArgumentParser(description="开放防火墙端口") parser.add_argument("ports", nargs="+", type=int, help="要开放的端口列表") args = parser.parse_args() print("="*60) print("🔓 开放防火墙端口...") print("="*60) success_count = 0 for port in args.ports: try: result = subprocess.run( ["iptables", "-I", "INPUT", "-p", "tcp", "--dport", str(port), "-j", "ACCEPT"], capture_output=True, text=True ) if result.returncode == 0: print(f"✅ 端口 {port} 已开放") success_count += 1 else: print(f"❌ 端口 {port} 开放失败: {result.stderr}") except Exception as e: print(f"❌ 端口 {port} 开放失败: {e}") ``` The server startup script independently performs the same modification: ```python # 尝试开放防火墙端口 try: result = subprocess.run( ["iptables", "-I", "INPUT", "-p", "tcp", "--dport", str(args.port), "-j", "ACCEPT"], capture_output=True, text=True ) if result.returncode == 0: print(f"✅ 防火墙端口 {args.port} 已开放") else: print(f"⚠️ 无法自动开放防火墙端口,请手动配置") except Exception as e: print(f"⚠️ 防火墙配置失败: {e}") ``` ### Technical Analysis Both scripts insert an `iptables` rule at the beginning of the `INPUT` chain that accepts TCP traffic to the selected port from every source address. The operation has the following security deficiencies: - No source network or address restriction is applied. - No explicit operator confirmation is required. - No validation restricts ports to the valid range of `1` through `65535`. - Existing equivalent rules are not detected, so repeated runs can create duplicate rules. - Rules created by the Skill are not tagged or tracked. - No shutdown handler or ...[truncated 1620 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not modify the host firewall automatically during ordinary server startup. 2. Require a separate, explicit administrative action and clear confirmation before changing firewall policy. 3. Validate every port as an integer in the range `1-65535`. 4. Restrict accepted traffic to a caller-specified trusted source IP or network rather than all sources. 5. Check for an equivalent rule before insertion to prevent duplicates. 6. Add an identifiable comment to every managed rule, for example with the `iptables` comment module. 7. Record the exact rule created and remove only that rule when the server stops. 8. Install signal and exception handlers so cleanup runs for normal termination, `SIGINT`, and `SIGTERM`. 9. Provide a cleanup command for daemon mode and maintain a PID/state file with restrictive permissions. 10. Before opening a port, verify which process is listening and refuse to expose an unrelated service. 11. Prefer application-level authentication and infrastructure-managed firewall rules over ad hoc host-wide changes. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_index.py:139
Finding
Generated download page permits stored HTML and script injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_index.py:139-189` **Vulnerability Type**: Stored HTML injection and cross-site scripting **Risk Level**: High ### Vulnerable Code For a single file, the description and filename are inserted directly into HTML text and attribute contexts: ```python if os.path.isfile(args.path): # 单个文件 filename = os.path.basename(args.path) file_size = get_file_size(args.path) upload_time = get_upload_time(args.path) description_html = f'<p style="color: #666; margin-top: 0;">{args.description}</p>' if args.description else '' content = f''' <div class="file-info"> <p><strong>文件名:</strong>{filename}</p> <p><strong>大小:</strong>{file_size}</p> <p><strong>上传时间:</strong>{upload_time}</p> </div> <a href="{filename}" class="download-btn" download>⬇️ 点击下载文件</a> ''' ``` For directories, every filename is likewise inserted without HTML escaping or URL encoding: ```python elif os.path.isdir(args.path): # 目录 description_html = f'<p style="color: #666; margin-top: 0;">{args.description}</p>' if args.description else '' # 列出目录中的文件 file_items = [] for item in sorted(os.listdir(args.path)): item_path = os.path.join(args.path, item) if os.path.isfile(item_path) and not item.startswith('.') and item != 'index.html': size = get_file_size(item_path) file_items.append(f''' <div class="file-item"> <a href="{item}" download>{item}</a> <span class="file-size">({size})</span> </div> ''') ``` The title and previously constructed fragments are then written into the final document: ```python # 生成 HTML html = HTML_TEMPLATE.format( title=args.title, description_html=description_html, content=content ) # 写入文件 with open(output_path, 'w', encoding='utf-8') as f: f.write(html) ``` ### Technical Analysis The page generator in ...[truncated 2271 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every value inserted into HTML text with `html.escape(value, quote=True)`. 2. URL-encode link path components with `urllib.parse.quote`, rather than reusing raw filenames in `href` attributes. 3. Use an auto-escaping template engine and keep untrusted values separate from pre-approved markup. 4. Treat titles, descriptions, and filenames as untrusted even when they originate from local command-line input or the filesystem. 5. Normalize and validate generated links to ensure they remain relative to the intended served directory. 6. Consider mapping files to generated safe identifiers instead of exposing original filenames directly in URLs. 7. Add a restrictive Content Security Policy, such as disallowing inline scripts and limiting resource sources to the same origin. This should supplement, not replace, output encoding. 8. Add automated tests using titles, descriptions, and filenames containing quotes, angle brackets, ampersands, event handlers, and URL-reserved characters. 9. Generate output atomically and avoid overwriting an existing `index.html` without explicit confirmation. ]]>
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill claims it can start an HTTP download server, open firewall ports, and provide downloadable links, but the finding indicates the actual implementation does not perform those actions and may only generate static HTML. This mismatch is dangerous because users or downstream agents may rely on nonexistent protections or behaviors, causing accidental data exposure, broken workflows, or unsafe manual workarounds.

Missing User Warnings

High
Confidence
94% confidence
Finding
The skill is explicitly designed to expose local files over HTTP and open firewall ports, but the description does not foreground the privacy and external-network risks at the point of invocation. In this context, that omission is significant because users may unintentionally publish sensitive directories or make a host reachable from untrusted networks.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documents shell commands and Python scripts that read files, write HTML output, and manipulate network exposure, but it declares no explicit tool scope or permissions boundary. In an agent setting, missing scope makes it easier for the skill to be invoked with broader-than-expected capabilities, increasing the chance of unsafe file access or shell execution.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are broad enough to match common requests about downloading or sending files, which can cause the skill to activate in contexts where the user did not intend to expose files over HTTP. In this skill's context, unintended activation is more dangerous because the documented behavior includes network exposure and firewall changes.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The quickstart explicitly instructs users to bind an HTTP file server to 0.0.0.0 and open the firewall with iptables, which exposes files to any reachable host without authentication, encryption, or scope warnings. In the context of a file-sharing skill, this is functional behavior, but the lack of clear cautions about public exposure, sensitive files, and network reachability makes accidental data disclosure reasonably likely.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This code includes user-facing natural-language content that is fixed to Chinese, beginning with the module description and continuing throughout CLI help and generated HTML. The policy allows locale constraints only when they are opt-in or clearly justified, and this file does neither.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The generated HTML displays fixed Chinese UI text such as the service status label, and similar hard-coded Chinese strings appear elsewhere in the page template. Because the file does not offer localization or an explicit justification for a Chinese-only experience, this is a language-policy issue.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The docstring, CLI description, argument help, and user-facing output are written only in Chinese, which imposes a specific language on all users. The file does not offer any language selection or explain that the skill is intended only for a Chinese-speaking or region-specific context.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
success_count = 0
    for port in args.ports:
        try:
            result = subprocess.run(
                ["iptables", "-I", "INPUT", "-p", "tcp", "--dport", str(port), "-j", "ACCEPT"],
                capture_output=True,
                text=True
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code presents its description, CLI help text, and user-facing messages exclusively in Chinese. Under the policy rule, forcing a specific language without offering user choice or documenting a justified locale restriction is a natural-language policy violation.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The skill goes beyond starting a temporary download server and modifies host firewall policy, which requires elevated privileges and changes the system's security posture. In this context, the danger is increased because the server also defaults to binding on 0.0.0.0, so opening the port can expose shared files to the entire reachable network or internet.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# 尝试开放防火墙端口
    try:
        result = subprocess.run(
            ["iptables", "-I", "INPUT", "-p", "tcp", "--dport", str(args.port), "-j", "ACCEPT"],
            capture_output=True,
            text=True
Confidence
96% confidence
Finding
This subprocess call inserts an iptables rule opening the chosen TCP port on the host firewall. Although the command is passed as an argument list rather than a shell string, it still performs a privileged security-sensitive action that broadens network exposure and can unintentionally make the file server reachable from untrusted networks.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if args.daemon:
        print("\n🚀 后台启动服务器...")
        # 后台运行
        process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print("\n🚀 前台启动服务器(按 Ctrl+C 停止)...")
        print("")
        try:
            subprocess.run(cmd)
        except KeyboardInterrupt:
            print("\n\n👋 服务器已停止")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
Natural-language content throughout the file forces a specific language locale for all users without offering an alternative or documenting that the skill is intentionally region- or language-specific. This can violate organizational language-choice policy when users are not given an opt-in or fallback.

Static analysis

No suspicious patterns detected.