Back to skill

Security audit

poe1-build-analyst

Security checks for vulnerabilities and agentic risk

Overview

The skill’s stated PoE build-analysis purpose is mostly coherent, but its local execution and network handling are under-scoped enough that users should review it before installing.

Install only if you are comfortable running local PoB tooling from a controlled environment. Use a known absolute pob installation, keep PATH and POB_CLI_ROOT under your control, prefer local trusted PoE Ninja JSON exports over arbitrary URLs, and avoid feeding untrusted large character codes until size limits and stricter source validation are added. The artifact does not show hidden uploads, persistence, or destructive behavior, but its execution boundary is not tight enough for a broadly privileged agent runtime.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/poe1_build_pipeline.py:25
Finding

Arbitrary URL Retrieval Enables Server-Side Request Forgery

Content
View full analysis
Any: if path_or_url.startswith(("http://", "https://")): req = urllib.request.Request(path_or_url, headers={"User-Agent": "poe1-build-analyst/1.0"}) with urllib.request.urlopen(req, timeout=30) as response: return json.loads(response.read().decode("utf-8")) return json.loads(Path(path_or_url).read_text(encoding="utf-8")) ``` ### Technical Analysis The `--ninja-json` argument is passed to `load_json`, which accepts any URL beginning with `http://` or `https://`. It does not restrict the hostname to PoE Ninja or another approved public data provider. The standard URL opener also follows redirects. Consequently, validating only the initial scheme does not prevent an external server from redirecting the request to a loopback, private-network, or link-local destination. The requested response is parsed as JSON, and candidate rows extracted from it can be copied into the generated report. Although the code does not intentionally transmit local files or credentials, it grants broader network access than the Skill's declared need to retrieve public PoE build statistics. ### Attack Path 1. An attacker supplies an internal URL through `--ninja-json`, such as an HTTP service on loopback, a private network, or a link-local metadata address. 2. Alternatively, the attacker supplies a public URL that redirects to such an internal address. 3. `urllib.request.urlopen` performs the request from the environment running the Skill. 4. If the response is valid JSON in a supported structure, `rows_from_payload` extracts its records. 5. The retrieved records are included in the generated output report, potentially exposing internal response data. ### Impact Assessment Succes ...[truncated 433 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/poe1_build_pipeline.py:110
Finding

Environment-Controlled Python Import Path Allows Module Hijacking

