T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/onboard.py:103
- Finding
- Indirect Prompt Injection Through Untrusted Repository Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboard.py:62-69`, `scripts/onboard.py:101-126`, and `scripts/onboard.py:182-194` **Vulnerability Type**: Untrusted remote content embedded into an Agent-facing prompt **Risk Level**: Medium ### Vulnerable Code ```python # scripts/onboard.py:62-69 # README readme = run_gh(["api", f"repos/{repo}/readme", "--jq", ".content", "-H", "Accept: application/vnd.github.raw+json"], ignore_errors=True) if readme: context["readme"] = readme[:5000] # Truncate to keep prompt manageable ``` ```python # scripts/onboard.py:101-126 readme_snippet = context.get("readme", "Not available")[:2000] prompt = f"""# Vision Interview for {name} ## Repo Context (auto-gathered) - **Repo:** {repo} - **Description:** {desc} - **Stars:** {stars} | **Language:** {language} - **Topics:** {', '.join(topic_names) if topic_names else 'none'} - **Open issues/PRs:** {context.get('open_issues', 'unknown')} ### README excerpt: ``` {readme_snippet} ``` ### Recent releases: {context.get('releases', 'None found')} --- ## Interview Questions Ask the repo owner these questions to build their vision document and scoring rubric. Adapt based on the repo context above. Skip questions that are already answered by the README. ``` ```python # scripts/onboard.py:182-194 # Generate interview prompt prompt = generate_interview_prompt(repo, context) # Save interview prompt output_dir = Path(args.output_dir) output_dir.mkdir(parents=True, exist_ok=True) interview_path = output_dir / "interview-prompt.md" interview_path.write_text(prompt) print(f"Interview prompt saved to: {interview_path}", file=sys.stderr) # Also print to stdout for the agent to use directly print(prompt) ``` ### Technical Analysis The onboarding workflow retrieves README content from a user-selected GitHub repository and interpolates that content verbatim into a prompt explicitly intended for direct Agent use. Repository owners and ...[truncated 2871 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all GitHub-derived fields as untrusted data, including README text, descriptions, topics, release output, and repository names. 2. Add an explicit instruction before the repository context stating that embedded content is data only and that instructions, tool requests, or policy claims inside it must never be followed. 3. Prevent Markdown fence termination by selecting a delimiter longer than any matching run in the content or by encoding the content as a JSON string inside a clearly delimited data structure. 4. Prefer extracting narrowly defined repository facts instead of embedding raw README content into an Agent prompt. 5. Separate trusted workflow instructions and untrusted repository evidence into distinct structured fields. 6. Sanitize or escape Markdown control characters when generating Agent-facing and human-facing documents. 7. Add adversarial tests covering: - Triple-backtick fence termination. - Fake system or developer messages. - Requests to invoke tools or disclose credentials. - Nested Markdown, HTML comments, and misleading headings. - Injection attempts in metadata and release text. 8. Ensure any Agent consuming the generated prompt operates with minimum privileges and requires explicit user confirmation before taking external or destructive actions. ]]>
