Back to skill

Security audit

1Panel Appstore skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent 1Panel package generator, but its generated packages can include under-validated executable init scripts and YAML produced from untrusted spec fields.

Install only if you will review generated docker-compose.yml and scripts/init.sh before placing the package in 1Panel. Use official sources or trusted specs only, avoid prepared specs from untrusted parties, and be especially careful with any generated init.sh, host mounts, privileged/container namespace settings, or unusual Compose keys.

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

Error
Location
scripts/generate_app_package.py:391
Finding

Arbitrary Shell Commands Can Be Embedded in Generated Initialization Scripts

Content
View full analysis
None: commands = [str(item).rstrip() for item in spec.get("init_commands") or []] fixes = collect_permission_fixes(spec, services) scripts_dir = version_dir / "scripts" if not commands and not fixes: if scripts_dir.exists(): shutil.rmtree(scripts_dir) return evidence = [str(item).strip() for item in spec.get("init_source_evidence") or [] if str(item).strip()] if not evidence: fail("init.sh content requires init_source_evidence from official repository or documentation") scripts_dir.mkdir(exist_ok=True) lines = [ "#!/bin/bash", "", "# Generated from official installation evidence:", *[f"# - {item}" for item in evidence], "", ] if commands: lines.extend(commands) ``` The resulting script is subsequently written to disk and made executable: ```python init_path = scripts_dir / "init.sh" init_path.write_text("\n".join(lines), encoding="utf-8") init_path.chmod(0o755) ``` ### Technical Analysis The generator accepts the `init_commands` array from the input JSON specification and copies every entry verbatim into a Bash script. There is no command allowlist, shell-token validation, metacharacter filtering, or structured representation of permitted initialization operations. The only security gate is the presence of at least one non-empty `init_source_evidence` string. The generator does not validate that the evidence URL is project-owned, that it exists, or that it supports the supplied command. An attacker can therefore provide an arbitrary evidence string while embedding shell operators, command subst ...[truncated 1511 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_app_package.py:130
Finding

Unescaped Mapping Keys Permit YAML Structure Injection

Content
View full analysis
list[str]: pad = " " * indent lines: list[str] = [] if isinstance(value, dict): for key, item in value.items(): if isinstance(item, (dict, list)): lines.append(f"{pad}{key}:") lines.extend(dump_yaml(item, indent + 2)) else: lines.append(f"{pad}{key}: {scalar(item)}") elif isinstance(value, list): for item in value: if isinstance(item, dict): first = True for key, subitem in item.items(): ``` User-controlled service names become YAML mapping keys at line 521: ```python write_yaml( version_dir / "docker-compose.yml", { "services": {svc["name"]: service_to_compose(svc, primary_name) for svc in services}, "networks": {"1panel-network": {"external": True}}, }, ) ``` Other user-controlled dictionaries, including labels and environment mappings, also pass through the same serializer. ### Technical Analysis The serializer applies `scalar()` escaping to values but emits mapping keys directly with string interpolation. A key containing a newline, colon, comment marker, or other YAML syntax can therefore terminate the intended key and introduce additional YAML nodes. Service names are read directly from the input specification and are not restricted to a safe Compose service-name pattern. Similar exposure exists for user-controlled environment and label keys. A malicious key can consequently change the structure or meaning of the generated `docker-compose.yml` rather than remaining a literal key. For example, a crafted service name con ...[truncated 1871 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `references/appstore-format.md` for 1Panel package rules.

Docker Socket Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · references/review-checklist.md (reported line 58)May include surrounding context.

md
- No unexpected `privileged: true`.
- No host network unless justified.
- No dangerous host mounts such as `/`, `/etc`, or `/var/run/docker.sock` unless explicitly required.
- Avoid unpinned `:latest` images unless the upstream application only publishes `latest`.
- Secrets are form fields with `type: password`.

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Code deploys a privileged Kubernetes workload (privileged container, hostPath mount, or host namespaces). This grants root on the node and is a node/cluster takeover vector.

Content

Scanner excerpt · references/review-checklist.md (reported line 56)May include surrounding context.

