Back to skill

Security audit

GitLab API

Security checks for vulnerabilities and agentic risk

Overview

This GitLab helper is coherent, but it handles a powerful token and can modify or delete repositories without enough built-in safeguards.

Review before installing. Use a least-privilege, revocable GitLab token, prefer an environment variable or secure credential store, ensure any file-based token is owner-only, require HTTPS for every GitLab URL, and manually approve write or delete operations, especially on protected or default branches.

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

Error
Location
scripts/gitlab_api.sh:8
Finding

GitLab Access Token Can Be Transmitted over Plaintext HTTP

Content
View full analysis
/dev/null || echo "https://gitlab.com")}" # Ensure URL has https:// prefix if [[ "$GITLAB_URL" != http* ]]; then GITLAB_URL="https://$GITLAB_URL" fi ``` The resulting URL is subsequently used to transmit the access token: ```bash curl -s -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \ "$API_BASE/projects?owned=true&per_page=50" \ | jq -r '.[] | "\(.id)\t\(.path_with_namespace)\t\(.web_url)"' ``` The same token-bearing header is used by the read, write, delete, and directory-listing operations. ### Technical Analysis The URL validation condition accepts any value beginning with `http`, including an insecure `http://` URL. Consequently, the comment stating that the script ensures an HTTPS prefix does not reflect its actual behavior. The instance URL can be supplied through the `GITLAB_URL` environment variable or the user-controlled `~/.config/gitlab/instance_url` configuration file. If either source contains a plaintext HTTP endpoint, every API operation sends the GitLab personal access token in a `PRIVATE-TOKEN` request header without transport encryption. Because the documented token scopes include `api` or repository write access, disclosure of this header can expose a highly privileged credential. ### Attack Path 1. An attacker modifies `~/.config/gitlab/instance_url`, influences the `GITLAB_URL` environment variable, or causes the user to configure an endpoint beginning with `http://`. 2. The user invokes any command such as `list-projects`, `read-file`, `write-file`, `delete-file`, or `list-dir`. 3. The script accepts the HTTP URL because it begins with `http`. 4. `curl` s ...[truncated 949 chars]
Remediation
View remediation
&2 exit 1 ;; esac ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:12
Finding

Token Setup Instructions Do Not Enforce Restrictive File Permissions

Content
View full analysis
~/.config/gitlab/api_token ``` ### Technical Analysis The documented setup writes a privileged GitLab personal access token to a predictable plaintext file without explicitly restricting permissions on either the directory or the token file. The resulting permissions depend on the user's current `umask` and any pre-existing directory permissions. In an environment with an overly permissive umask or an already accessible `~/.config/gitlab` directory, another local user or process may be able to read the token. The documentation also recommends scopes including `api` or `read_api` combined with `write_repository`. Therefore, disclosure may provide substantial access to private source code and repository modification capabilities. ### Attack Path 1. A user follows the documented setup instructions. 2. The token is written to `~/.config/gitlab/api_token` using permissions derived from the current environment and umask. 3. The resulting file or its parent directory is readable or traversable by another local account or untrusted process. 4. The attacker reads the plaintext token from the predictable path. 5. The attacker submits the token to GitLab and performs operations allowed by its scopes and the victim's project permissions. This path requires local access or execution under a security context capable of reading the insufficiently protected file. ### Impact Assessment Successful exploitation discloses the GitLab personal access token. Depending on the configured scopes, the attacker may obtain: - Read access to private projects and source code. - Repository write access, including malicious file modifications. - The ability to delete repository files where permitted. - Broader GitLab API capabilities whe ...[truncated 169 chars]
Remediation
View remediation
"$HOME/.config/gitlab/api_token" unset GITLAB_TOKEN printf '\n' ``` The helper script may also verify that the token file is owned by the current user and is not accessible to group or other users before reading it. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The skill explicitly instructs handling a GitLab personal access token and storing it in plaintext in a predictable local path. Because such tokens can grant broad API and repository access, compromise of the host, permissive file permissions, or accidental disclosure can directly enable unauthorized access and repository tampering.

Content

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

Setup

Store your GitLab personal access token:

bash
mkdir -p ~/.config/gitlab

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill invokes shell commands extensively but does not declare any tool restrictions or permissions boundaries. That increases the chance an agent may execute repository-modifying commands in contexts where only read-only behavior was expected, expanding operational risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The description says the skill should be used for essentially any GitLab repository operation, including read, write, create, and delete actions. This broad invocation scope makes it easier for an agent to apply the skill in high-impact situations without narrowing intent or least-privilege controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The setup instructions tell users to store a personal access token locally but do not warn that the token is sensitive, grants API access, and should be protected with strict filesystem permissions. This can lead to inadvertent exposure of reusable credentials on shared systems or in logs and backups.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

Persisting the access token under ~/.config/gitlab creates a durable credential artifact that survives beyond the immediate task. Persistent secrets increase exposure to later compromise by other local users, malware, backups, or unrelated processes with filesystem access.

Content

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

Store your GitLab personal access token:

bash
mkdir -p ~/.config/gitlab
echo "glpat-YOUR_TOKEN_HERE" > ~/.config/gitlab/api_token

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation includes file creation, update, deletion, and branch creation workflows without warnings about irreversible repository changes or the need for confirmation. In an agent setting, this can normalize destructive actions and increase the chance of unintended code loss or unauthorized modifications.

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 · SKILL.md (reported line 79)May include surrounding context.

md
BRANCH="main"
CONTENT=$(echo "print('hello')" | base64)

curl -X POST -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITLAB_URL/api/v4/projects/$PROJECT_ID/repository/files/${FILE_PATH}" \
  -d @- <<EOF

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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/gitlab_api.sh (reported line 18)May include surrounding context.

sh
if [ -z "$GITLAB_TOKEN" ]; then
    echo "Error: GitLab token not found" >&2
    echo "Set GITLAB_TOKEN env var or create ~/.config/gitlab/api_token" >&2
    exit 1
fi

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/gitlab_api.sh (reported line 71)May include surrounding context.

sh
local encoded_content=$(echo -n "$content" | base64)
    
    # Check if file exists
    if curl -s -f -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
        "$API_BASE/projects/$project_id/repository/files/$encoded_path?ref=$branch" \
        >/dev/null 2>&1; then
        # Update existing file

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The delete-file command issues a GitLab API DELETE request that removes a repository file, but the script provides no confirmation prompt or explicit user-facing warning before performing this irreversible remote change. Although the command name indicates deletion, the script itself lacks any safeguard or disclosure around the destructive action.

Content

No source excerpt is available for this finding.

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/gitlab_api.sh (reported line 108)May include surrounding context.

sh
local encoded_path=$(urlencode "$file_path")
    
    curl -s -X DELETE -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
        -H "Content-Type: application/json" \
        "$API_BASE/projects/$project_id/repository/files/$encoded_path" \
        -d @- <<EOF | jq -r '"Deleted: " + .file_path'

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The write-file command creates or updates files in a GitLab repository via authenticated API calls, which modifies user data remotely. The script does not include any confirmation prompt or explicit warning message before performing the write, so users may not get clear disclosure of the side effect from the script itself.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.