Back to skill

Security audit

GitLab Team Report

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent GitLab reporting tool, but it needs review because it includes an underdocumented scheduler that can repeatedly collect GitLab activity and upload reports to Feishu.

Review before installing. Use a dedicated read-only GitLab token, require HTTPS for the GitLab URL, keep config and token files protected, and do not run scripts/setup-cron.sh unless you intentionally want a persistent recurring job. If publishing to Feishu, confirm exactly which document or wiki will be modified and whether reports may contain internal repository or personnel activity data.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T06 · System Persistence

Error
Location
scripts/setup-cron.sh:82
Finding

Persistent scheduled task performs recurring GitLab collection and unconditional Feishu publication

Content
View full analysis
> \"$SKILL_DIR/logs/cron.log\" 2>&1 # $CRON_COMMENT" echo "⏰ Setting scheduled task:" echo " Schedule: $cron_expr" echo " Command: generate report and upload to Feishu" echo "" # Remove the previous task of the same type (crontab -l 2>/dev/null | grep -v "$CRON_COMMENT") | crontab - # Add the new task (crontab -l 2>/dev/null; echo "$CMD") | crontab - ``` The related removal logic is also present at `scripts/setup-cron.sh:66-70`: ```bash remove_cron() { echo "🗑️ Removing scheduled task..." (crontab -l 2>/dev/null | grep -v "$CRON_COMMENT") | crontab - echo "✅ Scheduled task removed" } ``` ### Technical Analysis The script directly modifies the invoking user's crontab and installs a recurring command that survives the current Skill or Agent session. The default schedule is weekly, but a caller can supply another cron expression. Scheduled report generation can be a legitimate optional capability. However, `SKILL.md` does not document cron installation as part of the declared workflow, and the persistent job performs more than local report generation: it always invokes `upload-to-feishu.sh`. The job does not check the configured `feishu.enabled` value. The example configuration sets that option to `false`, but a cron job installed by this script still attempts publication on every execution. Consequently, an optional network publication operation becomes a persistent, recurring operation. This exceeds the minimum privileges required for on-demand weekly report generation. It also extends access to GitLab and Feishu credentials beyond the session in which the user requested ...[truncated 1345 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate-report.py:93
Finding

GitLab private token may be transmitted over insecure HTTP or to an unintended redirect destination

