Back to skill

Security audit

code-review-assistant

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent code-review skill, but its remote GitLab diff helper can send a user's GitLab token to an untrusted host, so it should be reviewed before installation.

Install only if you trust the repositories and PR/MR URLs this skill will process. Avoid using --token on the command line, prefer narrowly scoped read-only tokens, and do not run authenticated GitLab fetching against self-hosted or unfamiliar hosts unless you have verified that the host should receive your GitLab token.

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/get_pr_diff.py:65
Finding

GitLab access token can be disclosed to an attacker-controlled host

Content
View full analysis

Vulnerability Details

File Location: scripts/get_pr_diff.py, lines 65-78, 101-108, 128-134, 147, 163-168, and 191-207
Vulnerability Type: Credential disclosure through an untrusted network destination
Risk Level: High

Vulnerable Code

python
def get_gitlab_diff(project, pr_number, token=None, base_url="https://gitlab.com"):
    """Fetch an MR diff from the GitLab API."""
    # URL encode project path
    project_encoded = project.replace("/", "%2F")
    url = f"{base_url}/api/v4/projects/{project_encoded}/merge_requests/{pr_number}/diffs"
    
    headers = {}
    if token:
        headers["PRIVATE-TOKEN"] = token
    
    req = urllib.request.Request(url, headers=headers)
    
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            diffs = json.loads(response.read().decode("utf-8"))

The destination can be populated from a user-provided merge request URL:

python
def parse_gitlab_url(url):
    """Parse a GitLab MR URL."""
    # https://gitlab.com/group/project/-/merge_requests/123
    match = re.match(r"https://([^/]+)/([^/]+)/([^/]+)/-/merge_requests/(\d+)", url)
    if match:
        base_url = f"https://{match.group(1)}"
        project = f"{match.group(2)}/{match.group(3)}"
        return base_url, project, int(match.group(4))
    return None

It can also be derived from the current repository's remote:

python
gitlab_match = re.match(r"(?:git@([^:]+):|https://([^/]+)/)([^/]+)/([^/]+?)(?:\.git)?$", remote_url)
if gitlab_match:
    host = gitlab_match.group(1) or gitlab_match.group(2)
    return {
        "provider": "gitlab",
        "base_url": f"https://{host}",
        "project": f"{gitlab_match.group(3)}/{gitlab_match.group(4)}"
    }

The environment token is then automatically attached to the request:

python
gitlab_info = parse_gitlab_url(args.url)
if gitlab_info:
    base_url, project, pr_number = gitlab_info
    token = args.token or os.environ.get("GITLAB_TOKEN")
    pri
...[truncated 2842 chars]
Remediation
View remediation

Remediation Suggestions

  1. Restrict authenticated requests to an explicit hostname allowlist. Default to gitlab.com and reject other hosts unless the user has deliberately configured a trusted self-hosted instance.
  2. Bind each credential to a specific hostname. For example, use a host-specific credential configuration rather than forwarding the generic GITLAB_TOKEN variable to arbitrary instances.
  3. Require explicit confirmation before transmitting credentials to a non-default GitLab host.
  4. Normalize and validate destinations with a URL parser. Require HTTPS, reject embedded credentials, unexpected ports, fragments, malformed hosts, and ambiguous hostnames.
  5. Disable automatic redirects for authenticated requests or implement redirect handling that removes authentication headers whenever the destination host changes.
  6. Do not infer authorization to send credentials solely from a repository's origin remote. Treat repository configuration as untrusted input.
  7. Separate token variables for GitLab.com and self-hosted instances, such as a host-to-token mapping stored in protected configuration.
  8. Use narrowly scoped, short-lived tokens and document the minimum required read-only permissions.
  9. Add tests confirming that tokens are not sent to unapproved hosts or across cross-origin redirects.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_pr_diff.py:146
Finding

API tokens accepted through command-line arguments may leak through process metadata and command history

Content
View full analysis

Vulnerability Details

File Location: scripts/get_pr_diff.py, line 146
Vulnerability Type: Insecure credential handling
Risk Level: Medium

Vulnerable Code

