Back to skill

Security audit

Cloudflare Open WebUI Tunnel Operator

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for setting up a Cloudflare tunnel, but it asks users to handle persistent credentials and account changes without enough safety controls.

Review this skill before installing. Use a narrowly scoped Cloudflare API token and a dedicated 1Password service account, avoid broad vault write access, store any runtime env file with owner-only permissions outside source control and backups, rotate/delete tokens when no longer needed, and require confirmation before DNS, tunnel, systemd, or 1Password changes.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
WORKFLOW.md:22
Finding
Insufficiently protected local credential materialization and persistent secret-manager access<![CDATA[ ## Vulnerability Details **File Location**: `WORKFLOW.md:22-26`; supporting guidance in `FAQ.md:23-26` **Vulnerability Type**: Plaintext credential storage and excessive credential exposure to a persistent service **Risk Level**: Medium ### Vulnerable Documentation ```text 7. fetch the tunnel runtime token and write a local env file 获取 tunnel 运行 token 并写入本地 env 文件 8. start `cloudflared` in Docker 用 Docker 启动 `cloudflared` 9. enable `systemd` if reboot persistence is required 如果要求跨重启持久化,启用 `systemd` ``` The related FAQ states: ```text ## Why must `systemd` use the same `op` binary as the shell? | 为什么 `systemd` 必须使用和 shell 相同的 `op`? Because the working shell command may actually be a wrapper that injects a service-account token before calling the real CLI. 因为 shell 里能工作的命令,实际可能是一个包装器:它先注入 service-account token,再调用真正的 CLI。 ``` ### Technical Analysis The workflow requires a Cloudflare tunnel runtime credential to be written to a local environment file, but it does not define: - A secure file location - Restrictive ownership and permissions - A protected creation procedure such as `umask 077` - Rotation or deletion requirements - Backup and log exclusions - Protection against accidental source-control inclusion - Whether the credential is exposed to other containers or processes The FAQ also contemplates a persistent `systemd` service invoking an `op` wrapper that injects a 1Password service-account token. The documentation does not require that this service-account token be read-only, restricted to one vault item, or removed from the runtime service after initial provisioning. Using a Cloudflare tunnel token is necessary for the declared functionality. Retrieving it from Cloudflare is not, by itself, evidence of exfiltration. The security issue is the unspecified local handling and the possibility of granting a long-lived service access to a more powerful secret-manager credential than it needs. ### Attack Path 1. An authorized operat ...[truncated 1663 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the runtime credential file in a dedicated, root-owned directory using `umask 077` and explicit mode `0600`. 2. Restrict ownership to the exact account running `cloudflared`. 3. Do not place credentials directly in shell command arguments, Docker Compose files, systemd unit text, logs, or command transcripts. 4. Prefer Docker secrets, systemd credentials, or an equivalent protected runtime secret mechanism instead of a general-purpose environment file. 5. Ensure only the `cloudflared` process receives the tunnel runtime token. Do not expose it to unrelated containers. 6. Use a dedicated 1Password service account with read-only access to the single required item. 7. Separate provisioning from runtime operation. The persistent tunnel service should receive only its tunnel token and should not routinely access 1Password. 8. Add systemd hardening such as `NoNewPrivileges=yes`, a dedicated service account, filesystem restrictions, and an explicit minimal environment. 9. Document token rotation, revocation, secure deletion, backup exclusions, and source-control exclusions. 10. Require operators to verify file permissions and service credential scope before enabling persistence. ]]>

T05 · Unauthorized Access and Privilege Escalation

Note
Location
WORKFLOW.md:28
Finding
Unnecessary write access to the 1Password credential item<![CDATA[ ## Vulnerability Details **File Location**: `WORKFLOW.md:28-29`; repeated in `SKILL.md:42` and `FAQ.md:13-16` **Vulnerability Type**: Excessive secret-manager privileges **Risk Level**: Low ### Vulnerable Documentation ```text 11. backfill `account_id` into 1Password if it was inferred 如果 `account_id` 是推断出来的,则回填到 1Password ``` The FAQ further instructs: ```text ## Can `account_id` be inferred from the zone? | `account_id` 可以从 zone 推断吗? Yes, but it is better to write it back into the 1Password item after the first successful run. 可以,但最好在第一次成功执行后回填到 1Password 条目中。 ``` ### Technical Analysis Creating and operating the Cloudflare tunnel requires reading the Cloudflare credential and resolving the relevant account. It does not require modifying the credential record in 1Password. Automatically writing an inferred `account_id` back to the item expands the required authorization from read-only secret consumption to vault mutation. This violates least privilege for the core tunnel workflow and increases the consequences of an agent error or compromised execution context. Although an account identifier is generally not secret, the containing 1Password item is a security-sensitive record. The workflow does not require explicit confirmation, validate that the inferred account belongs to the intended zone, or separate this optional metadata update from normal operation. ### Attack Path 1. The operator grants the Skill or its 1Password service account permission to edit the Cloudflare item. 2. The workflow derives an account identifier from Cloudflare API data. 3. Incorrect configuration, ambiguous account selection, or attacker-influenced input causes the wrong identifier to be selected. 4. The workflow writes the incorrect value into the shared 1Password record. 5. Subsequent automation trusts the persisted value and operates against the wrong account or fails in a way that disrupts tunnel management. 6. A compromised process holding the same writ ...[truncated 857 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Keep the normal workflow and its service-account credential read-only. 2. Store inferred non-secret metadata in a separate local configuration file rather than modifying the credential item. 3. Make backfilling an optional administrative action that is separate from tunnel creation and runtime operation. 4. Require explicit operator confirmation before any 1Password update. 5. Validate the inferred account identifier against both the intended Cloudflare zone and the operator-selected account. 6. Display the target item and field name without displaying secret values before requesting confirmation. 7. Use a separate, short-lived, narrowly scoped credential for the update operation. 8. Restrict write permission to the specific item and field where the platform supports such controls. 9. Record a non-secret audit event for the update and provide rollback instructions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (3)

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly instructs operators to write the runtime Cloudflare tunnel token to a local environment file, but it does not require secure storage controls, restrictive file permissions, lifecycle limits, or cleanup guidance. A locally persisted tunnel token can be exposed through backups, shell access, logs, accidental commits, or weak filesystem permissions, enabling unauthorized tunnel use or service impersonation.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The workflow explicitly instructs fetching a tunnel runtime token and writing it to a local env file, but it provides no warning or controls around file permissions, storage location, rotation, cleanup, or exclusion from logs and version control. In a skill specifically handling infrastructure access and secrets, this omission creates a realistic credential exposure path if the env file is world-readable, persisted unnecessarily, or accidentally committed.

Natural-Language Policy Violations

Low
Confidence
74% confidence
Finding
The packaging rule says that if the audience is mixed, the docs must be bilingual. This is a natural-language locale policy constraint rather than an offered choice, and no opt-in mechanism or justification is provided in the file.

Static analysis

No suspicious patterns detected.