Back to skill

Security audit

Juggle自动化工作流

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate Juggle workflow helper, but it can trigger external workflows with a token and user data without strong endpoint or approval safeguards.

Install only if you control the Juggle endpoint and token. Use an HTTPS trusted base URL, scope the token to only the needed workflows, confirm workflow key/version/parameters before execution, and avoid passing passwords or secrets through --flow-data because they can appear in shell history or process logs.

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

Warning
Location
scripts/flow.py:19
Finding

Authentication Token and Workflow Data Can Be Sent to an Untrusted or Unencrypted Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/flow.py:19-20, 40-61, 97-118
Vulnerability Type: Unvalidated network destination and possible plaintext transmission of sensitive data
Risk Level: Medium

Vulnerable Code

python
BASE_URL = os.getenv("MC_JUGGLE_BASE_URL")
JUGGLE_TOKEN = os.getenv("MC_JUGGLE_TOKEN")
python
url = f"{BASE_URL.rstrip('/')}/open/v1/flow/trigger/{flow_version}/{flow_key}"

headers = {
    "Content-Type": "application/json",
    "Juggle-Token": JUGGLE_TOKEN
}

request_body = {}
if flow_data:
    request_body["flowData"] = flow_data

response = requests.post(
    url,
    headers=headers,
    json=request_body if request_body else None,
    timeout=30
)
python
url = f"{BASE_URL.rstrip('/')}/v1/open/flow/getAsyncFlowResult/"

params = {
    "flowInstanceId": flow_instance_id
}

headers = {
    "Content-Type": "application/json",
    "Juggle-Token": JUGGLE_TOKEN
}

response = requests.get(
    url,
    headers=headers,
    params=params,
    timeout=30
)

Technical Analysis

Sending a Juggle API token and workflow input to the configured Juggle service is necessary for the Skill's declared workflow-triggering functionality. However, the implementation accepts MC_JUGGLE_BASE_URL without validating its scheme, hostname, port, or origin.

Consequently, the token is attached to requests made to any destination supplied through that environment variable. An http:// URL is accepted, allowing the Juggle-Token, workflow input, and workflow instance identifiers to traverse the network without transport encryption. A malicious or incorrectly configured URL can instead send these values directly to an attacker-controlled server.

