T09 · Insecure Skill Coding Practices
- Location
scripts/protein_key_fragment_analysis.py:423- Finding
Path Traversal Through Unsanitized Species Name Allows Writes Outside the Output Directory
- Content
View full analysis
{species_name}_consensus\n") for i in range(0, len(clean_consensus), 60): f.write(clean_consensus[i:i+60] + "\n") # ... fragments_path = species_dir / f"{species_name}_key_fragments.json" with open(fragments_path, 'w', encoding='utf-8') as f: json.dump({ "species": species_name, "date": DATE_STR, "consensus_length": len(clean_consensus), "key_fragments": key_fragments }, f, ensure_ascii=False, indent=2) report_path = generate_report( species_name, sequences, consensus_seq, conservation_scores, key_fragments, species_dir ) ``` The value reaches this function directly from the command-line positional argument: ```python parser.add_argument("species_name", nargs="?", help="物种名称") # ... result = analyze_species(args.species_name, fasta, out_dir, precomputed_aligned=args.precomputed_aligned) ``` ### Technical Analysis The user-controlled `species_name` is used as both a directory component and part of several output filenames without validation. `pathlib.Path` does not automatically constrain a joined path to its intended base directory. A value containing parent-directory components, such as `../target`, can escape `output_dir`. An absolute value can also cause the preceding base path to be discarded during path composition. The resulting paths are subsequently passed to directory creation, Py ...[truncated 2723 chars]- Remediation
View remediation
str: if not re.fullmatch(r"[A-Za-z0-9_-]+", species_name): raise ValueError( "Species name must contain only letters, digits, underscores, and hyphens" ) return species_name def confined_path(base: Path, *parts: str) -> Path: base = base.resolve() candidate = base.joinpath(*parts).resolve() if candidate != base and base not in candidate.parents: raise ValueError("Output path escapes the configured output directory") return candidate species_id = safe_species_id(species_name) output_root = Path(output_dir).resolve() output_root.mkdir(parents=True, exist_ok=True) species_dir = confined_path(output_root, species_id) species_dir.mkdir(parents=False, exist_ok=True) aln_path = confined_path( species_dir, f"{species_id}_aligned.fasta" ) consensus_path = confined_path( species_dir, f"{species_id}_consensus.fasta" ) fragments_path = confined_path( species_dir, f"{species_id}_key_fragments.json" ) ``` If spaces or non-ASCII biological names must be supported, create a deterministic safe slug or ...[truncated 163 chars]
