T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/list_openapi_meta_apis.py:33
- Finding
- Unvalidated API Identifiers Permit Output Path Traversal## Vulnerability Details **File Location**: `scripts/list_openapi_meta_apis.py:33-34, 62-69` **Vulnerability Type**: Path traversal and unintended file overwrite **Risk Level**: Medium ```python parser.add_argument("--product-code", default=DEFAULT_PRODUCT_CODE) parser.add_argument("--version", default=DEFAULT_VERSION) ``` ```python json_file = output_dir / f"{args.product_code}_{args.version}_api_docs.json" md_file = output_dir / f"{args.product_code}_{args.version}_api_list.md" json_file.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") md_lines = [ f"# {args.product_code} {args.version} API List", "", f"- Source: {url}", f"- API count: {len(api_names)}", "", ] md_lines.extend([f"- `{name}`" for name in api_names]) md_file.write_text("\n".join(md_lines) + "\n", encoding="utf-8") ``` ### Technical Analysis The command-line values `product-code` and `version` are incorporated directly into output filenames without validating or removing path separators, traversal components, or platform-specific path syntax. `pathlib.Path` joins these attacker-controlled values to `output_dir`, but it does not guarantee that the resulting paths remain inside that directory. An input containing components such as `../` can therefore cause the generated JSON and Markdown paths to resolve outside `output/alicloud-ai-content-aicontent/`. The writes use `Path.write_text()`, which overwrites an existing destination rather than requiring exclusive creation. Exploitation is constrained by several factors: the remote metadata request must first return a JSON response, the target parent directory must exist, generated filenames retain fixed suffixes, and the process can write only to locations allowed by its operating-system permissions. ### Attack Path 1. An attacker or untrusted caller invokes the script with a traversal-bearing `--product-code` or `--version` value. 2. The ...[truncated 1325 chars]
- Remediation
- ## Remediation Suggestions 1. Validate `product-code` and `version` against a strict allowlist before constructing either the URL or output filenames. For example, permit only ASCII letters, digits, underscores, and hyphens. 2. Reject empty values, `.` and `..` components, path separators, encoded separators, control characters, and absolute-path syntax. 3. Resolve each destination and verify that it remains beneath the resolved output directory before writing. 4. If overwriting is unnecessary, create output files exclusively to prevent accidental replacement of existing artifacts. 5. Consider mapping user-visible identifiers to locally generated safe filenames rather than using raw command-line values. 6. Add tests covering `../`, absolute paths, nested separators, Windows path syntax, malformed identifiers, and symlinked output paths. Example hardening approach: ```python import re SAFE_IDENTIFIER = re.compile(r"^[A-Za-z0-9_-]+$") def validate_identifier(name: str, value: str) -> str: if not SAFE_IDENTIFIER.fullmatch(value): raise ValueError(f"Invalid {name}: only letters, digits, '_' and '-' are allowed") return value product_code = validate_identifier("product code", args.product_code) version = validate_identifier("version", args.version) output_root = pathlib.Path(args.output_dir).resolve() json_file = (output_root / f"{product_code}_{version}_api_docs.json").resolve() md_file = (output_root / f"{product_code}_{version}_api_list.md").resolve() for destination in (json_file, md_file): if destination.parent != output_root: raise ValueError("Output path escapes the configured output directory") ```