The calls also use the default redirect behavior of requests. Because Juggle-Token is a custom authentication header rather than the standard Authorization header, applications should ...[truncated 1918 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse MC_JUGGLE_BASE_URL with urllib.parse.urlparse and reject malformed URLs.
  2. Require the https scheme by default. If HTTP is genuinely required for isolated development, place it behind an explicit opt-in flag and restrict it to loopback or approved private hosts.
  3. Reject URLs containing embedded user information, fragments, unexpected paths, or unapproved ports.
  4. Support an administrator-defined hostname allowlist or pin the expected Juggle origin during credential setup. For self-hosted deployments, store the approved origin alongside the token rather than accepting a destination independently for each execution.
  5. Disable automatic redirects with allow_redirects=False. If redirects are required, follow them manually only after confirming that the scheme, hostname, and port match the approved origin.
  6. Use a dedicated requests.Session with centrally enforced TLS, redirect, proxy, and timeout policies.
  7. Provide a configurable CA bundle for private deployments instead of encouraging TLS verification to be disabled.
  8. Scope Juggle tokens to only the workflow operations and workflow keys required by the Skill, and rotate any token suspected of having been sent to an untrusted destination.
  9. Warn users before transmitting fields identified as credentials or secrets, and avoid collecting such fields unless the selected workflow strictly requires them.

T09 · Insecure Skill Coding Practices

Warning
Location
references/flow_spec.md:20
Finding

Workflow Passwords Are Passed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: references/flow_spec.md:20-35, 76-81
Vulnerability Type: Sensitive information exposure through command-line arguments and shell history
Risk Level: Medium

Vulnerable Documentation

The workflow specification explicitly defines a password as workflow input:

markdown
| Parameter | Type | Required | Description |
| userName | String | Yes | Username |
| password | String | Yes | Password |
| deposit | Integer | Yes | Deposit amount |

**Input example**:
```json
{
    "flowData": {
        "userName": "juggle",
        "password": "123456",
        "deposit": 666
    }
}
text

It then directs users to place that password directly in a command-line argument:

```bash
python /workspace/projects/juggle/scripts/flow.py trigger \
  --flow-version "v1" \
  --flow-key "sync_example" \
  --flow-data '{"userName": "juggle", "password": "123456", "deposit": 666}'

Technical Analysis

The example value is demonstrative, but the documented invocation pattern instructs users to replace it with actual workflow input. When a real password is supplied through --flow-data, the complete JSON value becomes part of the process argument vector.

Command-line arguments may be exposed through:

  • Shell history files.
  • Process inspection tools such as ps.
  • /proc/<pid>/cmdline on systems whose process visibility settings permit access.
  • Terminal session recording.
  • Job-runner, orchestration, and CI/CD execution logs.
  • Monitoring or endpoint-management software that records process creation events.

Environment variables would not fully solve secret handling, but embedding passwords in a normal CLI argument is especially likely to create durable or broadly visible copies. This exceeds the minimum exposure necessary to submit workflow input because the script could accept data through standard input, a protected file descriptor ...[truncated 1274 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add a standard-input mode, such as --flow-data-stdin, and document it as the preferred mechanism:
    bash
    printf '%s' "$FLOW_JSON" | python scripts/flow.py trigger \
      --flow-version v1 --flow-key sync_example --flow-data-stdin
    
    Ensure automation does not echo the input.
  2. Support reading JSON from a protected file using --flow-data-file, and require or recommend owner-only permissions such as mode 0600.
  3. For known secret fields, provide an interactive prompt using Python's getpass module so input is not echoed or stored in shell history.
  4. Remove password-bearing command examples from the documentation. Use clearly non-sensitive fields in ordinary CLI examples.
  5. Add a warning that --flow-data must not be used for passwords, tokens, private keys, or regulated personal data.
  6. In CI/CD environments, use the platform's secret injection mechanism and pass secret data through standard input or a protected temporary file that is securely deleted after use.
  7. Review whether the demonstration workflow legitimately needs a raw password. Prefer short-lived credentials, scoped tokens, or server-side secret references where possible.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The script builds the request destination from the MC_JUGGLE_BASE_URL environment variable and sends authenticated requests containing the JUGGLE token to that host. If an attacker can influence the environment or credential configuration, this enables SSRF-like outbound requests and credential exfiltration to an arbitrary server, which is especially sensitive because the token is included in the header.

Content

Scanner excerpt · scripts/flow.py (reported line 63)May include surrounding context.

python
try:
        # 发送 POST 请求
        response = requests.post(
            url,
            headers=headers,
            json=request_body if request_body else None,

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The GET request target is also derived from MC_JUGGLE_BASE_URL and is used with the same authentication header. A malicious or misconfigured base URL could redirect the client to an attacker-controlled endpoint, disclosing the Juggle token and allowing unintended network access from the runtime environment.

Content

Scanner excerpt · scripts/flow.py (reported line 118)May include surrounding context.

python
try:
        # 发送 GET 请求
        response = requests.get(
            url,
            headers=headers,
            params=params,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill requires environment secrets and performs networked workflow execution, but it does not declare any explicit tool scope or permission boundary. That increases the chance an agent can invoke external actions and use credentials without clear authorization constraints, especially in an automation skill designed to trigger workflows.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Saying related trigger words can trigger corresponding workflows without sufficient constraints creates an unsafe mapping from vague language to privileged external actions. Because this skill is specifically built to identify and trigger workflows automatically, an attacker or even a normal user could cause unintended process execution through imprecise phrasing or prompt injection in surrounding context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger condition is broad enough that routine user language such as '执行工作流' or '调用流程' could activate a real external workflow without a tightly defined intent check. In this skill's context, activation leads to network calls against a workflow engine, so ambiguity can cause unintended execution of operational or business processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file includes cURL and Python examples that send identifiers such as orderId, userId, flowData, and flowInstanceId to a remote API, but the surrounding documentation does not warn users that these requests transmit workflow and user data off-system. For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that could affect user data or privacy.

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 · references/api_spec.md (reported line 183)May include surrounding context.

流程触发示例

cURL 示例

bash
curl -X POST "https://api.juggle.plus/open/v1/flow/trigger/v1/order-process" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/api_spec.md (reported line 185)May include surrounding context.

cURL 示例

bash
curl -X POST "https://api.juggle.plus/open/v1/flow/trigger/v1/order-process" \
  -H "Content-Type: application/json" \
  -H "Juggle-Token: your-token-here" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/api_spec.md (reported line 200)May include surrounding context.

cURL 示例

bash
curl -X POST "https://api.juggle.plus/open/v1/flow/trigger/v1/order-process" \
  -H "Content-Type: application/json" \
  -H "Juggle-Token: your-token-here" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/api_spec.md (reported line 221)May include surrounding context.

cURL 示例

bash
curl -X POST "https://api.juggle.plus/open/v1/flow/trigger/v1/order-process" \
  -H "Content-Type: application/json" \
  -H "Juggle-Token: your-token-here" \
  -d '{

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 · references/api_spec.md (reported line 212)May include surrounding context.

} }

response = requests.post(url, headers=headers, json=data) result = response.json() print(result)

text

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

文档在 L127-L156 将异步结果查询接口的响应描述为 result 直接承载最终输出,执行中时甚至可能为 null,未声明 status 或嵌套 data 字段。但 L244-L253 的 Python 示例却读取 result["result"]["status"] 和 result["result"]["data"],这与前述接口定义直接冲突,会误导实现方按错误的数据结构处理响应。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The workflow specification explicitly requires a username and password and provides example credential values, but it gives no warning about sensitive credential handling, storage, logging, or privacy risks. In an automation skill, this omission is risky because users may copy the pattern into real workflows and inadvertently expose secrets in requests, logs, screenshots, or documentation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The command-line example passes the password directly on the command line in plaintext, which can expose it through shell history, process listings, audit logs, and terminal recordings. Because this skill is designed for workflow automation, users are especially likely to operationalize the example as-is, making credential leakage more likely in real environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file’s natural-language interface is entirely in Chinese, including the module description, error messages, CLI help text, and user-facing prompts. This imposes a specific language on users without opt-in or any indication that the skill is intentionally region-specific, which matches the language/locale policy-violation category.

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

python
try:
        # 发送 POST 请求
        response = requests.post(
            url,
            headers=headers,
            json=request_body if request_body else None,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The entire specification is written in Chinese and does not provide an alternative language, opt-in, or note that the locale is intentionally region-specific. Under SQP-3, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.