Back to skill

Security audit

tencentcloud-oceanus-ops

Security checks for vulnerabilities and agentic risk

Overview

This Oceanus operations skill is not evidently malicious, but it should be reviewed because it can change TencentCloud resources and has under-scoped credential and upload paths.

Review before installing. Use least-privilege and preferably short-lived TencentCloud credentials, avoid storing permanent keys in shell profiles, do not set OCEANUS_ENDPOINT unless you fully trust the destination, validate any COS upload/download URLs before sharing or using them, and manually confirm every resource-changing operation.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/client.py:32
Finding
Unvalidated API Endpoint Override Exposes Credential Material and Workload Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/client.py:32-34` and `scripts/client.py:163-202` **Vulnerability Type**: Unvalidated credential-bearing network destination **Risk Level**: High ### Vulnerable Code ```python _DEFAULT_HOST = "oceanus.tencentcloudapi.com" HOST = os.environ.get("OCEANUS_ENDPOINT", _DEFAULT_HOST) ENDPOINT = f"https://{HOST}" ``` ```python secret_id, secret_key = get_credentials() timestamp = int(time.time()) date = datetime.fromtimestamp(timestamp, tz=timezone.utc).strftime("%Y-%m-%d") payload = json.dumps(params) authorization = _build_authorization( secret_id, secret_key, service, date, str(timestamp), payload ) connect_timeout = int(os.environ.get("OCEANUS_API_CONNECT_TIMEOUT", "10")) read_timeout = int(os.environ.get("OCEANUS_API_READ_TIMEOUT", "60")) headers = { "Authorization": authorization, "Content-Type": "application/json; charset=utf-8", "Host": HOST, "X-TC-Action": action, "X-TC-Timestamp": str(timestamp), "X-TC-Version": version, "X-TC-Region": region, "User-Agent": DEFAULT_USER_AGENT, } token = os.environ.get("TENCENTCLOUD_SECURITY_TOKEN", "") if token: headers["X-TC-Token"] = token try: req = Request( ENDPOINT, data=payload.encode("utf-8"), headers=headers, method="POST", ) resp = urlopen(req, timeout=max(connect_timeout, read_timeout)) ``` ### Technical Analysis The API host is taken directly from the `OCEANUS_ENDPOINT` environment variable without validating that it is an approved TencentCloud endpoint. All Oceanus API calls are subsequently sent to this destination. Each request includes: - The TencentCloud SecretId inside the `Authorization` header. - A request signature derived from the SecretKey. - The complete STS security token when temporary credentials are used. - The complete serialized API payload. - Operation, region, version, and timestamp metadata. The long-term SecretKey is not transmitted d ...[truncated 1803 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `OCEANUS_ENDPOINT` overrides from production execution unless they are operationally required. 2. If endpoint overrides are necessary for testing, require an explicit development-mode option and reject them by default. 3. Parse the destination with `urllib.parse.urlsplit` and enforce: - HTTPS only. - No URL user information. - No path, query string, or fragment in a host override. - No unexpected port. - No IP literal. - An exact approved TencentCloud hostname or a narrowly defined allowlist. 4. Do not rely on a broad suffix check alone. Normalize the hostname and protect against suffix-confusion values such as `tencentcloudapi.com.attacker.example`. 5. Disable automatic redirects for credential-bearing requests, or validate every redirect destination before forwarding sensitive headers. 6. Never forward `Authorization` or `X-TC-Token` across an origin change. 7. Add unit tests covering malicious hosts, user-information syntax, ports, IP literals, malformed values, and redirect attempts. 8. Document any supported private endpoint explicitly and bind it to a trusted configuration source rather than an ambient environment variable. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/resource_management.py:221
Finding
Local Files Can Be Uploaded to an Unvalidated Presigned URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/resource_management.py:221-251` and `scripts/resource_management.py:342-362` **Related Locations**: `scripts/resource_change_ops.py:134-146` and `scripts/resource_change_ops.py:272-284` **Vulnerability Type**: Arbitrary outbound file upload and insufficient destination validation **Risk Level**: High ### Vulnerable Code ```python def upload_to_cos(presigned_url, file_path): """Upload local file to COS via presigned URL using HTTP PUT. This is a public API — other modules (e.g. job_development) may import and call it directly. """ try: file_size = os.path.getsize(file_path) content_type, _ = mimetypes.guess_type(file_path) if not content_type: content_type = "application/octet-stream" with open(file_path, "rb") as f: file_data = f.read() req = Request( presigned_url, data=file_data, method="PUT", ) req.add_header("Content-Type", content_type) req.add_header("Content-Length", str(file_size)) resp = urlopen(req, timeout=300) status = resp.getcode() ``` The caller uses the API-provided location without validating its destination: ```python presign_data = result.get("data", {}) presigned_url = presign_data.get("Location", "") bucket = presign_data.get("Bucket", "") key = presign_data.get("Key", "") cos_region = presign_data.get("Region", region) if not presigned_url: return output( error_response( "upload_resource", "GetPresignedUrlFailed", "Presigned URL response was empty", ), args.output, ) upload_result = upload_to_cos(presigned_url, file_path) ``` ### Technical Analysis The upload workflow obtains a `Location` value from an API response and passes it directly to `urllib.request.Request`. It does not verify: - That the URL uses HTTPS. - That the host is an appro ...[truncated 2639 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate the presigned URL inside `upload_to_cos()` so every caller receives the same protection. 2. Parse the URL with `urllib.parse.urlsplit` and enforce: - Scheme must be `https`. - Host must be a valid expected TencentCloud COS hostname. - User information must be absent. - Port must be absent or explicitly approved. - Fragment must be absent. 3. Verify that the URL hostname corresponds exactly to the `Bucket` and `Region` values returned by the API. 4. Pass the expected bucket and region to the upload function rather than validating the URL in only one caller. 5. Reject IP literals, localhost, link-local addresses, private network destinations, and malformed internationalized hostname variants. 6. Disable redirects for PUT uploads. If redirects are genuinely required, manually process them and revalidate every target before resending file contents. 7. Display the validated hostname, bucket, object key, and file size before final upload confirmation. 8. Stream the file rather than reading it fully into memory, while retaining strict destination validation. 9. Make the upload helper private unless external use is required. 10. Add tests for attacker-controlled domains, HTTP URLs, DNS-suffix confusion, internal IP addresses, unexpected ports, and cross-origin redirects. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/credential-setup.md:33
Finding
Long-Lived Cloud Credentials Are Persisted in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `references/credential-setup.md:33-92` **Vulnerability Type**: Plaintext persistent credential storage **Risk Level**: Medium ### Vulnerable Instructions The credential setup guide instructs users to append long-lived credentials to shell startup files: ```bash cat >> ~/.zshrc <<'EOF' # TencentCloud Oceanus credentials export TENCENTCLOUD_SECRET_ID="<SecretId>" export TENCENTCLOUD_SECRET_KEY="<SecretKey>" # export TENCENTCLOUD_SECURITY_TOKEN="<Token>" EOF chmod 600 ~/.zshrc source ~/.zshrc ``` ```bash cat >> ~/.bashrc <<'EOF' # TencentCloud Oceanus credentials export TENCENTCLOUD_SECRET_ID="<SecretId>" export TENCENTCLOUD_SECRET_KEY="<SecretKey>" # export TENCENTCLOUD_SECURITY_TOKEN="<Token>" EOF chmod 600 ~/.bashrc source ~/.bashrc ``` The guide also recommends persistent user-level environment variables on Windows: ```powershell [Environment]::SetEnvironmentVariable( "TENCENTCLOUD_SECRET_ID", "<SecretId>", "User" ) [Environment]::SetEnvironmentVariable( "TENCENTCLOUD_SECRET_KEY", "<SecretKey>", "User" ) ``` ```cmd setx TENCENTCLOUD_SECRET_ID "<SecretId>" setx TENCENTCLOUD_SECRET_KEY "<SecretKey>" ``` The placeholder values above represent the credential placeholders in the audited guide; no real credential values were present in the repository. ### Technical Analysis The instructions persist reusable TencentCloud credentials in plaintext shell initialization files or user-level operating-system environment configuration. Restricting a Unix startup file to mode `0600` reduces exposure to other local users, but it does not encrypt the credentials or protect them from: - Malware or compromised applications running under the same account. - Accidental inclusion in backups or support bundles. - Developer tools and extensions that can read user files. - Processes that inherit the environment. - Diagnostic collection and process inspection. - Unintended disclosure of shell co ...[truncated 1674 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer short-lived STS credentials instead of permanent access keys. 2. Recommend an operating-system credential manager, managed secret broker, or supported TencentCloud credential provider rather than shell startup files. 3. Inject credentials only into the process or terminal session that needs them. 4. Avoid placing credentials in `.zshrc`, `.bashrc`, fish startup configuration, registry-backed persistent environment variables, or equivalent cross-session storage. 5. Provide a wrapper that retrieves short-lived credentials at invocation time without printing them. 6. Require least-privilege CAM policies limited to necessary Oceanus operations and resources. 7. Document credential expiration, revocation, and rotation procedures. 8. Advise users to audit inherited environments and prevent unrelated applications from receiving cloud credentials. 9. If file-based storage must be supported, use an encrypted credential store and verify restrictive ownership and permissions. 10. Add explicit warnings that permanent environment variables are accessible to same-user processes and may be captured by backups or diagnostic tooling. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (47)

