Back to skill

Security audit

project-init

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but it handles a powerful Gitea token in risky ways that users should review before installing.

Install only if you intend this skill to administer the configured Gitea organization. Before entering a token, change GITEA_URL to a trusted HTTPS endpoint, use a least-privilege bot token scoped to the intended organization, review EMAIL_SKILL_PATH, and be aware that the token is stored locally in plaintext with file permissions set to 600.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Tainted flow: 'GITEA_URL' from os.environ.get (line 49, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
}

def api_get(path):
    return requests.get(f'{GITEA_URL}/api/v1{path}', headers=_headers(), timeout=15)

def api_post(path, data):
    return requests.post(f'{GITEA_URL}/api/v1{path}', json=data, headers=_headers(), timeout=15)
Confidence
95% confidence
Finding
GITEA_URL is taken from environment or a local .env file and used directly as the destination for authenticated HTTP requests. Because the Authorization token is sent in headers, a malicious or compromised configuration can redirect requests to an attacker-controlled server and exfiltrate the Gitea API token, making this an SSRF-plus-credential-leak issue.

Tainted flow: 'GITEA_URL' from os.environ.get (line 49, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
return requests.get(f'{GITEA_URL}/api/v1{path}', headers=_headers(), timeout=15)

def api_post(path, data):
    return requests.post(f'{GITEA_URL}/api/v1{path}', json=data, headers=_headers(), timeout=15)

def api_put(path, data):
    return requests.put(f'{GITEA_URL}/api/v1{path}', json=data, headers=_headers(), timeout=15)
Confidence
95% confidence
Finding
This POST helper sends authenticated API requests to a base URL fully controlled by environment configuration. If that URL is tampered with, repository metadata, file contents, collaborator settings, and the bearer token can all be transmitted to an attacker-controlled endpoint.

Tainted flow: 'GITEA_URL' from os.environ.get (line 49, credential/environment) → requests.put (network output)

Critical
Category
Data Flow
Content
return requests.post(f'{GITEA_URL}/api/v1{path}', json=data, headers=_headers(), timeout=15)

def api_put(path, data):
    return requests.put(f'{GITEA_URL}/api/v1{path}', json=data, headers=_headers(), timeout=15)

# ── 邮件发送(调用 imap-smtp-email Skill)────────────────────
Confidence
95% confidence
Finding
The PUT helper also uses the untrusted base URL and includes the API token in the Authorization header. In this skill, PUT requests grant repository access to users, so misdirection of these requests can leak sensitive information and enable unauthorized remote interactions with attacker infrastructure.

Tainted flow: 'cmd' from os.environ.get (line 89, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
cmd = ['node', str(smtp_script), '--account', EMAIL_ACCOUNT,
               'send', '--to', to, '--subject', subject, '--body', body]

    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if result.returncode != 0:
        print(f'[WARN] 邮件发送失败: {result.stderr}', file=sys.stderr)
    return result.returncode == 0
Confidence
76% confidence
Finding
Although shell injection is avoided, the executed program path is partly controlled by EMAIL_SKILL_PATH from configuration, so the script can be induced to execute an attacker-chosen Node.js file. In an agent/skill environment, that becomes arbitrary code execution if a malicious local path is supplied in the .env or environment.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill metadata declares required binaries but does not declare explicit permissions despite clearly intending to use environment variables, local files, network access, and likely shell/tool execution. This weakens the trust boundary for users and reviewers because the skill can perform impactful actions such as modifying repositories and sending email without transparent capability disclosure.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The trigger phrase includes very broad natural-language requests like '帮我建一个新仓库', which can match ordinary conversation and cause the skill to activate for high-impact operations. Because the skill creates repositories, changes collaborator permissions, creates issues, and sends emails, accidental invocation could lead to unauthorized or unintended actions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The description says the skill initializes a repository but omits prominent warning that it will modify remote repositories, assign admin/read permissions, create issues, and send outbound emails. This is dangerous because users may provide information in what appears to be a planning conversation without realizing it will trigger privileged external actions affecting other accounts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script interactively collects a Gitea personal access token and stores it in a plaintext local .env file. Although it applies restrictive file permissions afterward, users are not clearly warned that a long-lived credential will be persisted on disk, which increases the risk of accidental exposure through backups, endpoint compromise, shell history/workflow mistakes, or later unsafe file handling.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
main.js:64