Back to skill

Security audit

flutter-schema

Security checks for vulnerabilities and agentic risk

Overview

This Flutter scaffolding skill is mostly coherent, but its generator can be tricked into writing new files outside the intended project folder through symlinks.

Review before installing if you plan to use the scaffold generator. The architecture guidance itself is low risk, but run scripts/validate.py only in trusted Flutter repositories and avoid target directories containing symlinks until the path containment check is hardened with realpath/lstat-style validation and no-follow file creation.

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/validate.py:151
Finding
Symbolic-Link Path Escape in GetX Page Generator<![CDATA[ ## Vulnerability Details **File Location**: `scripts/validate.py:151-184` **Vulnerability Type**: Symbolic-link path traversal / arbitrary file creation outside the intended directory **Risk Level**: Medium ### Vulnerable Code ```python # 计算目标目录的绝对路径,并限制在 lib 目录内 if target_dir is None: abs_target_dir = os.path.join(lib_root, "modules", name) else: # 允许绝对路径或相对项目根目录的路径 if os.path.isabs(target_dir): abs_target_dir = os.path.normpath(target_dir) else: abs_target_dir = os.path.normpath( os.path.join(project_root, target_dir) ) # 防止路径穿越:强制要求在 lib 目录下 common_prefix = os.path.commonpath([lib_root, abs_target_dir]) if common_prefix != os.path.abspath(lib_root): raise ValueError( f"目标目录不安全或超出 lib 目录范围: {target_dir!r} " f"(解析为: {abs_target_dir})" ) page_dir = os.path.join(abs_target_dir, name) # 计算用于 package import 的相对路径(相对于 lib 根目录) package_path = os.path.relpath(page_dir, lib_root).replace(os.sep, "/") os.makedirs(page_dir, exist_ok=True) files = { f"{name}_binding.dart": generate_binding(name, pascal_name, package_path), f"{name}_state.dart": generate_state(pascal_name), f"{name}_logic.dart": generate_logic(name, pascal_name), f"{name}_view.dart": generate_view(name, pascal_name), } created_files = [] for filename, content in files.items(): file_path = os.path.join(page_dir, filename) if os.path.exists(file_path): print(f"⚠️ 文件已存在,跳过: {file_path}") continue with open(file_path, 'w', encoding='utf-8') as f: f.write(content) ``` ### Technical Analysis The script claims to restrict generated files to the Flutter project's `lib` directory. However, it uses `os.path.normpath()` and `os.path.commonpath()` to perform only a lexical containment check. These functions normalize path text but do not resolve symbolic links. Consequently, a path can appear to reside under `lib` while a symbolic-link component redirects filesystem ope ...[truncated 2375 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve canonical paths before checking containment: ```python lib_root = os.path.realpath(os.path.join(project_root, "lib")) resolved_target = os.path.realpath(abs_target_dir) resolved_page = os.path.realpath(os.path.join(resolved_target, name)) if os.path.commonpath([lib_root, resolved_target]) != lib_root: raise ValueError("Target directory is outside lib") if os.path.commonpath([lib_root, resolved_page]) != lib_root: raise ValueError("Page directory is outside lib") ``` 2. Explicitly reject symbolic links in every existing path component between `lib_root` and `page_dir`, using `os.lstat()` rather than APIs that follow links. 3. Revalidate the canonical `page_dir` after directory creation. This reduces the chance that path state changes between initial validation and file creation. 4. Create output files atomically and refuse to follow symlinks. On supported platforms, use descriptor-relative operations with `os.open()` and flags such as: ```python os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW ``` 5. Avoid the `exists()` followed by `open()` check-then-use sequence. Atomic exclusive creation prevents replacement races and preserves the existing behavior of not overwriting files. 6. Add automated tests covering: - A symlink used as `target_dir`. - A symlink used as the final `page_dir`. - Nested symlink components. - A concurrent path replacement attempt. - Valid in-tree destinations to ensure normal scaffolding remains functional. ]]>
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 (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The manifest description and main heading are written entirely in Chinese, and the file provides no indication that other languages are supported or that Chinese is required for a region-specific purpose. This creates a natural-language locale constraint without user opt-in, which matches the policy-violation category.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
Line L151 states '避免拼音', which is a natural-language constraint on language usage in identifiers. The file does not present this as an optional convention or provide user choice or a documented compliance reason, so it fits the locale/language policy concern.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This code file contains user-facing natural language in Chinese, including the module description and usage notes, which effectively imposes a language/locale on users. The policy allows locale constraints only when they are optional or clearly justified, and neither is present here.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The script prints status, success, and error messages in Chinese, which can force a specific language experience on users. There is no option to switch languages and no justification that this tool is region-specific.

Static analysis

No suspicious patterns detected.