Back to skill

Security audit

Github Trend Observer

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent GitHub research tool, but it needs review because untrusted GitHub text can influence analysis and generated HTML reports are not safely escaped.

Review before installing. This skill will use your locally authenticated GitHub CLI and make live GitHub API calls, so use it only with a GitHub account and quota you are comfortable spending. Treat generated HTML reports cautiously until the renderer escapes untrusted fields, and do not let README or issue text from analyzed repositories change the agent's instructions.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_report.py:70
Finding

Unescaped Template Substitution Enables HTML and Script Injection in Generated Reports

Content
View full analysis
{s}' for s in signals ) if lang == "cn": for detail in data.get("pick_details", []): if detail.get("pattern_label"): detail["pattern_label"] = LABEL_CN.get(detail["pattern_label"], detail["pattern_label"]) return data def render_simple(template, data): """Simple template rendering: {{key}} replacement + {{#each list}}...{{/each}} single-level loop""" def replace_each(match): key = match.group(1) block = match.group(2) items = data.get(key, []) parts = [] for item in items: rendered = block if isinstance(item, dict): for k, v in item.items(): if isinstance(v, (str, int, float)): rendered = rendered.replace("{{" + k + "}}", str(v)) else: rendered = rendered.replace("{{this}}", str(item)) parts.append(rendered) return "\n".join(parts) output = re.sub( r'{{#each (\w+)}}(.*?){{/each}}', replace_each, template, flags=re.DOTALL ) # Replace top-level {{key}} variables for k, v in data.items(): if isinstance(v, (str ...[truncated 3029 chars]
Remediation
View remediation
` elements. - Event-handler attributes such as `onerror`. - Quotes that escape `href` attributes. - `javascript:` and `data:` URLs. - HTML embedded in repository descriptions, issue titles, signals, and analysis fields. 8. Escape Markdown table delimiters and link destinations independently when generating Markdown reports. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
scripts/deep_link.py:43
Finding

Untrusted GitHub Content Is Supplied to the Analyzer Without Prompt-Injection Boundaries

Content
View full analysis
500: break excerpt += line + "\n" return excerpt.strip() return "" ``` The remotely controlled text is included in the structured output intended for analysis: ```python print_json({ "repo": repo, "base": base, "readme_excerpt": readme, "commits_distribution": commits, "star_history": star_history, "contributors_top10": contributors, "releases_recent": releases, "issue_analysis": issues, "high_star_forks": forks, "owner_other_repos": owner_repos, "ecosystem": ecosystem, "competitor_candidates": competitors, "adoption_signals": adoption }) ``` The Skill then directs the Agent to analyze the collected data without establishing an explicit trust boundary: ```markdown # Step 2: Fetch complete data python scripts/deep_link.py langchain-ai/langgraph # Step 3: Fetch star growth curve (full mode only) python scripts/fetch_star_history.py langchain-ai/langgraph # Step 4: Read agents/analyzer.md + references/layer_model.md # Generate ecosystem map + Layer positioning + paradigm assessment ``` The analyzer role likewise describes the data generically as structured input: ```markdown # GitHub Radar — PM Insight Analyzer Agent You are an open-source ...[truncated 3167 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description emphasizes a GitHub intelligence tool that produces PM-grade insights using authenticated gh CLI and the GitHub API. The supplied code chunk does not perform GitHub querying, intelligence gathering, or PM analysis. Its primary purpose is post-processing already-produced analysis data into HTML and Markdown reports using local templates and writing them to output files. That is a materially different function from the declared end-user description, and the claimed GitHub/gh-powered behavior is absent in this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code clearly uses the GitHub CLI/API as declared, but its implemented behavior is limited to searching repositories, filtering/deduplicating results, and returning structured metadata. It does not analyze repositories from an AI PM perspective, infer paradigms, or produce insights beyond raw/filtered search results. The script itself even states that relevance filtering and higher-level classification are handled externally by an agent workflow, reinforcing that this chunk is a retrieval component rather than the described intelligence/insight tool. Therefore the description materially overstates the code’s actual purpose and capabilities.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · skill.md (reported line 35)May include surrounding context.

md
- If the user speaks **English** -> Use `skill.md`, `agents/analyzer.md`, `references/layer_model.md`, `templates/*.html`, and generate English reports

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/deep-link.html (reported line 118)May include surrounding context.

html
<hr>

<!-- ==================== Profile ==================== -->
<h2>Profile</h2>
<table>
  <colgroup><col style="width:90px"><col style="width:180px"><col></colgroup>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/deep-link_cn.html (reported line 118)May include surrounding context.

html
<hr>

<!-- ==================== 基础画像 ==================== -->
<h2>基础画像</h2>
<table>
  <colgroup><col style="width:90px"><col style="width:180px"><col></colgroup>

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file title and instructions are entirely Chinese and direct the agent to output a fixed response verbatim, with no indication that the user may choose another language. The policy forbids forcing a specific language or locale without user opt-in unless the restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The onboarding instructions direct the agent to run authenticated gh and Python commands that can access GitHub account context and make network requests, but they do not require explicit user consent or warn that local credentials will be used. This creates a real risk of unintended external access, metadata disclosure, or consumption of the user's authenticated GitHub session simply by loading the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the agent to run automated tests that include live API and integration checks, but it does not give an upfront warning that these tests may contact external services and consume GitHub API quota. An agent following these instructions could silently trigger network activity and spend limited authenticated API budget without the user's informed approval.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction '你是一个 AI PM 视角的开源项目分析 agent' and the rest of the document consistently prescribe Chinese-language behavior, with no opt-in, fallback, or note that the skill is region-specific. This is a natural-language locale policy issue because it constrains language unconditionally rather than letting the user choose.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This JSON eval file is a manifest-type file, so vague-trigger checks apply. The prompt text "Monitor abnormal signals" is broad and underspecified; it does not define what counts as a signal, which sources are in scope, or exclusion conditions, making accidental or inconsistent invocation more likely.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The phrase "What's worth looking at today" is highly generic everyday language and lacks domain-specific constraints. In a manifest-like file, this kind of broad trigger can collide with ordinary user requests and does not clearly distinguish when this skill should or should not activate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

All user-facing prompts and expectations are written in Chinese, which suggests a fixed language/locale assumption. The file does not offer a language choice or document that the skill is intentionally region-specific, so this may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This JSON file is a manifest-like config, so vague-trigger review applies. The prompt "今天有什么值得看的" is very broad and conversational, with no scope constraints or negative examples, making it unclear when this skill should activate versus ordinary discussion.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file presents all substantive guidance in Chinese, including headings, criteria, and examples, without indicating that language selection is optional or that the document is intentionally limited to a Chinese-speaking audience. Under the policy criteria, a skill or reference that implicitly enforces a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/deep_link.py (reported line 86)May include surrounding context.

python
"""Call fetch_star_history.py to get star growth data"""
    script = os.path.join(SCRIPT_DIR, "fetch_star_history.py")
    try:
        result = subprocess.run(
            [sys.executable, script, repo],
            capture_output=True, text=True, timeout=120,
            encoding='utf-8', errors='replace'

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/gh_utils.py (reported line 18)May include surrounding context.

python
def run_gh(args, timeout=15):
    """Execute a gh command and return the stdout string. Returns None on failure."""
    try:
        result = subprocess.run(
            [GH] + args,
            capture_output=True, text=True,
            timeout=timeout,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/gh_utils.py (reported line 39)May include surrounding context.

python
json_fields = "name,owner,description,stargazersCount,forksCount,updatedAt,language,url,createdAt,isArchived"
    cmd = [GH, "search", "repos"] + query_args + ["--json", json_fields]
    try:
        result = subprocess.run(
            cmd, capture_output=True, text=True,
            timeout=timeout,
            encoding='utf-8', errors='replace'

compile() call detected

Medium
Category
Dangerous Code Execution
Confidence
65% confidence
Finding

compile() creates code objects from strings. When combined with exec()/eval(), it enables obfuscated code execution.

Content

Scanner excerpt · scripts/test_oss.py (reported line 31)May include surrounding context.

python
with open(path, "r", encoding="utf-8") as f:
            source = f.read()
        try:
            compile(source, filename, "exec")
        except SyntaxError as e:
            self.fail(f"{filename} syntax error: {e}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_oss.py (reported line 130)May include surrounding context.

python
def test_print_json_output(self):
        """print_json tested via subprocess (setup_utf8_stdout replaces sys.stdout)"""
        result = subprocess.run(
            [sys.executable, "-c",
             'import sys; sys.path.insert(0,r"' + SCRIPT_DIR + '"); '
             'from gh_utils import print_json; '

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The test suite runs external commands via subprocess and performs live GitHub API checks using authenticated gh CLI calls. Although these actions are described in test docstrings, there is no user-facing confirmation, warning print, or explicit disclosure that running the tests may invoke network activity against the user's authenticated GitHub account.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_oss.py (reported line 227)May include surrounding context.

python
def setUpClass(cls):
        """Check if gh is available"""
        try:
            result = subprocess.run(
                ["gh", "auth", "status"],
                capture_output=True, text=True, timeout=10
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_oss.py (reported line 240)May include surrounding context.

python
# Check rate limit
        try:
            result = subprocess.run(
                ["gh", "api", "rate_limit", "--jq", ".rate.remaining"],
                capture_output=True, text=True, timeout=10
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_oss.py (reported line 290)May include surrounding context.

python
# Check rate limit
        try:
            result = subprocess.run(
                ["gh", "api", "rate_limit", "--jq", ".rate.remaining"],
                capture_output=True, text=True, timeout=10
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_oss.py (reported line 256)May include surrounding context.

python
def test_check_rate_limit_script(self):
        """check_rate_limit.py outputs valid JSON"""
        result = subprocess.run(
            [sys.executable, os.path.join(SCRIPT_DIR, "check_rate_limit.py")],
            capture_output=True, text=True, timeout=15,
            encoding="utf-8", errors="replace"