Tainted flow: 'req' from os.environ.get (line 196, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers=headers,
            method="POST",
        )
        resp = urlopen(req, timeout=max(connect_timeout, read_timeout))
        resp_body = json.loads(resp.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
91% confidence
Finding
The request destination is derived from the OCEANUS_ENDPOINT environment variable and then used to build the signed request URL and Host header. In an agent or automation context, environment variables are part of the execution trust boundary; if an attacker can influence them, they can redirect requests to an arbitrary host and receive authenticated API payloads and headers, enabling SSRF-style egress and possible credential/signature misuse against a malicious endpoint.

Ae1

High
Category
analysis-evasion
Content
- `scripts/unit_test.py` — offline unit tests for pure-logic helpers (no network / no credentials). Run via `python scripts/unit_test.py` or `python -m unittest
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
### For mutation/destructive operations
```
--confirm                  # Required flag to bypass safety check
```

## Safety Level Definitions
Confidence
96% confidence
Finding
The phrase 'bypass safety check' explicitly instructs the operator to override a protective control for mutation/destructive operations. In an operational skill that can create, modify, run, and stop production Oceanus jobs, normalizing safety-bypass language increases the chance that an agent or user treats confirmation as a mere formality rather than a deliberate authorization step.

Instruction Override

High
Category
Prompt Injection
Content
### For mutation/destructive operations
```
--confirm                  # Required flag to bypass safety check
```

## Safety Level Definitions
Confidence
94% confidence
Finding
This wording functions like an instruction to override a safety mechanism by presenting --confirm as the way to get past protections. Even though it is documentation rather than executable code, agent skills use such mappings operationally, so this can steer downstream automation to append --confirm routinely and suppress meaningful human-in-the-loop checks.

Self-Modification

High
Category
Rogue Agent
Content
### For mutation/destructive operations
```
--confirm                  # Required flag to bypass safety check
```

## Safety Level Definitions
Confidence
90% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Credential Access

High
Category
Privilege Escalation
Content
| `TENCENTCLOUD_SECRET_KEY`       | Yes              | Matching secret key |
| `TENCENTCLOUD_SECURITY_TOKEN`   | Only for STS     | Temporary credential token |

Get keys from the [腾讯云 CAM 控制台](https://console.cloud.tencent.com/cam/capi).

## Persistent configuration templates by OS
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
"不用确认草稿". Implied urgency or convenience is NOT sufficient.
2. When the draft summary is displayed, you MUST present it to the user and
   **wait for explicit approval** ("确认发布", "OK", "没问题", "发布吧")
   before proceeding. Do NOT auto-approve on behalf of the user.
3. If the CLI outputs the draft to a temporary file, read and display the
   key changes (SQL diff / resource changes / config deltas) to the user.
4. Violation of this gate is a **critical protocol breach** — equivalent to
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
3. If the CLI outputs the draft to a temporary file, read and display the
   key changes (SQL diff / resource changes / config deltas) to the user.
4. Violation of this gate is a **critical protocol breach** — equivalent to
   executing a destructive operation without consent.

- `--skip_draft_confirm`: skip the review (**automation-only flag**; agent
  must NEVER use it unless user explicitly opted out of review).
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. NEVER read, print, or echo their values (no `echo $TENCENTCLOUD_*`,
   `env | grep TENCENT`, `printenv`, …).
2. NEVER ask the user to paste keys into chat. Have them configure locally.
3. Never embed credentials in command arguments or generated files. The CLI
   reads them from the environment.
4. If a tool result accidentally surfaces a credential value, redact it
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The protocol classifies `check_sql` as both a read operation and a write operation that modifies draft state, creating ambiguity about whether side effects occur. In an agentic execution setting, that inconsistency can cause the agent to run a state-changing command under weaker safeguards than intended, leading to unauthorized or unexpected modifications.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- Folder: `describe_folder`, `query_folder`
- Resource: `describe_tree_resources`, `create_presigned_url`

**Rule**: Execute immediately without confirmation.

### Mutation Operations (create/modify resources)
- Job: `create_job`, `create_job_config`, `run_jobs`, `trigger_savepoint`
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Treating a broad direct-imperative phrase like "帮我创建" as implicit approval weakens the explicit confirmation barrier for mutation operations. An attacker or ambiguous prompt can trigger resource creation without a distinct consent step, especially in multi-turn conversations where user intent may be inferred incorrectly.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**Rule**: Require `--confirm` flag. If user gives direct imperative ("帮我创建"), treat as approved.

### Write Operations (safe, no confirmation needed)
- `modify_draft`, `check_sql`

**Rule**: Execute directly (no `--confirm`). These modify draft state but are safe / idempotent.
Confidence
91% confidence
Finding
The protocol explicitly allows `modify_draft` and `check_sql` to execute without confirmation because they are considered safe, even though at least one of them modifies draft state. Removing confirmation for state-changing actions enables silent changes to user assets or configurations, which is especially risky in an agent that may act on ambiguous user instructions.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This markdown file documents the `delete_folders` command as destructive but does not include any user-facing warning, safeguard note, or confirmation requirement in the description. For markdown files, destructive behaviors that could affect user data or system integrity should be accompanied by explicit warnings.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The `stop_jobs` command is marked as destructive, but the catalog entry does not warn users that stopping running jobs may interrupt workloads or affect system state. In markdown documentation, potentially disruptive operations should include clear user warnings.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
export TENCENTCLOUD_SECRET_KEY="你的SecretKey"
# export TENCENTCLOUD_SECURITY_TOKEN="你的Token"   # 仅临时凭证需要
EOF
chmod 600 ~/.zshrc
source ~/.zshrc
```
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
export TENCENTCLOUD_SECRET_KEY="你的SecretKey"
# export TENCENTCLOUD_SECURITY_TOKEN="你的Token"   # 仅临时凭证需要
EOF
chmod 600 ~/.zshrc
source ~/.zshrc
```
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
export TENCENTCLOUD_SECRET_KEY="你的SecretKey"
# export TENCENTCLOUD_SECURITY_TOKEN="你的Token"   # 仅临时凭证需要
EOF
chmod 600 ~/.zshrc
source ~/.zshrc
```
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
### Linux / macOS with fish shell — `~/.config/fish/conf.d/tencentcloud.fish`

```fish
mkdir -p ~/.config/fish/conf.d
cat > ~/.config/fish/conf.d/tencentcloud.fish <<'EOF'
set -gx TENCENTCLOUD_SECRET_ID "你的SecretId"
set -gx TENCENTCLOUD_SECRET_KEY "你的SecretKey"
Confidence
76% confidence
Finding
The fish-shell template persists long-lived cloud credentials to disk in a shell startup file, which increases the exposure window if the local account, backups, dotfile sync, or developer tooling are compromised. Although the file recommends restrictive permissions and never pasting secrets into chat, persistent plaintext storage of access keys is still a real security concern in an ops skill context.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The section is explicitly titled 'Reusable Chinese reply template' and mandates a Chinese response template for the agent. This is a natural-language locale constraint, but the file does not offer user opt-in or explain a justified region-specific requirement, which fits the language/locale policy violation category.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| Code | Meaning | Recovery |
|------|---------|----------|
| MissingCredentials | Env vars not set | **Stop execution** and guide the user to persist credentials in a shell/OS config file based on their OS (macOS → `~/.zshrc`; Linux bash → `~/.bashrc`; fish → `~/.config/fish/conf.d/*.fish`; Windows → `setx` / `[Environment]::SetEnvironmentVariable(... "User")`). Never ask the user to paste secrets into chat, never echo/print env vars, and never write keys to repo files. See `references/credential-setup.md` for the full per-OS template and the `MissingCredentials` recovery flow. |
| ValidationError | Required parameter missing | Add the missing --parameter |
| SafetyCheckRequired | Mutation without --confirm | Add --confirm flag |
| Cancelled | User cancelled interactively | Re-run with --confirm if intended |
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This markdown file uses Chinese throughout its operational instructions, examples, and error guidance, which effectively forces a specific language for users. Under the policy, language constraints should either be optional for the user or clearly justified as region-specific; that justification is not stated here.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The playbook instructs users to generate pre-signed COS download URLs for job logs but does not warn that these URLs confer temporary direct access to potentially sensitive operational data and can be shared or leaked via terminals, chat, tickets, or shell history. In an observability/ops context, logs often contain stack traces, identifiers, endpoints, and occasionally secrets, so omission of handling guidance materially increases the chance of unintended disclosure.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This markdown file contains user-facing operational instructions in Chinese and does not indicate that language selection is optional. The policy explicitly calls for flagging language or locale constraints when a skill forces a specific language without user opt-in.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/credential-setup.md:84

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/unit_test.py:118