T09 · Insecure Skill Coding Practices
- Location
scripts/qwen-audio.py:747- Finding
Unsanitized Voice IDs Permit Filesystem Path Traversal
- Content
View full analysis
dict | None: """Get voice file paths by voice_id. Returns dict with ref_audio, ref_text and instruct, or None if not found.""" voices_dir = get_voices_dir() voice_dir = os.path.join(voices_dir, voice_id) if not os.path.isdir(voice_dir): return None ref_audio = os.path.join(voice_dir, "ref_audio.wav") ref_text_path = os.path.join(voice_dir, "ref_text.txt") instruct_path = os.path.join(voice_dir, "ref_instruct.txt") if not os.path.exists(ref_audio): return None ref_text = "" if os.path.exists(ref_text_path): with open(ref_text_path, "r", encoding="utf-8") as f: ref_text = f.read().strip() ``` ```python def run_voice_create(args: argparse.Namespace) -> None: """Create a new voice by generating audio and saving reference info.""" voices_dir = get_voices_dir() voice_id = args.id or str(uuid.uuid4())[:8] voice_dir = os.path.join(voices_dir, voice_id) os.makedirs(voice_dir, exist_ok=True) # Normalize text: replace newlines with spaces text = _normalize_text(args.text) instruct = _normalize_text(args.instruct) if args.instruct else None if not instruct: raise ValueError("--instruct 参数是必需的,请提供语音风格描述") # Generate audio using TTS output_audio = os.path.join(voice_dir, "ref_audio.wav") ``` ```python sf.write(output_audio, audio_np, sample_rate) # Save reference text ref_text_path = os.path.join(voice_dir, "ref_text.txt") with open(ref_text_path, "w", encoding="utf-8") as f: f.write(text) # Save instruct instruct_path = os.path.join(voice_dir, "ref_instruct.txt") with open(instruct_path, "w", encoding="utf-8") as f: f. ...[truncated 2228 chars]- Remediation
View remediation
str: if not VOICE_ID_RE.fullmatch(voice_id): raise ValueError("Invalid voice ID") return voice_id ``` 2. Resolve and verify directory containment before every read or write: ```python voices_root = os.path.realpath(get_voices_dir()) voice_dir = os.path.realpath(os.path.join(voices_root, validate_voice_id(voice_id))) if os.path.commonpath([voices_root, voice_dir]) != voices_root: raise ValueError("Voice path escapes the voices directory") ``` 3. Reject absolute paths, path separators, `.` components, and `..` components even if an allowlist is introduced. 4. Apply the same centralized path-validation function to both `run_voice_create()` and `get_voice_path()`. 5. Refuse to overwrite an existing voice directory unless the user explicitly supplies a dedicated overwrite option. 6. Where supported, protect against symbolic-link traversal by checking each path component and using safe file-opening primitives with no-follow semantics. ]]>
