T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/run_meeting_minutes.py:176
- Finding
- Indirect Prompt Injection Through Untrusted Meeting Transcripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_meeting_minutes.py:176-199` **Additional Location**: `scripts/run_meeting_minutes.py:150-172` **Vulnerability Type**: Indirect prompt injection and insufficient output validation **Risk Level**: Medium ### Complete Code Snippet ```python def summarize_meeting(transcript: str) -> dict[str, Any]: prompt = f"""You are an AI assistant that generates meeting minutes. Analyze the following meeting transcript and return JSON with these fields: - topic - discussion_points - decisions - action_items - voice_summary_text Rules: - do not fabricate missing facts - discussion_points should be concise - decisions should only include confirmed conclusions - action_items should include owner if mentioned Transcript: {transcript} """ client = build_client() response = client.chat.completions.create( model=LLM_MODEL, temperature=0.3, messages=[ {"role": "system", "content": "Return valid JSON only."}, {"role": "user", "content": prompt}, ], ) return extract_json(extract_message_content(response)) ``` The same unsafe interpolation pattern is used during transcript cleaning: ```python def clean_transcript_with_llm(transcript: str) -> str: prompt = f"""You are an assistant that cleans meeting transcripts. Clean the transcript below: - remove filler words - remove repeated phrases - improve readability - preserve facts, names, numbers, decisions, and action items Transcript: {transcript} Return only the cleaned transcript text. """ client = build_client() response = client.chat.completions.create( model=LLM_MODEL, temperature=0.2, messages=[ {"role": "system", "content": "Return only cleaned transcript text."}, {"role": "user", "content": prompt}, ], ) return extract_message_content(response) ``` ### Technical Analysis The transcript originates from us ...[truncated 2150 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all transcript text as untrusted data and explicitly state in the system instruction that commands, policies, or requests appearing inside the transcript must never be followed. 2. Place transcript data inside clearly identified boundaries or pass it through a structured input field rather than concatenating it with task instructions. 3. Use provider-supported structured output or JSON Schema enforcement for the summary response. 4. Validate the parsed object before use: - Require all expected fields. - Require `topic` and `voice_summary_text` to be strings. - Require `discussion_points`, `decisions`, and `action_items` to be arrays of strings. - Reject unexpected nesting, excessive lengths, and unknown fields where appropriate. 5. Add post-generation grounding checks for decisions and action items, especially before using them in automated workflows. 6. Do not silently accept suspicious or malformed model output. Reject it or retry with a constrained prompt. 7. Add adversarial tests containing spoken prompt-injection phrases and verify that they are represented only as meeting content, not followed as instructions. ]]>
