Back to skill

Security audit

code-review-for-gitcode

Security checks for vulnerabilities and agentic risk

Overview

This GitCode PR review skill is mostly purpose-aligned, but its posting script can publish comments without its documented confirmation gate and it handles access tokens insecurely.

Install only if you are comfortable granting the agent a narrowly scoped GitCode token and publishing PR comments through this workflow. Do not pass long-lived tokens on the command line or in URLs, rotate any token already used that way, and require manual confirmation outside the script before running post_review.py.

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/post_review.py:99
Finding

PR comments are posted without the required explicit user confirmation

Content
View full analysis

Vulnerability Details

File Location: scripts/post_review.py:99-121
Related Requirement: SKILL.md:356-389
Vulnerability Type: Missing authorization/consent gate before an external write
Risk Level: High

Vulnerable Code:

python
# Show preview
print("\n" + "="*60)
print("代码检视意见预览")
print("="*60)
print(f"\n来源: {review_file}")
print(f"总问题数: {meta.get('total_issues', 0)}")
print(f"自动扫描: {meta.get('automated_count', 0)}")
print(f"人工审查: {meta.get('manual_count', 0)}")
print(f"将提交: {len(comments)} 条评论\n")

for i, comment in enumerate(comments, 1):
    print(f"### 评论 #{i}")
    print(f"文件: {comment['path']} (行 {comment['position']})")
    print(f"严重程度: {comment['severity']}/10")
    print(f"类型: {comment['type']}")
    print(f"内容:\n{comment['body'][:500]}...")
    print()

# Post individual comments only (no summary)
print(f"\n正在提交 {len(comments)} 条评论...")
for i, comment in enumerate(comments, 1):
    print(f"提交评论 #{i}...")
    post_comment(
        owner, repo, pr_number, token,
        comment["body"],
        comment.get("path"),
        comment.get("position")
    )

Technical Analysis

The Skill specification says that posting comments is optional and must occur only after the user explicitly confirms the preview. The implementation does not enforce this control. Once invoked with valid arguments, post_review.py displays the preview and immediately enters the posting loop.

This is a time-of-authorization flaw: displaying intended changes does not establish consent to perform them. Because the check is absent from the executable boundary, an Agent that follows the documented invocation can perform external writes even when the user has not answered yes.

The script also reports that all comments were successfully posted without checking each post_comment() return value, although this reporting defect is secondary to the missing confirmation gate.

...[truncated 1084 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add an explicit confirmation prompt after displaying the complete preview and before the first network request.
  2. Normalize the response and proceed only for an exact allowlist such as yes or 是; treat empty, malformed, or unrecognized input as denial.
  3. Prefer separating preview and execution into distinct operations. For automation, require an explicit --confirm flag supplied only after consent has been obtained outside the script.
  4. Keep the posting function inaccessible until the authorization gate succeeds.
  5. Abort remaining submissions when a post fails, or clearly report per-comment success and failure rather than always claiming full success.
  6. Add tests proving that EOF, no, empty input, and arbitrary text result in zero POST requests.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/post_review.py:55
Finding

GitCode access tokens are exposed through command-line arguments and URL examples

Content
View full analysis

Vulnerability Details

File Location: scripts/post_review.py:55-73
Additional Locations: scripts/review_pr.py:590-603, SKILL.md:35,365-377, API.md:38-46
Vulnerability Type: Insecure credential handling
Risk Level: Medium

Vulnerable Code:

python
def main():
    if len(sys.argv) < 5:
        print("Usage: python post_review.py <owner> <repo> <pr_number> <token> [formatted_review.json]")
        print("")
        print("Parameters:")
        print("  owner: Repository owner (e.g., Ascend)")
        print("  repo: Repository name (e.g., msinsight)")
        print("  pr_number: PR number (e.g., 277)")
        print("  token: GitCode access token")
        print("  formatted_review.json: Path to formatted review JSON (default: formatted_review.json)")
        sys.exit(1)

    owner = sys.argv[1]
    repo = sys.argv[2]
    pr_number = int(sys.argv[3])
    token = sys.argv[4]
    review_file = sys.argv[5] if len(sys.argv) > 5 else "formatted_review.json"

scripts/review_pr.py similarly accepts a token as a positional argument:

python
pr_url = sys.argv[1]
token = sys.argv[2] if len(sys.argv) > 2 else None

if not token:
    token = os.environ.get('GITCODE_TOKEN')

API.md additionally demonstrates placing the token in a URL:

bash
curl -X POST \
  "https://api.gitcode.com/api/v5/repos/Ascend/msinsight/pulls/275/comments?access_token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "【review】可维护性问题。代码中存在硬编码值。建议提取为常量。",
    "path": "src/components/Table.tsx",
    "position": 42
  }'

Technical Analysis

Tokens passed as command-line arguments may be retained in shell history, captured by command telemetry, or exposed through process-list and process-inspection interfaces to other local principals, depending on the operating system and its configuration.

