Back to skill

Security audit

XGJK BP Audit

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent BP audit tool, but it needs Review because it can create business records and its credentialed API client can be redirected by environment configuration.

Install only if you intend the agent to access BP business data with an appKey and potentially create KR/Action records; use a least-privilege key, lock the API base URL to the documented production host, and require explicit human confirmation before any `add_*` action.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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/bp-audit/bp_api.py:37
Finding

Unrestricted API Base URL Override Can Exfiltrate the appKey and Business Data

Content
View full analysis

Vulnerability Details

File Location: scripts/bp-audit/bp_api.py:37-41, 48-60
Vulnerability Type: Credential exfiltration through an unvalidated network destination
Risk Level: High

Vulnerable Code

python
BASE_URL = os.environ.get(
    "BP_OPEN_API_BASE_URL",
    "https://sg-al-cwork-web.mediportal.com.cn/open-api",
)
APP_KEY = os.environ.get("BP_OPEN_API_APP_KEY", "")

TIMEOUT = 30


def _request(method, path, *, params=None, json_body=None):
    if not APP_KEY:
        return {"error": "BP_OPEN_API_APP_KEY is not configured. Set it as an environment variable."}

    url = f"{BASE_URL}{path}"
    headers = {"appKey": APP_KEY}

    try:
        if method == "GET":
            resp = requests.get(url, params=params, headers=headers, timeout=TIMEOUT)
        else:
            headers["Content-Type"] = "application/json"
            resp = requests.post(
                url,
                params=params,
                json=json_body,
                headers=headers,
                timeout=TIMEOUT,
            )

Technical Analysis

The script allows BP_OPEN_API_BASE_URL to determine the complete destination to which the authentication credential is sent. No validation restricts this value to the documented production origin, https://sg-al-cwork-web.mediportal.com.cn/open-api.

In particular, the implementation does not:

  • Require HTTPS.
  • Allowlist the expected hostname.
  • Reject loopback, private, or attacker-controlled destinations.
  • Reject unexpected ports or embedded URL credentials.
  • Prevent cross-origin HTTP redirects.
  • Normalize and verify the final request origin.

