T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/report_processor.py:54
- Finding
- Untrusted Report Content Can Manipulate Model-Generated Analysis## Vulnerability Details **File Location**: `scripts/report_processor.py`, lines 54–95 **Vulnerability Type**: Prompt injection with insufficient output validation **Risk Level**: Medium ### Vulnerable Code ```python def extract_with_ollama(text, prompt): """使用 Ollama 模型提取信息""" full_prompt = f""" {prompt} 请从以下研报内容中提取信息: --- {text[:50000]} # 限制输入长度 --- 请以 JSON 格式返回结果,包含以下字段: - core_points: 核心观点(数组) - key_data: 关键数据(对象) - investment_advice: 投资建议(字符串) - risk_warnings: 风险提示(数组) """ try: result = subprocess.run( ['ollama', 'run', OLLAMA_MODEL, full_prompt], capture_output=True, text=True, timeout=180, env={**os.environ, 'OLLAMA_HOST': '127.0.0.1:11434'} ) if result.returncode == 0: return result.stdout, None else: return None, f"Ollama 错误: {result.stderr}" except subprocess.TimeoutExpired: return None, "处理超时" except Exception as e: return None, str(e) def parse_json_response(response_text): """解析模型返回的 JSON 响应""" try: # 尝试找到 JSON 块 import re json_match = re.search(r'\{.*\}', response_text, re.DOTALL) if json_match: return json.loads(json_match.group()) except: pass return None ``` ### Technical Analysis The processor interpolates up to 50,000 characters of attacker-controlled report text directly into the Ollama prompt. Although delimiter lines visually separate the report from the surrounding instructions, the prompt does not explicitly identify the document as untrusted data or instruct the model to ignore commands contained within it. A malicious TXT, Markdown, or PDF report can therefore contain instructions that ask the model to disregard the intended extraction task and return fabricated core points, financial data, investment advice, or risk warni ...[truncated 2121 chars]
- Remediation
- ## Remediation Suggestions 1. Treat all extracted report text as untrusted content. Add explicit instructions stating that text inside the document is data only and that any commands, role changes, or output-format instructions within it must be ignored. 2. Use the model runtime's structured-output or JSON-schema capability where available instead of extracting an arbitrary JSON-looking substring with a regular expression. 3. Validate the parsed result against a strict schema: - Require exactly the intended fields. - Enforce arrays for `core_points` and `risk_warnings`. - Enforce an object for `key_data`. - Enforce a string for `investment_advice`. - Reject unknown keys, excessive lengths, invalid nesting, and malformed values. 4. Replace the greedy `r'\{.*\}'` extraction with a robust structured-response parser. Reject responses containing surrounding instructions, multiple objects, or non-JSON content. 5. Require generated claims to include source quotations or page references and verify that cited text occurs in the extracted report. 6. Mark all model-generated output as untrusted before it enters a knowledge base or decision-making workflow. Apply human review for investment recommendations or other high-impact uses. 7. Add adversarial tests containing embedded prompt-injection phrases in every supported input format and verify that the model continues to follow only the processor's extraction policy.