md
BUILTIN_VARS = {"CONTAINER_NAME", "HOST_IP", "HOST_ADDRESS"}
LANG_KEYS = ["en", "es-es", "ja", "ms", "pt-br", "ru", "ko", "zh-Hant", "zh", "tr"]
RISKY_PATTERNS = {
    "privileged: true": "privileged containers require explicit review",
    "network_mode: host": "host networking should be avoided unless required",
    "pid: host": "host PID namespace should be avoided",
    "/var/run/docker.sock": "docker socket mount is high risk",

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Code deploys a privileged Kubernetes workload (privileged container, hostPath mount, or host namespaces). This grants root on the node and is a node/cluster takeover vector.

Content

Scanner excerpt · scripts/validate_app_package.py (reported line 16)May include surrounding context.

python
BUILTIN_VARS = {"CONTAINER_NAME", "HOST_IP", "HOST_ADDRESS"}
LANG_KEYS = ["en", "es-es", "ja", "ms", "pt-br", "ru", "ko", "zh-Hant", "zh", "tr"]
RISKY_PATTERNS = {
    "privileged: true": "privileged containers require explicit review",
    "network_mode: host": "host networking should be avoided unless required",
    "pid: host": "host PID namespace should be avoided",
    "/var/run/docker.sock": "docker socket mount is high risk",

Docker Socket Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · scripts/validate_app_package.py (reported line 19)May include surrounding context.

python
"privileged: true": "privileged containers require explicit review",
    "network_mode: host": "host networking should be avoided unless required",
    "pid: host": "host PID namespace should be avoided",
    "/var/run/docker.sock": "docker socket mount is high risk",
    "- /:/": "root filesystem mount is high risk",
    "- /etc:": "host /etc mount is high risk",
}

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill explicitly instructs use of Python scripts, writes package artifacts, and implies shell execution, but it does not declare any tool scope restrictions such as allowed tools or permissions. In an agent environment, this increases the blast radius by permitting broader file and shell access than necessary, which can lead to unintended file modification, command execution, or abuse if the skill is invoked on adversarial input.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The instruction requires generating the root README.md specifically in a Chinese appstore style using the heading ## 产品介绍, while English is only conditional. This imposes a specific language/locale behavior in the skill instructions without offering the user a choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file requires additionalProperties.description to include a specific set of languages and later requires every form field label to include the full appstore language set. This is a natural-language locale policy constraint presented as mandatory behavior, with no indication that language selection is optional or user-driven.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Requiring every label to include the full language set imposes a fixed locale policy across all generated packages. Under the stated rule, mandatory language constraints should either offer user choice or be clearly documented as justified for a region- or platform-specific use case.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Line L28 requires additionalProperties.description to include a specific list of locales. This forces locale coverage as policy without offering user choice or documenting why those languages are mandatory.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The generator copies spec-controlled init_commands directly into a generated init.sh and marks it executable. Because this skill packages apps from external specs, a malicious or unreviewed spec can embed arbitrary shell code that will later run during installation with the privileges of the installer, turning a packaging tool into a code-execution mechanism.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The validator rejects packages unless README.md contains the Chinese heading '## 产品介绍' and README_en.md contains the English heading '## Introduction'. This is a natural-language locale requirement embedded in code, and the file does not indicate that this constraint is optional, user-selectable, or justified as a region-specific compliance rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

Line L09 requires README_en.md whenever the upstream app or docs support English. This is a natural-language locale requirement, and the file does not present it as an optional user choice or explain a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code writes multiple generated files to disk and later can also remove an existing scripts directory, but beyond generic function names there is no docstring, comment, or user-facing disclosure explaining which filesystem locations will be modified or deleted. Because this is a code file, filesystem-modifying operations should have some visible warning unless they are clearly disclosed as part of the skill behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script removes an existing scripts directory with shutil.rmtree when no init commands or permission fixes are present, but there is no confirmation prompt or explicit warning message about this deletion. Although the script is a generator, this specific destructive action is not disclosed to the user at the point it occurs.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.