T09 · Insecure Skill Coding Practices
- Location
scripts/workflow-engine.py:399- Finding
Environment Secrets Can Be Substituted into Arbitrary Outbound Requests
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This workflow skill is broadly useful in concept, but it gives custom workflows unrestricted command, file, network, and environment-variable access without adequate safeguards.
Install only if you intend to run trusted, locally reviewed workflows and are comfortable treating workflow JSON as executable code. Do not run workflows from untrusted sources, especially on machines with API keys or tokens in the environment, and avoid using this engine for destructive cleanup until shell execution, environment interpolation, path restrictions, and dry-run behavior are fixed.
scripts/workflow-engine.py:399Environment Secrets Can Be Substituted into Arbitrary Outbound Requests
scripts/workflow-engine.py:339Untrusted Workflow Definitions Provide Unrestricted Shell Command Execution
scripts/workflow-engine.py:221Arbitrary Downloads Can Be Chained with Shell Execution to Run Remote Payloads
scripts/workflow-engine.py:190Recursive File Deletion Is Not Restricted to an Authorized Workspace
scripts/workflow-engine.py:497Advertised Dry-Run Option Is Ignored and Does Not Prevent Side Effects
scripts/workflow-engine.py:57Workflow-Controlled Log Name Permits Path Traversal and Unsafe Temporary-Directory Writes
The skill documents backup and other automation flows that can overwrite, move, or delete data, but provides no warning about irreversible actions or scheduling risks. In an auto-executing workflow context, users may enable tasks that continue running and cause repeated data loss without realizing the consequences.
The engine implements a generic shell.exec action using subprocess.run(..., shell=True), which enables arbitrary command execution far beyond the documented workflow purposes. Because the skill also supports custom workflows, any user-supplied or attacker-influenced workflow can execute OS commands, read/write sensitive files, or launch follow-on attacks.
Using subprocess.run with shell=True on workflow-supplied command text allows shell metacharacter interpretation and direct OS command execution. In this skill's context, that means a crafted workflow can chain file access, secret expansion, and network operations into full command-injection and system-compromise scenarios.
print(f" 💻 执行:{cmd}")
try:
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True, timeout=60
)
print(f" ✅ 完成")
The code enumerates all environment variables and makes them available for substitution into workflow-controlled strings. This is a classic secret-harvesting primitive because credentials from the runtime environment can be injected into files, network requests, or shell commands without any per-secret approval.
text = text.replace('{day}', now.strftime('%d'))
# 替换环境变量
for key, value in os.environ.items():
text = text.replace(f'{{{key}}}', value)
# 替换上下文变量
The engine explicitly exposes a shell.exec workflow action, which extends the skill from automation into arbitrary code execution. Because the skill is designed for automatic workflow execution, this capability materially increases risk: a crafted workflow can run system commands, pivot to network actions, or modify local files far beyond a narrow automation purpose.
The subprocess invocation is directly parameterized by workflow input and executed with shell=True, so the workflow file acts as code. In an automation skill that can be triggered on behalf of users, this is a tool-parameter abuse path that can execute arbitrary commands, bypass intended workflow semantics, and compromise the execution environment.
timeout = params.get('timeout', CONFIG['timeout'])
try:
log(f" 执行:{cmd}", 'info', 2)
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True, timeout=timeout
)
if result.returncode == 0:
Enumerating os.environ.items() and applying substitutions into workflow-controlled text creates a broad secret-harvesting surface. In this engine, the expanded values can be routed into HTTP requests, shell commands, saved files, or logs, making credential exfiltration straightforward for any untrusted workflow.
text = text.replace('{minute}', now.strftime('%M'))
# 环境变量
for key, value in os.environ.items():
text = text.replace(f'{{{key}}}', value)
# 上下文变量
The skill exposes capabilities for filesystem access, network access, environment-variable access, and shell execution, but declares no explicit tool scope or permissions boundaries. In an automation skill that can run custom workflows, this lack of scoping increases the chance of over-privileged execution and makes dangerous behavior harder to audit or restrict.
Broad trigger phrases like '自动化', '工作流', and 'automate' are likely to match many ordinary requests, causing the skill to activate in contexts where users did not intend privileged automation. Because this skill can perform destructive file operations, network access, and custom workflow execution, accidental invocation materially increases risk.
The documentation and implemented behavior are inconsistent: documented actions include image/upload/cleanup capabilities that are not implemented, while the code includes undocumented shell execution. This mismatch can mislead reviewers and users about the true attack surface, causing unsafe trust decisions and insufficient approval controls.
The skill supports HTTP/API workflows but does not warn that workflow data may be sent to external services. Combined with environment-variable expansion and custom workflows, this can lead to unintentional exfiltration of local files, workflow outputs, or secrets to remote endpoints.
The variable expansion logic iterates over the full process environment and substitutes any matching token into workflow parameters. This gives workflows access to unrelated secrets and runtime context such as API keys or tokens, enabling accidental disclosure through files, HTTP requests, or shell commands.
This is a manifest file, so vague-trigger checks apply. The description "备份指定目录到压缩包" describes a general backup action but does not define specific invocation phrases, scope limits, or exclusion conditions, which could allow unintended activation for broad backup-related requests.
The workflow is described as backing up a specified directory to an archive, which is already covered by the dedicated archive step. Using shell.exec to run mkdir introduces command-execution capability that is not clearly justified by the stated backup purpose, since directory creation could be handled by safer built-in file operations.
The manifest context emphasizes file processing and workflow automation, and this specific workflow claims only to back up a directory into an archive. Running ls -lh via shell.exec adds a general shell capability unrelated to the core archive creation behavior and broadens what the workflow can do beyond the narrowly described task.
The workflow supports deleting arbitrary files or directories, including recursive directory removal, with no confirmation, path restriction, or safety interlock. In an auto-executing workflow system, a malicious or mistaken workflow can irreversibly destroy data, especially when combined with variable expansion or user-provided paths.
The skill allows arbitrary shell execution without meaningful safety boundaries or prominent warnings, which is especially dangerous for an automation engine that may process externally authored workflows. This enables workflows to chain file, network, and command actions into full remote-control behavior on the host.
The workflow engine executes a workflow-supplied command via subprocess.run(..., shell=True), which permits arbitrary shell execution. In an agent skill context where workflow files or parameters may be influenced by users or other automated systems, this becomes a direct command-execution primitive and can lead to full host compromise, data theft, or destructive actions.
timeout = params.get('timeout', CONFIG['timeout'])
try:
log(f" 执行:{cmd}", 'info', 2)
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True, timeout=timeout
)
if result.returncode == 0:
The parameter-expansion logic iterates over all environment variables and substitutes them into workflow-controlled strings. This allows any workflow author to reference secrets such as API keys, tokens, credentials, or internal endpoints and then exfiltrate them through logs, HTTP requests, file writes, or shell commands.
The CLI advertises a --dry-run mode, but no such control is implemented. Users may reasonably rely on this documented safety feature and accidentally trigger real file deletion, network access, downloads, archive extraction, or shell execution while believing they are only simulating a workflow.
Most of the skill’s natural-language instructions and examples are presented only in Chinese, despite including English trigger terms like “workflow” and “automate.” This creates an implicit language constraint without opt-in, language selection, or documentation that the skill is intended solely for a Chinese-speaking context.
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
The manifest uses Chinese-only natural-language metadata for the skill name and description, with no indication that language selection is optional or that the workflow is intentionally region-specific. This can violate a language/locale policy when users are not offered a choice or informed of the locale constraint.
Natural-language strings in the module header, help text, logs, and status messages are presented in Chinese only, with no indication that users may choose another language. This creates a locale policy concern because the skill effectively enforces a specific language without opt-in or justification.
No suspicious patterns detected.