Every API request attaches BP_OPEN_API_APP_KEY as the appKey header. Therefore, control over the process environment is sufficient to redirect the credential to an arbitrary server. POST requests can additionally disclose business payloads containing internal task IDs, em ...[truncated 1985 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the BP_OPEN_API_BASE_URL override from the published production Skill and use a fixed, audited API origin.
  2. If an override is operationally required, parse the URL and strictly allowlist:
    • Scheme: https
    • Hostname: sg-al-cwork-web.mediportal.com.cn
    • Expected port: 443 or no explicit port
    • Expected base path: /open-api
  3. Reject URLs containing user information, fragments, unexpected query strings, IP-literal hosts, loopback addresses, or private-network destinations.
  4. Disable redirects with allow_redirects=False, or manually verify that every redirect remains on the exact approved origin before resending credentials.
  5. Build endpoints using a validated URL-joining function rather than direct string concatenation.
  6. Use a narrowly scoped, short-lived credential if supported by the service. Separate read-only audit credentials from write-capable credentials.
  7. Add automated tests proving that HTTP URLs, alternate hosts, unexpected ports, and cross-origin redirects are rejected.
  8. Rotate the appKey if there is any possibility that the override has previously pointed to an untrusted destination.

T01 · Skill Instruction Hijacking

Warning
Location
scripts/bp-audit/bp_api.py:106
Finding

Untrusted API Content Is Inserted Directly Into Agent-Consumed Markdown

Content
View full analysis

Vulnerability Details

File Location: scripts/bp-audit/bp_api.py:106-119, 141-158, 229-238
Vulnerability Type: Indirect prompt injection through remotely retrieved BP records
Risk Level: Medium

Vulnerable Code

python
def _strip_html(text):
    """Remove HTML tags and collapse whitespace."""
    if not text:
        return ""
    text = re.sub(r"<br\s*/?>", "\n", text)
    text = re.sub(r"<[^>]+>", "", text)
    text = re.sub(r" ", " ", text)
    text = re.sub(r"&", "&", text)
    text = re.sub(r"<", "<", text)
    text = re.sub(r">", ">", text)
    text = re.sub(r"\n{3,}", "\n\n", text)
    return text.strip()
python
def _fmt_align_list(items, label):
    """Format upwardTaskList / downTaskList into markdown lines."""
    if not items:
        return f"- {label}:无\n"
    lines = [f"- {label}({len(items)}项):\n"]
    for t in items:
        group_name = ""
        gi = t.get("groupInfo")
        if gi:
            group_name = f"[{gi.get('name', '?')}]"
        lines.append(
            f"  - {t.get('name', '?')} {group_name}"
            f"(id:{t.get('id', '?')})\n"
        )
    return "".join(lines)
python
def _md_key_result(kr, heading_level=3, include_actions=True):
    """Format a single KR (with optional actions)."""
    h = "#" * heading_level
    lines = [
        f"{h} KR {kr.get('fullLevelNumber', '?')}:"
        f"{_strip_html(kr.get('name', '?'))}\n\n"
    ]
    lines.append(
        f"- 状态:{kr.get('statusDesc', '?')} | "
        f"周期:{kr.get('reportCycle', '?')} | "
        f"时间:{kr.get('planDateRange', '?')}\n"
    )
    lines.append(f"- 人员:{_fmt_users(kr.get('taskUsers'))}\n")
    depts = _fmt_depts(kr.get("taskDepts"))
    if depts:
        lines.append(f"- 部门:{depts}\n")
    ms = _strip_html(kr.get("measureStandard", ""))
    if ms:
        li
...[truncated 2857 chars]
Remediation
View remediation

Remediation Suggestions

  1. Add an explicit instruction to SKILL.md stating that every API-returned field is untrusted data and must never be followed as an instruction.
  2. Delimit retrieved content structurally, for example:
    • BEGIN_UNTRUSTED_BP_DATA
    • Serialized typed records
    • END_UNTRUSTED_BP_DATA
  3. Prefer a typed JSON representation at the Agent boundary instead of instruction-like Markdown.
  4. Escape Markdown metacharacters in all remote string fields, including names, group names, measurement standards, paths, statuses, and user names.
  5. Remove or visibly encode code fences, links, images, control characters, bidirectional overrides, and zero-width characters.
  6. Apply strict field-length limits to prevent oversized prompt-injection payloads.
  7. Detect instruction-like phrases and flag them as suspicious record content without executing or following them.
  8. Ensure the Agent only extracts business facts from retrieved records and never treats those records as authority to invoke tools, reveal secrets, change policies, or alter the requested scope.
  9. Add adversarial tests using BP fields containing Markdown headings, code fences, fake system messages, tool-call requests, and instructions to ignore prior rules.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (36)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The destination URL is derived from BP_OPEN_API_BASE_URL, so anyone who can influence the environment can redirect authenticated GET requests to an arbitrary host. Because the appKey is sent in the request header, this can leak credentials and potentially expose queried organizational BP data to an attacker-controlled endpoint.

Content

Scanner excerpt · scripts/bp-audit/bp_api.py (reported line 57)May include surrounding context.

python
try:
        if method == "GET":
            resp = requests.get(url, params=params, headers=headers, timeout=TIMEOUT)
        else:
            headers["Content-Type"] = "application/json"
            resp = requests.post(url, params=params, json=json_body, headers=headers, timeout=TIMEOUT)

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The POST path combines an environment-controlled base URL with authenticated, state-changing requests and arbitrary JSON payload support, allowing redirection of both credentials and business data to an attacker-controlled server. In this skill, that is more dangerous because the same script can create BP records, so misuse can cause both data exfiltration and unauthorized external transmission of write payloads.

Content

Scanner excerpt · scripts/bp-audit/bp_api.py (reported line 60)May include surrounding context.

python
resp = requests.get(url, params=params, headers=headers, timeout=TIMEOUT)
        else:
            headers["Content-Type"] = "application/json"
            resp = requests.post(url, params=params, json=json_body, headers=headers, timeout=TIMEOUT)

        resp.raise_for_status()
        data = resp.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill is presented primarily as an audit/diagnostic tool, but it also includes write operations that create BP records, while the claimed audit logic largely exists as prompt instructions rather than enforceable code. This mismatch can cause users or supervising systems to authorize the skill under read-only assumptions, then unintentionally allow state-changing actions against business data.

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

md
1. 读取 `SKILL.md` 与 `common/*`,明确能力范围与约束。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
1. 读取 `SKILL.md` 与 `common/*`,明确能力范围与约束。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
1. 读取 `SKILL.md` 与 `common/*`,明确能力范围与约束。

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is described as an audit/diagnostic tool, but the README also documents mutation operations that create BP nodes (add_key_result, add_action). Mixing read-only auditing with write-capable workflows increases the chance that an agent invoked for analysis will perform unintended state-changing actions, especially if prompted to 'fix' issues it discovers. This is dangerous because it expands the tool from assessment into modification without a strong trust boundary or explicit safety gate.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is presented as an audit/query tool, but it includes add_key_result and add_action, which mutate remote state. In an agent setting, this mismatch is dangerous because a caller or downstream automation may grant it broader trust than appropriate and inadvertently allow record creation when expecting read-only auditing.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documents networked/script-based capabilities but declares no explicit tool scope or permission boundaries. In an agent environment, that omission increases the chance of unintended access to environment data or arbitrary outbound requests, especially because the skill instructs execution of a Python script that talks to internal APIs.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The activation description is broad enough that the skill may be invoked in many loosely related situations, increasing the chance of unnecessary access to business data or accidental execution of its network/script capabilities. Overbroad triggers are more dangerous here because the skill can query internal BP structures and also contains write paths.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Advertising an audit tool while embedding direct write capability violates the principle of least surprise and weakens operator trust boundaries. Even if the text says writes require explicit intent, the same skill context normalizes modification paths and may lead an agent to perform creation actions during what a user believes is a diagnostic workflow.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest and capability description emphasize built-in query functionality, but the documented action list includes POST-style creation endpoints. That discrepancy can mislead both users and automated policy systems into treating the skill as observational when it is capable of mutating production planning data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill describes write-capable operations in detail but does not present a strong, user-facing warning that these actions modify system state. In practice, that increases the risk of accidental creation of KR/Action records in production, especially when combined with automated ID discovery and scripted execution guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file contains only Chinese-language instructions and conventions, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking or region-specific audience. Under the policy, forcing a specific language without user opt-in 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
92% confidence
Finding

The README includes state-changing commands but lacks a prominent warning that these operations modify live BP data and may have organizational impact. Without explicit caution and confirmation requirements, users or agents can mistake example commands for safe diagnostic steps and unintentionally create or change records.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documented write capabilities are not necessary for the stated purpose of a system-audit skill and therefore violate least privilege. An agent or operator may over-trust the skill's audit framing and use embedded write commands to alter organizational BP data, turning a diagnostic workflow into an unauthorized or accidental change mechanism.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is presented as a BP audit/diagnostic tool, but the documented API surface includes POST endpoints that create key results and actions. This creates a capability mismatch: an agent or user expecting read-only auditing could be induced to mutate production BP data, increasing the risk of unauthorized or accidental changes.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · openapi/bp-audit/api-index.md (reported line 85)May include surrounding context.

md
|------|------|------|
| `taskId` | Long | 任务 ID |
| `role` | String | 角色:`承接人` / `协办人` / `抄送人` / `监督人` / `观察人` |
| `empList` | List | 该角色下的员工列表(含 `id`、`name`) |

### SimpleTaskVO(向上/向下对齐任务)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/bp-audit/bp_api.py (reported line 127)May include surrounding context.

python
|------|------|------|
| `taskId` | Long | 任务 ID |
| `role` | String | 角色:`承接人` / `协办人` / `抄送人` / `监督人` / `观察人` |
| `empList` | List | 该角色下的员工列表(含 `id`、`name`) |

### SimpleTaskVO(向上/向下对齐任务)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill file is written in Chinese and presents mandatory audit instructions such as '强制' and '严禁' without any indication that another language may be used or that the Chinese-only requirement is region-specific. This creates a natural-language locale constraint that does not provide user opt-in or documented 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 file title and the entire rule document are written in Chinese and present mandatory reporting requirements, but there is no indication that language choice is optional or limited to a justified region-specific context. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire guidance document is written exclusively in Chinese and does not indicate that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the regional constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level documentation repeatedly frames the utility as a data query CLI while exposing creation actions. This can mislead operators, reviewers, and agent orchestrators about the tool's trust boundary, increasing the chance of unsafe invocation in contexts intended to be non-destructive.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module and usage text emphasize fetching/querying BP data, but the implementation also performs POST-based task creation. This deceptive capability expansion is especially risky for LLM-driven tools, where descriptions are often used to decide whether a tool is safe to invoke automatically.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/bp-audit/bp_api.py (reported line 60)May include surrounding context.

python
resp = requests.get(url, params=params, headers=headers, timeout=TIMEOUT)
        else:
            headers["Content-Type"] = "application/json"
            resp = requests.post(url, params=params, json=json_body, headers=headers, timeout=TIMEOUT)

        resp.raise_for_status()
        data = resp.json()

Static analysis

No suspicious patterns detected.