Content
View full analysis
Any: req = urllib.request.Request(url, headers=headers) with urllib.request.urlopen(req, timeout=60) as resp: return json.load(resp) ``` ```python headers = {"PRIVATE-TOKEN": cfg["gitlab"]["token"]} base = cfg["gitlab"]["url"].rstrip("/") ``` The alternate shell implementation has the same insecure-transport exposure at `scripts/generate-report-simple.sh:102-106`: ```bash get_user_events() { local user_id=$1 curl -s "${GITLAB_URL}/api/v4/users/${user_id}/events?per_page=100" \ -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" 2>/dev/null } ``` ### Technical Analysis The GitLab base URL is entirely configuration-controlled. Neither implementation requires an HTTPS scheme before attaching the `PRIVATE-TOKEN` header. If `gitlab.url` is accidentally or maliciously configured with `http://`, the personal access token and API responses can cross the network without transport encryption. The Python implementation also relies on the default redirect behavior without explicitly ensuring that a redirect remains on the original trusted origin before credentials are reused. The outbound GitLab access itself is necessary for the declared reporting functionality and no hard-coded attacker endpoint was found. The vulnerability is the lack of transport and destination restrictions around a high-value authentication token. ### Attack Path 1. An attacker modifies the configuration, supplies a prepared configuration file, or causes a user to configure an HTTP or redirecting GitLab URL. 2. The report generator reads the GitLab private token from that configuration. 3. The generator constructs requests from the unvalidated base URL ...[truncated 1008 chars]
Remediation
View remediation
/dev/null`. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/generate-report.py:347
Finding

Generated reports execute mutable JavaScript from a remote CDN

Content
View full analysis
``` ### Technical Analysis Every generated HTML report retrieves and executes ECharts JavaScript from jsDelivr when the report is opened. The dependency is specified only by major version (`echarts@5`) rather than an immutable exact version, and no Subresource Integrity hash is supplied. As a result, the effective browser-side code is not fully contained in the reviewed Skill package and may change after the audit. A compromised CDN account, package release, registry artifact, or delivery path could cause arbitrary JavaScript to execute in the report page. The remote script is not required for collecting GitLab data. Charts can be generated locally by the included Python chart generator, so this remote execution channel is avoidable. ### Attack Path 1. The Skill generates `weekly_report.html` containing the remote script element. 2. A user opens the generated report in a browser. 3. The browser requests the current `echarts@5` asset from jsDelivr. 4. The returned JavaScript executes in the report's browser context. 5. If the CDN or upstream package is compromised, the payload can inspect the report DOM and transmit report content to another endpoint. ### Impact Assessment A malicious remote script could access all information rendered in the report, including: - Team member names and profile links. - Internal repository names. - Merge-request titles and URLs. - Contribution and activity statistics. - Reporting periods and organizational metadata. The script executes in the report's browser context. Its ability to access unrelated origins remains constrained by browser same-origin rules, but it can read and exfiltrate the complete generated report and manipulate what the ...[truncated 18 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Python dependencies are open-ended and not integrity-verified

Content
View full analysis
=3.5.0 pandas>=1.3.0 numpy>=1.21.0 requests>=2.26.0 python-dateutil>=2.8.0 ``` The installation instruction appears at `SKILL.md:106-108`: ```bash pip3 install -r requirements.txt ``` ### Technical Analysis Every Python dependency uses an open-ended minimum version. A future installation can therefore resolve versions substantially different from those tested or reviewed with this Skill. The dependency file does not include hashes, a lock file, an index restriction, or a reproducible dependency graph. Although no suspicious or typosquatted package names were identified, installation can introduce future compromised, incompatible, or behavior-changing releases. Several listed packages also do not appear necessary for the main generator's current implementation, increasing the dependency surface beyond the minimum required functionality. ### Attack Path 1. A user follows the documented installation command. 2. pip queries its configured package index and selects the newest compatible releases. 3. Package installation executes build or installation logic and places the dependencies in the runtime environment. 4. A compromised future release or maliciously configured index supplies unreviewed code. 5. That code executes during installation or when imported by the chart generator. ### Impact Assessment Third-party package code executes with the privileges of the user performing installation or running the Skill. Compromise could expose: - GitLab and Feishu configuration files. - Environment variables and credentials. - Generated reports. - Other files accessible to the user. - Network access available to the process. The finding is rated Low because the package names and default sources shown in the project are conventional and no malicious de ...[truncated 29 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/upload-to-feishu.js:6
Finding

Feishu SDK is loaded from a hard-coded mutable global OpenClaw installation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (43)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code’s core domain matches the description at a high level: it does generate a GitLab weekly report for configured users over a date range, including merge requests and commit/push activity, and outputs Markdown. However, many prominently declared capabilities are absent from this code chunk. The script only writes a simple Markdown file and summary table. Although it parses flags/config related to Feishu and charts, it never performs Feishu upload or chart generation. It also does not generate HTML, historical index pages, repository summaries, or classify work by product area/function. There is no evidence of unrelated or dangerous undeclared behavior; the issue is that the declared description significantly overstates implemented functionality in this code chunk.

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 16)May include surrounding context.

md
4. 如需发布到飞书,使用 `scripts/upload-to-feishu.sh` 或 `scripts/upload-to-feishu.js`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 34)May include surrounding context.

md
4. 如需发布到飞书,使用 `scripts/upload-to-feishu.sh` 或 `scripts/upload-to-feishu.js`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 110)May include surrounding context.

md
- 保持 `SKILL.md` 聚焦流程和决策,不要把大段样例配置塞进来。

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/generate-report.py (reported line 216)May include surrounding context.

python
if layer == "repo":
            for rule in rule_config.get("repo_rules", []):
                if match_any(repo, rule.get("match", [])):
                    return rule["category"], rule["subcategory"], "config_repo", 1000
        elif layer in {"label", "title", "branch"}:
            for rule in rule_config.get("keyword_rules", []):
                if rule.get("field") == layer and match_any(field_values[layer], rule.get("match", [])):

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/generate-report.py (reported line 220)May include surrounding context.

python
if layer == "repo":
            for rule in rule_config.get("repo_rules", []):
                if match_any(repo, rule.get("match", [])):
                    return rule["category"], rule["subcategory"], "config_repo", 1000
        elif layer in {"label", "title", "branch"}:
            for rule in rule_config.get("keyword_rules", []):
                if rule.get("field") == layer and match_any(field_values[layer], rule.get("match", [])):

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/lib/feishu-api.sh (reported line 8)May include surrounding context.

sh
FEISHU_API_BASE="https://open.feishu.cn/open-apis"

# 获取 tenant access token
get_tenant_token() {
    local app_id=$1
    local app_secret=$2

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill describes operations that can read and write files, invoke shell scripts, access environment-based secrets, and perform network publishing, but it declares no explicit tool scope or permission boundaries. In an agent environment, this increases the chance of overbroad execution or unintended access when the skill is auto-invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger phrases are broad enough that the skill may activate for loosely related requests about reports, summaries, commits, or publishing. Because the skill can lead to shell execution, file operations, and optional outbound publishing, accidental activation increases the risk of unintended data processing or disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill advertises optional publishing to Feishu without a prominent warning that report contents may include internal engineering activity, repository metadata, and contributor information sent to an external service. In a reporting context, that omission materially raises the chance of accidental data exfiltration or policy violations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The skill description and primary heading/body are presented as Chinese-first instructions for report generation, with no statement that users may choose output language or locale. This can constitute a locale/language policy issue when the skill behavior is implicitly tied to a specific language without explicit opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The config hard-codes category and subcategory values in Chinese, and similar Chinese-only labels recur throughout the file. Because this is a general example JSON file with no documented locale constraint or user opt-in, it appears to force a specific language choice in a way that can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code includes natural-language strings such as the module description and later user-facing output entirely in Chinese, but provides no opt-in, fallback, or justification for a Chinese-only locale. Under the policy, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script loads a GitLab token and Feishu app credentials from the config file, which is access to sensitive credentials. While there is a log that the config is being loaded, there is no comment, help text, or user-facing warning that the skill will read and use these secrets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script makes authenticated HTTP requests to the GitLab API using the PRIVATE-TOKEN header. There is no explicit warning in the help text or surrounding comments that running the script will contact GitLab and send the configured token to the remote server.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code performs multiple HTTP requests to the GitLab API using a private token and retrieves user details, events, projects, and merge-request metadata. Although the script's purpose is report generation, this file does not include a docstring, comment, or user-facing notice explaining that user and repository activity data will be sent over the network to the configured GitLab server.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script reads a GitLab private token from configuration and uses it for authenticated API access. There is no nearby comment, docstring, or startup message warning operators that the skill consumes sensitive credentials and will use them to query account and project data.

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/generate-report.py (reported line 576)May include surrounding context.

python
if not args.no_charts:
        try:
            subprocess.run([sys.executable, str((Path(__file__).parent / "generate-charts.py").resolve()), str(stats_file), str(charts_dir)], check=True)
        except Exception:
            pass

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · scripts/lib/feishu-api.sh (reported line 13)May include surrounding context.

sh
local app_id=$1
    local app_secret=$2
    
    curl -s -X POST "${FEISHU_API_BASE}/auth/v3/tenant_access_token/internal" \
        -H "Content-Type: application/json" \
        -d "{\"app_id\":\"$app_id\",\"app_secret\":\"$app_secret\"}" | \
        jq -r '.tenant_access_token'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The function sends app_id and app_secret to the Feishu authentication endpoint, which is a sensitive credential-handling network operation. Although the code has an internal comment naming the function, there is no user-facing warning, confirmation, or logging that this skill transmits credentials over the network.

Content

No source excerpt is available for this finding.

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 · scripts/setup-cron.sh (reported line 64)May include surrounding context.

sh
list_cron() {
    echo "📋 当前定时任务:"
    crontab -l 2>/dev/null | grep -A2 -B2 "$CRON_COMMENT" || echo "  未找到 GitLab 周报定时任务"
}

remove_cron() {

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 · scripts/setup-cron.sh (reported line 99)May include surrounding context.

sh
list_cron() {
    echo "📋 当前定时任务:"
    crontab -l 2>/dev/null | grep -A2 -B2 "$CRON_COMMENT" || echo "  未找到 GitLab 周报定时任务"
}

remove_cron() {

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

This function rewrites the user's crontab to remove tagged entries, which is a persistent system modification. In the context of an agent skill, modifying scheduled tasks is security-relevant because it changes system state outside the current execution and should be treated as a privileged operation even if intended for cleanup.

Content

Scanner excerpt · scripts/setup-cron.sh (reported line 69)May include surrounding context.

sh
remove_cron() {
    echo "🗑️  正在移除定时任务..."
    (crontab -l 2>/dev/null | grep -v "$CRON_COMMENT") | crontab -
    echo "✅ 定时任务已移除"
}

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The cron job unconditionally chains report generation with upload-to-feishu.sh, so enabling automation also enables external publication. This exceeds the stated 'optional Feishu publishing' behavior and can cause unintended disclosure of internal engineering activity to a third-party platform on a recurring basis.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The scheduled command sends generated reports to Feishu, but the setup help and prompts do not clearly disclose that recurring external data transmission will occur. Users may believe they are only scheduling local report generation, when in fact project summaries may be published automatically to an external service.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.