T09 · Insecure Skill Coding Practices
- Location
scripts/list_openapi_meta_apis.py:33- Finding
Unvalidated API Identifiers Permit Output Path Traversal
- Content
View full analysis
Vulnerability Details
File Location:
scripts/list_openapi_meta_apis.py:33-34, 62-69
Vulnerability Type: Path traversal and unintended file overwrite
Risk Level: Mediumpython 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-codeandversionare incorporated directly into output filenames without validating or removing path separators, traversal components, or platform-specific path syntax.pathlib.Pathjoins these attacker-controlled values tooutput_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 outsideoutput/alicloud-ai-content-aicontent/. The writes usePath.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
- An attacker or untrusted caller invokes the script with a traversal-bearing
--product-codeor--versionvalue. - The ...[truncated 1325 chars]
- An attacker or untrusted caller invokes the script with a traversal-bearing
- Remediation
View remediation
Remediation Suggestions
- Validate
product-codeandversionagainst a strict allowlist before constructing either the URL or output filenames. For example, permit only ASCII letters, digits, underscores, and hyphens. - Reject empty values,
.and..components, path separators, encoded separators, control characters, and absolute-path syntax. - Resolve each destination and verify that it remains beneath the resolved output directory before writing.
- If overwriting is unnecessary, create output files exclusively to prevent accidental replacement of existing artifacts.
- Consider mapping user-visible identifiers to locally generated safe filenames rather than using raw command-line values.
- 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")- Validate