python
parser.add_argument("--token", type=str, help="API Token (or use environment variable)")

The argument is subsequently preferred over environment-based credentials:

python
token = args.token or os.environ.get("GITHUB_TOKEN")
python
token = args.token or os.environ.get("GITLAB_TOKEN")

Technical Analysis

The script permits users and automation to provide an API token directly as a command-line argument. Command-line arguments are not an appropriate secret transport mechanism because they may be exposed through:

  • Shell command history.
  • Process inspection facilities.
  • Process-monitoring and endpoint-management tools.
  • CI/CD command logs.
  • Debugging output and audit records.
  • Wrapper scripts or job metadata that preserve the complete invocation.

Although the script does not print args.token itself, the credential can be exposed before or during process execution by the surrounding operating system and execution environment.

Attack Path

  1. A user runs the script with --token SECRET_VALUE, or a CI job constructs an equivalent command.
  2. The complete command is retained in shell history, CI logs, process metadata, or monitoring records.
  3. A local user, administrator, monitoring integration, or party with access to retained logs reads the token.
  4. The exposed token is used against GitHub or GitLab before it expires or is revoked.

Impact Assessment

An attacker who obtains the token receives the API permissions granted to that credential. Depending on its scopes, this can include:

  • Reading private repositories and pull or merge requests.
  • Accessing organization or group resources.
  • Modifying code, branches, issues, or merge requests.
  • Triggering workflows or pipelines.
  • Performing administrative actions if the token is excessivel ...[truncated 135 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the --token command-line option.
  2. Prefer a protected credential store or the platform's standard credential helper.
  3. If interactive entry is required, use a non-echoing prompt such as Python's getpass rather than command-line arguments.
  4. For automated execution, use a protected secret injection mechanism and prevent secret values from appearing in generated commands or logs.
  5. Use short-lived, narrowly scoped, read-only tokens for diff retrieval.
  6. Document that tokens must not be passed through shell arguments.
  7. Add automated checks that reject deprecated --token usage and guide users toward the protected credential mechanism.
  8. Ensure CI systems mask applicable environment variables and avoid verbose command tracing while credentials are in scope.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是一个完整的代码 Review 助手,核心能力应是“分析代码并输出审查结果”。但实际代码仅是一个本地 Git diff 获取工具,负责执行 git 命令并打印差异与简单行数统计。这可以视为代码 Review 工作流中的前置辅助步骤,但不是声明中的主要功能本身。代码没有任何审查规则、静态分析、风险识别、结构化报告生成、远程 PR 获取或多格式输出逻辑,因此实际行为与声明的主用途存在实质性不符。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码的实际主功能只是“抓取 PR/MR diff”,属于声明中提到的一个辅助子能力,但完全没有实现所宣称的核心能力——代码审查与报告输出。脚本会访问 GitHub/GitLab API、读取 GITHUB_TOKEN/GITLAB_TOKEN 环境变量,并通过 git 命令读取当前仓库 remote 信息,这些资源访问虽与 diff 获取相关,但声明整体将技能定位为 Review 助手,而不是单纯的 diff 拉取工具。由于实际行为与声明的主要用途存在明显落差,应判定为不匹配。

Content

No source excerpt is available for this finding.

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/get_pr_diff.py (reported line 11)May include surrounding context.

python
python get_pr_diff.py --url "https://github.com/owner/repo/pull/123"

环境变量:
  GITHUB_TOKEN - GitHub Personal Access Token
  GITLAB_TOKEN - GitLab Personal Access Token
"""

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/get_pr_diff.py (reported line 12)May include surrounding context.

python
python get_pr_diff.py --url "https://github.com/owner/repo/pull/123"

环境变量:
  GITHUB_TOKEN - GitHub Personal Access Token
  GITLAB_TOKEN - GitLab Personal Access Token
"""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

该技能说明明确要求运行本地脚本、读取 git diff,并支持获取 GitHub/GitLab PR diff,这意味着会用到 shell、本地环境信息以及可能的网络访问,但 SKILL.md 没有声明任何 permissions 或 allowed-tools 范围。缺少最小权限边界会让调用环境默认授予过宽能力,增加意外执行命令、访问仓库元数据或发起外部请求的风险。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

技能描述包含大量宽泛触发词,如“检查这段代码”“看看这个 diff 有没有问题”“代码审查”等,容易与常见日常请求重叠,导致技能在用户未明确授权的上下文中被过度触发。对于具备 shell、环境读取和潜在网络能力的技能,这种误触发会扩大数据暴露和非预期操作的攻击面。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction “中文输出,技术术语保留英文原词” imposes a specific output language unconditionally. This is a natural-language policy concern because the skill does not indicate that the user can opt into another language or that the Chinese-only requirement is justified by a documented regional constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents all guidance in Chinese and does not indicate that the language choice is optional or limited to a justified region-specific audience. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The title and all instructional content in this markdown file are written exclusively in Chinese, which imposes a specific language on users without any opt-in or alternative. The policy specifically calls for flagging language or locale constraints unless the skill offers choice or clearly documents a justified regional limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This markdown file contains natural-language guidance exclusively in Chinese, including the title and all instructional content. Under the policy, forcing a specific language without user opt-in or a documented region-specific justification is a language/locale policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The document title and all guidance are presented exclusively in Chinese, indicating a language-specific constraint. There is no visible user opt-in, alternative locale, or justification that this is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document title and all instructional content are written in Chinese, which imposes a specific language on users without any indication of language choice or opt-in. This matches the policy category for natural-language locale/language constraints when no alternative or justification is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown template is entirely written in Chinese and hard-codes Chinese report headings and examples such as "代码 Review 报告" and lang="zh-CN". Under the policy rule, forcing a specific language or locale without offering a user choice or documenting a justified regional constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents all review guidance exclusively in Chinese, including headings and checklist items, with no indication that language selection is optional. Under the policy rule, a skill that enforces a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The entire skill guide is written only in Chinese and presents trigger phrases and usage guidance solely in that language, without indicating that language selection is optional or region-specific. This can constitute a language/locale policy violation because it implicitly forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The Standard mode activates on generic phrases like "review", "代码审查", and especially "检查代码(未指定模式时)", which are common everyday requests in coding contexts and may match many unintended situations. The file does not provide exclusion conditions or narrower constraints to distinguish when this skill should activate versus when a user is making a general request.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The trigger list includes broad phrases like "全面检查" and "PR review", which can appear in ordinary collaboration or code-review discussion and are not uniquely tied to this skill. Because no constraints or negative examples are provided, the activation boundary for Strict mode is unclear and could cause unintended invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring, CLI description, help text, and runtime messages are written entirely in Chinese, which imposes a specific language on users. Under the policy, this is a natural-language locale constraint and there is no opt-in or justification that the skill is intended only for a Chinese-speaking or region-specific audience.

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/get_diff.py (reported line 22)May include surrounding context.

python
def run_git(args, cwd=None):
    """执行 git 命令,返回输出"""
    try:
        result = subprocess.run(
            ["git"] + args,
            capture_output=True,
            text=True,

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/get_pr_diff.py (reported line 28)May include surrounding context.

python
def run_git(args, cwd=None):
    """执行 git 命令,返回输出"""
    try:
        result = subprocess.run(
            ["git"] + args,
            capture_output=True,
            text=True,

External Transmission

Medium
Category
Data Exfiltration
Confidence
71% confidence
Finding

The script sends repository and PR/MR identifiers, and potentially authentication tokens, to external GitHub or GitLab endpoints. In the context of a code-review assistant, this can expose private code diffs to third-party services or attacker-controlled GitLab instances when --base-url or a crafted URL is used, creating confidentiality risk.

Content

Scanner excerpt · scripts/get_pr_diff.py (reported line 41)May include surrounding context.

python
def get_github_diff(owner, repo, pr_number, token=None):
    """从 GitHub API 获取 PR diff"""
    url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
    
    headers = {"Accept": "application/vnd.github.v3.diff"}
    if token:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language documentation entirely in Chinese, including the module docstring and usage/environment variable explanations. Under the stated policy, forcing a specific language without offering a user choice or documenting a justified locale restriction is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.