The API documentation further encourages a que ...[truncated 1731 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove positional token parameters from both scripts.
  2. Obtain credentials from a protected credential store, a narrowly scoped environment variable, or an interactive getpass.getpass() prompt.
  3. Send tokens exclusively through the Authorization: Bearer ... header; remove all query-string token examples.
  4. Update SKILL.md, API.md, and usage messages so they never encourage secrets in command lines or URLs.
  5. Request the narrowest GitCode scopes that support reading the target PR and posting review comments. Avoid broad repository scope where a narrower scope is available.
  6. Ensure errors and debug output never print request headers, request bodies containing credentials, or complete authenticated URLs.
  7. Recommend token rotation if a real token has already been used in documented command forms and may have entered history or logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (18)

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

md
- `owner`: Repository owner (e.g., `Ascend`)
- `repo`: Repository name (e.g., `msinsight`)
- `pr_number`: PR number (e.g., `277`)
- `token`: GitCode access token
- `temp/formatted_review.json`: Output from Step 4 (default: `temp/formatted_review.json`)

**Example**:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

The skill instructs deletion of temp/ using recursive force commands (rm -rf temp/ / Remove-Item -Recurse -Force temp/). In an agentic environment, destructive filesystem operations are risky because path confusion, working-directory manipulation, or symlink abuse could cause unintended deletion of files outside the intended scratch area.

Content

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

删除 temp 目录及其所有内容

Remove-Item -Recurse -Force temp/

或

rm -rf temp/

text

**清理时机**:

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The script explicitly solicits a GitCode access token as a positional argument and then transmits it for authenticated API use. If exposed via process listings, logs, command history, or CI output, the token could be reused to impersonate the user and modify repository discussions or perform other actions allowed by the token's scope.

Content

Scanner excerpt · scripts/post_review.py (reported line 65)May include surrounding context.

python
print("  owner: Repository owner (e.g., Ascend)")
        print("  repo: Repository name (e.g., msinsight)")
        print("  pr_number: PR number (e.g., 277)")
        print("  token: GitCode access token")
        print("  formatted_review.json: Path to formatted review JSON (default: formatted_review.json)")
        sys.exit(1)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

文档在 L023-L027 明确将 access_token 标为必需的 Query Parameter,但 L056-L079 的 Python 示例却把 access_token 放入 data JSON 体中,并未按示例 URL 查询参数方式传递。这不是简单省略,而是对调用方式的直接矛盾,可能导致读者按示例实现时认证失败或误用接口。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation explicitly demonstrates passing an access token in the URL query string, which can leak credentials through browser history, shell history, reverse proxies, analytics, and server logs. In an agent skill context, this is more dangerous because downstream automation may copy this pattern verbatim and expose long-lived repository tokens at scale.

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

请求示例

bash
curl -X POST \
  "https://api.gitcode.com/api/v5/repos/Ascend/msinsight/pulls/275/comments?access_token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This markdown repeatedly uses mandatory Chinese-language instructions and output examples, such as requiring review artifacts and prompts in Chinese, without indicating that the user can choose another language. That creates a natural-language locale policy issue because the skill effectively imposes a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring and all user-facing messages in this script are written in Chinese, which imposes a specific language on users without offering a choice or documenting a justified regional scope. Under the policy, a fixed locale is a natural-language violation unless the skill is explicitly region-specific or user-selectable.

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

md
def post_comment(owner: str, repo: str, pr_number: int, token: str, 
                 body: str, path: str = None, position: int = None):
    """Post a comment to GitCode PR."""
    url = f"https://api.gitcode.com/api/v5/repos/{owner}/{repo}/pulls/{pr_number}/comments"
    
    # Build request data
    data = {

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

md
def post_comment(owner: str, repo: str, pr_number: int, token: str, 
                 body: str, path: str = None, position: int = None):
    """Post a comment to GitCode PR."""
    url = f"https://api.gitcode.com/api/v5/repos/{owner}/{repo}/pulls/{pr_number}/comments"
    
    # Build request data
    data = {

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

md
def post_comment(owner: str, repo: str, pr_number: int, token: str, 
                 body: str, path: str = None, position: int = None):
    """Post a comment to GitCode PR."""
    url = f"https://api.gitcode.com/api/v5/repos/{owner}/{repo}/pulls/{pr_number}/comments"
    
    # Build request data
    data = {

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 · scripts/post_review.py (reported line 16)May include surrounding context.

python
def post_comment(owner: str, repo: str, pr_number: int, token: str, 
                 body: str, path: str = None, position: int = None):
    """Post a comment to GitCode PR."""
    url = f"https://api.gitcode.com/api/v5/repos/{owner}/{repo}/pulls/{pr_number}/comments"
    
    # Build request data
    data = {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script accepts a GitCode access token directly as a command-line argument, which can expose the secret through shell history, process listings, CI job logs, and audit tooling. In an automation/review tool context, this is a real credential-handling weakness because the token is then used to perform authenticated API actions against a repository.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script prints operational preview and submission status messages exclusively in Chinese, even though other user-facing text in the file is in English. This imposes a specific language on users without opt-in or justification, which matches the natural-language locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code emits issue type, description, and suggestion text in Chinese string literals throughout the analyzer, with no option for the user to select another language. That is a natural-language locale policy concern because the skill effectively forces one output language by default rather than offering opt-in or configurability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

对于 markdown 文件,若描述了可能影响隐私的数据传输行为,应提供相应警告。这里的示例函数会将 token 与评论内容提交到 GitCode 外部接口,但文档只描述功能和参数,没有明确提醒这是一次外部网络传输,可能包含敏感审查内容和认证凭证。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

前文主 API 使用 https://api.gitcode.com/api/v5/... 且示例采用 access_token 查询参数(L009-L011, L039-L047),但 L132-L135 的 diff 获取示例改为 https://gitcode.com/api/v5/... 并使用 Authorization: Bearer TOKEN。对于同一套 API 文档,这种主机和认证方式切换构成了主动性的文档矛盾,容易误导实现者。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The formatter strips and reconstructs review text using the full-width Japanese period '。' and a fixed '【review】' template, which enforces a specific locale/style on all output. There is no option for the user to choose language or output convention, so this can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.