Content
View full analysis
dict[str, Any]: """Mandatory PoB TreeData gate for every XML entering official analysis.""" build_file = Path(build_path).resolve() root = ET.parse(build_file).getroot() spec = root.find("Tree/Spec") if spec is None: raise ValueError("PoB XML 缺少 Tree/Spec;拒絕進入計算") tree_version = spec.get("treeVersion") or spec.get("tree_version") if not tree_version: raise ValueError("Tree/Spec 缺少 treeVersion;拒絕進入計算") nodes = [int(value) for value in spec.get("nodes", "").replace("\\n", ",").split(",") if value.strip()] class_value = spec.get("classId") class_id = int(class_value) if class_value not in (None, "") else None cli_root = os.environ.get("POB_CLI_ROOT", "/home/ubuntu/poe1-pob-cli") if cli_root not in sys.path: sys.path.insert(0, cli_root) from pob_cli.treedata import validate_tree_selection result = validate_tree_selection(pob_root, tree_version, nodes, class_id=class_id) if not result.get("valid"): raise ValueError("天賦連通性驗證失敗:" + "; ".join(result.get("errors", []))) return result ``` From `scripts/poe1_tree_optimizer.py`: ```python def load_treedata(pob_root: str, tree_version: str) -> tuple[dict[int, dict[str, Any]], dict[int, set[int]]]: cli_root = os.environ.get('POB_CLI_ROOT', '/home/ubuntu/poe1-pob-cli') if cli_root not in sys.path: sys.path.insert(0, cli_root) from pob_cli.treedata import load_tree_data data = load_tree_data(str(Path(pob_root).resolve()), tree_version) ``` ```python def validate_selection(pob_root: str, tree_v ...[truncated 2456 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/poe1_build_pipeline.py:60
Finding

PATH-Based PoB Resolution Allows Executable Spoofing

Content
View full analysis
str: """Resolve only the intended `pob` executable; never execute user-supplied commands.""" command = shutil.which("pob") if not command or Path(command).name != "pob" or not os.access(command, os.X_OK): raise RuntimeError("找不到受信任的 pob 執行檔;本 skill 不接受自訂或任意外部命令") return str(Path(command).resolve()) ``` The resolved command is executed here: ```python def run_pob(args: list[str], timeout: int = 120) -> tuple[int, str, str]: """Run the fixed PoB CLI with bounded runtime and captured output.""" command = resolve_pob_command() if not args or Path(args[0]).name != "pob": raise ValueError("拒絕執行非 pob 命令") safe_args = [command, *args[1:]] try: completed = subprocess.run( safe_args, text=True, capture_output=True, check=False, timeout=max(1, min(timeout, 600)), cwd=os.getcwd() ) ``` From `scripts/poe1_tree_optimizer.py`: ```python def resolve_pob_command() -> str: """Resolve only the intended `pob` executable; never execute user-supplied commands.""" command = shutil.which('pob') if not command or Path(command).name != 'pob' or not os.access(command, os.X_OK): raise RuntimeError('找不到受信任的 pob 執行檔;本 skill 不接受自訂或任意外部命令') return str(Path(command).resolve()) ``` ### Technical Analysis `shutil.which("pob")` returns the first matching executable found through the process's `PATH`. The subsequent checks establish only that: - A matching path was found. - Its basename is `pob`. - The current process can execute it. These checks do not verify that the executable is the reviewed `qpooqp777/pob-cli` binary. An attacker-controlled execu ...[truncated 1577 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/poe1_build_pipeline.py:165
Finding

Unbounded Character-Code Decompression Enables Resource Exhaustion

Content
View full analysis
bytes: normalized = code.strip() if normalized.startswith(('https://pobb.in/', 'http://pobb.in/')): raise ValueError('請提供完整 PoB character code,不要提供短 pobb.in 網址;短網址不是可直接解碼的 code。') normalized += "=" * (-len(normalized) % 4) encoded = base64.urlsafe_b64decode(normalized) for wbits in (zlib.MAX_WBITS, -zlib.MAX_WBITS): try: return zlib.decompress(encoded, wbits) except zlib.error: continue raise ValueError('PoB character code 不是可解壓縮的 zlib/raw-deflate XML code') ``` The result is subsequently written to disk: ```python xml = decode_pob_code(load_code_argument(args.pob_code)) if not xml.lstrip().startswith(b'
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
copies; `SKILL.zh-TW.md` and `SKILL.zh-CN.md` are localized reference copies. `SKILL.md` remains the active default skill.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly says the active skill's default language is English, which imposes a language preference as part of the skill behavior. Under the policy, forcing or defaulting to a specific language without offering user choice or opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill explicitly instructs use of network access, shell commands, file reads/writes, and environment variables, but the manifest does not declare any tool restrictions or permission scope. In an agent environment, that mismatch can enable broader-than-necessary capability use, increasing the blast radius if untrusted PoB XML, character codes, or fetched data are processed unsafely or if the skill is invoked in an overly privileged runtime.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description explicitly includes 'early/mid/endgame passive trees, gem links, equipment targets, metrics, and PoB character codes'. But the body of the skill says 'Endgame-only' and explicitly states 'Early and Mid configurations are not generated in this workflow' at L010 and L107-L108. This is an active contradiction between the skill's own top-level documentation and its operational instructions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill repeatedly states that the workflow is Endgame-only and that Early and Mid configurations are intentionally omitted, notably at L010 and L105-L108. However, the output contract then requires sections for 'Early configuration' and 'Mid configuration', which directly conflicts with the stated workflow boundaries and could cause an agent to produce outputs the skill says it should not generate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

该文件在描述和标题中明确标注为“简体中文参考版”,且整体指令内容仅以简体中文给出,没有说明用户可选择其他语言或根据用户偏好切换语言。根据规则,未经用户选择而强制特定语言/locale 属于自然语言政策违规。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

檔案描述與標題明確將此技能定義為「繁體中文參考版」,屬於自然語言上的語言/locale 限制。依規則,若未明確提供使用者語言選擇或 opt-in,這類強制特定語言的設計應視為政策違反。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document title and all instructional content are written in Traditional Chinese, which imposes a specific language on users without stating that language selection is optional. Under the policy, language-specific behavior is only acceptable when the skill offers user choice or clearly documents a justified locale constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The instruction '每個階段都要輸出' appears in a Chinese-language skill note and mandates a fixed output structure in that language context, but nowhere in the file offers the user a choice of language or explains a justified locale restriction. Under the stated policy, forcing a specific language or locale without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code includes user-facing runtime messages entirely in Traditional Chinese, such as the trusted executable and command rejection errors. Because the file does not offer any language selection or opt-in, it imposes a specific language/locale on users, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/poe1_build_pipeline.py (reported line 74)May include surrounding context.

python
raise ValueError("拒絕執行非 pob 命令")
    safe_args = [command, *args[1:]]
    try:
        completed = subprocess.run(
            safe_args, text=True, capture_output=True, check=False,
            timeout=max(1, min(timeout, 600)), cwd=os.getcwd()
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code continues to present end-user validation feedback in Chinese only, including PoB code decoding errors. This is a natural-language policy issue because the skill enforces a specific language for interactive CLI feedback without offering users a choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The primary command-line interface exposes multiple help strings, warnings, and status descriptions in Chinese only. Since there is no visible mechanism for language selection and no documented justification for a Chinese-only audience, this violates the language/locale policy constraint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes this skill as generating, comparing, and verifying PoE1 builds using PoE Ninja research, pob-cli analysis, and staged recommendations. However, this file also dispatches an optimize-tree subcommand into a separate tree optimizer module, which is a materially different capability than the documented pipeline/reporting behavior and is not justified anywhere in this file's stated purpose or module docstring.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code includes multiple natural-language error and warning strings in Traditional Chinese, such as the exceptions and runtime errors emitted to users. Because the skill does not offer any language selection or explain that it is intentionally region-specific, it violates the policy against forcing a specific language without user opt-in.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/poe1_tree_optimizer.py (reported line 170)May include surrounding context.

python
def run_pob_calc(build: str, pob_root: str, skill: str) -> dict[str, Any]:
    args = [resolve_pob_command(), 'calc', build, '--pob-root', pob_root, '--skill', skill, '--format', 'json', '--timeout', '120']
    try:
        proc = subprocess.run(args, capture_output=True, text=True, check=False, timeout=120, cwd=os.getcwd())
    except subprocess.TimeoutExpired as exc:
        raise RuntimeError('PoB calc 執行逾時') from exc
    stdout = proc.stdout[-MAX_POB_OUTPUT:]

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

Line L005 states that the active default language is English, which is a natural-language locale constraint. While localized documentation exists, the text does not indicate that users can choose their preferred language at runtime or opt into English, so this may conflict with a language-choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

L005 明确写明“主动技能默认语言为英文”,但未说明用户可选择其他语言或进行语言偏好设置。按规则,强制或默认施加特定语言且无用户 opt-in 可视为自然语言层面的语言/地区策略违例。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill states 'Default to English' and only switches to Traditional or Simplified Chinese when requested. This is a natural-language locale default that may conflict with a policy requiring language choice or explicit opt-in, since the user is not first offered a language selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The file says 'README.md' is English user-facing documentation and that 'SKILL.md remains the active default skill,' while localized copies are secondary. This indicates a fixed default locale rather than an explicit user-selected language.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The value "冰霜流派名稱" is a natural-language string in Chinese, and the template provides no indication that users may choose another language or that the file is intentionally limited to a Chinese locale. This can create a language/locale policy issue because it implicitly forces a specific language in a general-purpose template.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.