Back to skill

Security audit

9527-github-trending

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward GitHub Trending notifier, with disclosed network notifications and no evidence of hidden execution, covert persistence, or local data theft.

Install only if you are comfortable allowing it to fetch GitHub Trending and send that public summary to your chosen notification service. Keep bot tokens and webhook URLs private, prefer environment variables or a protected config file over command-line arguments or cron entries, and use only trusted official webhook URLs.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
trending.py:125
Finding

Unrestricted Webhook Destinations Allow Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: trending.py, lines 125–136 and 146–157
Vulnerability Type: Server-Side Request Forgery through user-controlled webhook URLs
Risk Level: Medium

Vulnerable Code

python
try:
    req = urllib.request.Request(webhook, data=json.dumps(data).encode('utf-8'), headers={
        'Content-Type': 'application/json'
    })
    with urllib.request.urlopen(req, timeout=30) as response:
        result = json.loads(response.read().decode('utf-8'))
        return result.get('errcode', -1) == 0
except Exception as e:
    print(f"钉钉发送失败: {e}")
    return False
python
try:
    req = urllib.request.Request(webhook, data=json.dumps(data).encode('utf-8'), headers={
        'Content-Type': 'application/json'
    })
    with urllib.request.urlopen(req, timeout=30) as response:
        result = json.loads(response.read().decode('utf-8'))
        return result.get('errcode', -1) == 0
except Exception as e:
    print(f"企业微信发送失败: {e}")
    return False

Technical Analysis

The --webhook argument is passed directly to urllib.request.Request and urllib.request.urlopen. The implementation does not validate:

  • The URL scheme
  • The destination hostname
  • The resolved IP address
  • Whether the destination is loopback, private, link-local, or reserved
  • Redirect destinations
  • Whether the URL belongs to an official DingTalk or WeCom webhook service

Consequently, a party able to control the program arguments can instruct the process to issue an HTTP POST request to an arbitrary URL reachable from the host. This creates a server-side request forgery primitive.

Exploitation is constrained because the request body is a fixed notification JSON structure and the response is only parsed for errcode, rather than being displayed to the caller. Nevertheless, the request can reach internal HTTP services that are inaccessible to an external attacke ...[truncated 1425 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use separate DingTalk and WeCom webhook parameters and allowlist only the official HTTPS webhook hostnames required by each provider.
  2. Reject all schemes except https.
  3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses.
  4. Disable automatic redirects or validate the scheme, hostname, and resolved address of every redirect target.
  5. Reject URLs containing unexpected user information, ports, fragments, or malformed hostnames.
  6. Apply outbound firewall or proxy rules so the process can connect only to GitHub and approved notification API domains.
  7. Add tests covering localhost, private IPv4 ranges, IPv6 loopback, link-local destinations, DNS rebinding scenarios, and redirects to prohibited destinations.

T09 · Insecure Skill Coding Practices

Note
Location
README.md:62
Finding

Documented Cron Configuration Exposes Telegram Credentials in Plaintext Arguments

Content
View full analysis

Vulnerability Details

File Location: README.md, lines 62–67; SKILL.md, lines 39–43
Vulnerability Type: Plaintext credential exposure in persistent scheduler configuration and process arguments
Risk Level: Low

Vulnerable Code

README.md:

bash
# 编辑 crontab
crontab -e

# 添加一行
0 9 * * * python3 /path/to/github-trending-daily/trending.py --telegram --token xxx --chat_id xxx

SKILL.md:

bash
# 每天 9:00 推送
0 9 * * * python3 /path/to/trending.py --telegram --token xxx --chat_id xxx

Technical Analysis

The documentation recommends placing the Telegram bot token and chat identifier directly in a cron command. If users replace the placeholders with real values, those values become persistent plaintext content in the user's crontab.

The token may also appear in the command line while the scheduled process is running. Depending on operating-system process visibility, account permissions, diagnostic tooling, monitoring agents, backups, or support bundles, other parties may be able to recover it. Users may additionally expose the token through shell history while testing or installing the command.

Cron scheduling is consistent with the Skill's declared daily-notification functionality, and the code does not install a scheduled task automatically. Therefore, this is not covert persistence. The security issue is the documented handling of credentials within that scheduler configuration.

Attack Path

  1. A user follows the documented cron example and substitutes a real Telegram bot token for xxx.
  2. The token is stored as plaintext in the crontab and appears in the scheduled process command line during execution.
  3. A local account, monitoring tool, backup process, diagnostic collector, or other actor with sufficient visibility reads the cron configuration or process arguments.
  4. The actor extracts the bot token.
  5. The actor uses the token with the Telegram Bot API to perf ...[truncated 557 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not pass Telegram bot tokens through command-line arguments.
  2. Add support for loading credentials from a dedicated configuration file or secret manager.
  3. Restrict any credential file to the owning account, such as with mode 0600, and verify ownership and permissions before reading it.
  4. Keep only a reference to the protected credential source in the cron entry, not the secret value itself.
  5. Avoid printing tokens in errors, logs, or debug output.
  6. Update both README.md and SKILL.md with a secure cron example.
  7. Advise users who previously followed the example to remove exposed values, review logs and backups, and rotate the Telegram bot token.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 63)May include surrounding context.

bash
# 编辑 crontab
crontab -e

# 添加一行
0 9 * * * python3 /path/to/github-trending-daily/trending.py --telegram --token xxx --chat_id xxx

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises network-dependent behavior and automated notifications, but it does not declare any explicit tool scope or permission boundary. In agent ecosystems, missing scope declarations can cause users or runners to underestimate what the skill is allowed to do, increasing the risk of unintended outbound network access or unsafe execution in broader-permission environments.

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 users to supply bot tokens, chat IDs, and webhook URLs for Telegram, DingTalk, and WeCom, and to schedule automatic execution, but it does not clearly warn that these secrets will be used for automatic transmission to external services. This can lead to accidental credential exposure, misuse of notification endpoints, or unanticipated data egress to third-party platforms.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · trending.py (reported line 99)May include surrounding context.

python
def send_telegram(message: str, token: str, chat_id: str) -> bool:
    """发送到 Telegram"""
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    data = {
        'chat_id': chat_id,
        'text': message,

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file describes sending data to Telegram, 钉钉, and 企业微信 using bot tokens, chat IDs, and webhook URLs, but it does not include any warning that these actions transmit data to third-party services or that the credentials are sensitive. Under the markdown-specific missing-warning rule, user-facing documentation should disclose behaviors that may affect privacy or system integrity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file’s natural-language instructions and description force a specific language for all users, which can be a language/locale policy concern when no opt-in or scope limitation is stated. There is no note that the skill is only for Chinese-speaking users or that other languages are supported.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The request header sets Accept-Language to en-US,en;q=0.5, which forces a specific language/locale preference for fetched content. This is a natural-language locale choice embedded in code, and the file provides no user option or explanation for why English is required.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.