T09 · Insecure Skill Coding Practices
Error
- Location
- workflow.py:17
- Finding
- Untrusted Audio Paths Can Cause Local Files to Be Uploaded to OpenAI<![CDATA[ ## Vulnerability Details **File Location**: `workflow.py:17-22`; `transcribe.py:17-31` **Vulnerability Type**: Unvalidated local file access and external data disclosure **Risk Level**: High ### Vulnerable Code ```python # workflow.py:17-22 if message["type"] == "text": prompt = message["content"] elif message["type"] == "audio": # Transcribe audio to get prompt print(f"Transcribing audio file: {message['content']}") prompt = transcribe_audio(message["content"]) ``` ```python # transcribe.py:17-31 audio = AudioSegment.from_file(file_path) chunk_size_ms = chunk_size_mins * 60 * 1000 chunks = [audio[i:i + chunk_size_ms] for i in range(0, len(audio), chunk_size_ms)] full_transcript = "" for i, chunk in enumerate(chunks): buffer = io.BytesIO() buffer.name = f"chunk_{i}.mp3" chunk.export(buffer, format="mp3") buffer.seek(0) transcript = client.audio.transcriptions.create( model="whisper-1", file=buffer, response_format="text", ) ``` ### Technical Analysis The workflow treats the `content` property of an audio message as a trusted local file path. It passes that path directly to `AudioSegment.from_file()` without canonicalizing it, restricting it to a controlled media directory, rejecting symbolic links, or validating its ownership and origin. After opening the file, the application converts the audio into MP3 chunks and uploads those chunks to the OpenAI transcription API. Consequently, any readable file that can be decoded as supported media may be disclosed to an external service. The implementation also has no input file-size, decoded-duration, chunk-count, or aggregate upload limit. A large or specially prepared media file could consume significant memory, CPU time, network bandwidth, and paid API quota. The current WhatsApp client returns hard-coded messages, but this flaw becomes directly exploitable if it is replaced with the real incoming-message integration described by the ...[truncated 1644 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not accept local filesystem paths directly from incoming messages. Use an internal, server-generated media identifier and resolve it through a trusted download or storage component. 2. Store inbound media in a dedicated directory that is inaccessible to untrusted users. 3. Resolve the candidate path with `Path.resolve()` and verify that it remains beneath the approved media root. 4. Reject absolute paths, traversal sequences, symbolic links, device files, pipes, sockets, and other non-regular files. 5. Open files using mechanisms that prevent symbolic-link following where supported. 6. Verify that the file was created by the trusted inbound-media component and has appropriate ownership and permissions. 7. Enforce limits on compressed file size, decoded duration, chunk count, and total bytes sent to the API. 8. Validate the media container and codec rather than relying only on its filename. 9. Process decoding in a sandbox with restricted filesystem and network access. 10. Require explicit user or administrator authorization before transmitting sensitive audio to an external service. 11. Record auditable metadata about the source message and upload without logging the sensitive content itself. ]]>
