T09 · Insecure Skill Coding Practices
- Location
scripts/onboard.py:103- Finding
Indirect Prompt Injection Through Untrusted Repository Content
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill performs disclosed GitHub PR triage tasks, with a real caution that repository text can influence generated prompts and should be reviewed before use.
Use this with repositories you trust or review the generated interview prompt before letting an agent act on it. Treat README, PR bodies, releases, and report text as untrusted; do not allow automatic labeling, closing, or posting based only on the generated output without human review.
scripts/onboard.py:103Indirect Prompt Injection Through Untrusted Repository Content
The declared description presents a broader triage system for both PRs and issues, with onboarding, scanning, de-duplication, and reporting. The supplied code only implements the scanning portion for open pull requests. It fetches PR metadata with gh CLI, parses a local vision document for green/red keywords, scores PRs using fixed heuristics, identifies possible duplicate PRs by title overlap, and writes JSON. There is no code for interviewing a repo owner, generating a vision document, triaging issues, or producing markdown reports. The primary purpose is adjacent to the description but materially narrower, so this is a mismatch.
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
### From Lex Fridman Podcast #491:
- "AI agents will replace 80% of apps" (timestamp 3:02)
- Discussed acquisition offers from OpenAI and Meta (chose OpenAI for alignment)
- "Self-modifying AI agent" as a core concept
- Security concerns discussed at length (1:02:26)
### From README:
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
Use `references/rubric-template.md` as the starting template for the rubric.
"""
return prompt
def main():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self.assertEqual(onboard.parse_repo("owner/repo"), "owner/repo")
def test_path_traversal(self):
result = onboard.parse_repo("https://github.com/../../etc/passwd")
self.assertIsInstance(result, str)
def test_url_with_semicolon(self):
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self.assertEqual(onboard.parse_repo("owner/repo"), "owner/repo")
def test_path_traversal(self):
result = onboard.parse_repo("https://github.com/../../etc/passwd")
self.assertIsInstance(result, str)
def test_url_with_semicolon(self):
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self.assertEqual(onboard.parse_repo("owner/repo"), "owner/repo")
def test_path_traversal(self):
result = onboard.parse_repo("https://github.com/../../etc/passwd")
self.assertIsInstance(result, str)
def test_url_with_semicolon(self):
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def test_shell_injection_in_repo_name(self):
ctx = {"metadata": {"name": "$(rm -rf /)", "description": "", "stargazerCount": 0,
"primaryLanguage": {"name": "Python"}, "repositoryTopics": []}}
prompt = onboard.generate_interview_prompt("$(rm -rf /)/repo", ctx)
# Just verify it produces a string without crashing
self.assertIsInstance(prompt, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIn("none", md)
def test_shell_injection_in_title(self):
pr = _make_scored_pr(title="$(rm -rf /)")
md = report.pr_to_markdown(pr, "owner/repo")
self.assertIn("$(rm -rf /)", md)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIn("none", md)
def test_shell_injection_in_title(self):
pr = _make_scored_pr(title="$(rm -rf /)")
md = report.pr_to_markdown(pr, "owner/repo")
self.assertIn("$(rm -rf /)", md)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIn("none", md)
def test_shell_injection_in_title(self):
pr = _make_scored_pr(title="$(rm -rf /)")
md = report.pr_to_markdown(pr, "owner/repo")
self.assertIn("$(rm -rf /)", md)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def test_shell_injection_in_title(self):
pr = _make_scored_pr(title="$(rm -rf /)")
md = report.pr_to_markdown(pr, "owner/repo")
self.assertIn("$(rm -rf /)", md)
class TestGenerateReport(unittest.TestCase):
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def test_shell_injection_in_title(self):
pr = _make_scored_pr(title="$(rm -rf /)")
md = report.pr_to_markdown(pr, "owner/repo")
self.assertIn("$(rm -rf /)", md)
class TestGenerateReport(unittest.TestCase):
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
self.assertIsInstance(result, str)
def test_url_injection(self):
result = scan.parse_repo("https://github.com/owner/repo; rm -rf /")
self.assertIsInstance(result, str)
No suspicious patterns detected.