Back to skill

Security audit

Huo15 Furniture Mfg

Security checks for vulnerabilities and agentic risk

Overview

The skill is largely purpose-aligned for a manufacturing ERP assistant, but it needs Review because it handles ERP credentials and business records without technically enforcing its promised test-only HTTPS boundary.

Review before installing. Use only a least-privilege Odoo API key, confirm the configured URL is https://test.heysleep.cn with db=test, do not use production credentials until endpoint and HTTPS allowlisting are enforced, inspect every dry-run preview before approving --yes, and treat generated PDFs as sensitive business documents.

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/odoo_client.py:174
Finding

Unrestricted endpoint configuration can disclose Odoo credentials over plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/odoo_client.py:174-177, 199-211, 228-258; scripts/login.py:61-76, 86-91; scripts/report.py:72-79
Vulnerability Type: Insufficient endpoint validation and plaintext transmission of authentication secrets
Risk Level: High

Vulnerable Code

python
# scripts/odoo_client.py:174-177
def normalize_url(url: str) -> str:
    """Normalize the system address and add HTTPS when no scheme is supplied."""
    url = (url or "").strip().rstrip("/")
    if url and not url.startswith(("http://", "https://")):
        url = "https://" + url
    return url
python
# scripts/odoo_client.py:199-211
def authenticate(self) -> int:
    if not (self.url and self.db and self.login and self.secret):
        raise OdooError(
            "Credentials have not been initialized."
        )
    try:
        if self.transport == "jsonrpc":
            self.uid = self._jsonrpc(
                "common", "authenticate", [self.db, self.login, self.secret, {}]
            )
        else:
            common = xmlrpc.client.ServerProxy(f"{self.url}/xmlrpc/2/common")
            self.uid = common.authenticate(self.db, self.login, self.secret, {})
python
# scripts/odoo_client.py:228-258
def _jsonrpc(self, service: str, method: str, args: list):
    payload = {
        "jsonrpc": "2.0",
        "method": "call",
        "params": {"service": service, "method": method, "args": args},
        "id": 1,
    }
    req = urllib.request.Request(
        f"{self.url}/jsonrpc",
        data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
    )
    with urllib.request.urlopen(req, timeout=60) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    if data.get("error"):
        err = data["error"]
        msg = err.get("data", {}).get("message") or err.get("message") or str(err)

...[truncated 4963 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce an exact endpoint allowlist before storing configuration and again immediately before every request:
    • Scheme: https
    • Hostname: test.heysleep.cn
    • Database: test
    • Port: default HTTPS port unless an explicitly approved alternative is required
  2. Reject URLs containing embedded credentials, unexpected ports, fragments, or nonempty paths.
  3. Remove support for http://; do not silently downgrade or accept plaintext transport.
  4. Apply the same validation to values loaded from files and environment variables, not only interactive input.
  5. Centralize request construction so XML-RPC, JSON-RPC, and web-session authentication cannot bypass the policy.
  6. If custom endpoints are a legitimate future requirement, require an explicit administrative opt-in and clearly warn before transmitting credentials.
  7. Prefer scoped, revocable Odoo API keys rather than primary account passwords.
  8. Consider TLS certificate pinning or organization-managed trust configuration where the deployment model permits it.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/report.py:129
Finding

Predictable shared temporary report files allow information disclosure and symlink-based file overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/report.py:61, 129-145
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Medium

Vulnerable Code

python
# scripts/report.py:61
DEFAULT_OUT = Path("/tmp/fmfg-reports")
python
# scripts/report.py:129-145
out_dir = Path(args.out) if args.out else DEFAULT_OUT
out_dir.mkdir(parents=True, exist_ok=True)
safe_ref = re.sub(r"[^\w\-.]", "_", rec["name"])
safe_alias = re.sub(r"[^\w\-.]", "_", alias.split(".")[-1])
out_path = out_dir / f"{safe_ref}-{safe_alias}.pdf"

sess = WebSession(odoo)
sess.authenticate()
blob = sess.download_pdf(report_name, rec["id"])
out_path.write_bytes(blob)
print(f"✅ {out_path}")
print(f"   Document: {rec['name']} | Report: {report_name} | {len(blob) / 1024:.0f} KB")
print("   Send the PDF as a file message rather than a local path.")

Technical Analysis

Generated contracts, labels, delivery records, and work orders are written to the predictable shared directory /tmp/fmfg-reports. The filename is deterministically derived from the record name and report alias.

The implementation does not create a private temporary directory, enforce restrictive permissions, validate directory ownership, reject symbolic links, use exclusive file creation, or remove the report after delivery. Path.write_bytes() follows symbolic links and truncates an existing target.

On a multi-user system, another local user can predict report paths and potentially read generated business documents if filesystem permissions permit. A local attacker can also pre-create the output path as a symbolic link to another file writable by the process running the Skill.

Attack Path

  1. A local attacker predicts that a report such as SO-260531-758-contract.pdf will be generated.
  2. The attacker creates /tmp/fmfg-reports with attacker-controlled permissions before the legitimate user does, or places a symbolic link at t ...[truncated 938 chars]
Remediation
View remediation

Remediation Suggestions

  1. Create a private temporary directory using tempfile.mkdtemp() or tempfile.TemporaryDirectory().
  2. Ensure the directory has mode 0700 and is owned by the current user.
  3. Create report files with mode 0600 and exclusive semantics, such as os.open() with O_CREAT | O_EXCL | O_WRONLY and O_NOFOLLOW where supported.
  4. Use randomized filenames rather than deterministic record-based names.
  5. Reject symbolic links and verify that the output remains inside the intended directory after path resolution.
  6. When a user supplies --out, validate directory ownership and permissions before writing.
  7. Delete generated reports immediately after successful delivery, or provide a documented retention policy and cleanup mechanism.
  8. Avoid exposing sensitive record identifiers in temporary filenames where they are unnecessary.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented behavior presents a constrained manufacturing assistant with confirm-gated business actions, but the underlying behavior reportedly includes generic Odoo ORM access, JSON-RPC in addition to XML-RPC, and write/delete primitives such as unlink. That gap is dangerous because it enables arbitrary access to models and methods outside the declared workflows, allowing data exfiltration, unauthorized modification, or destructive deletion in the connected ERP environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

L03 明确将该技能定义为中文项目描述,且整份说明均以中文作为默认和唯一操作语言。根据规则,若技能强制特定语言而未提供用户 opt-in 或语言选择,属于自然语言层面的语言/区域策略违规。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document presents the skill as 'P0 全只读' while also documenting existing or planned write-capable paths gated by dry-run/--yes. This mismatch can cause reviewers, operators, or downstream agents to misclassify the skill as read-only and invoke it in contexts where write-capable tooling should be blocked or require stronger approval, increasing the risk of unintended state changes in the manufacturing system.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Labeling the core client as a '只读 ORM 封装' while the same repository guidance discusses write calls through the same codebase creates a deceptive trust boundary. If maintainers or agent frameworks rely on that description, they may grant broader execution than appropriate or skip safeguards, leading to unauthorized or accidental writes via shared client functionality.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill description and all user-facing examples are entirely in Chinese, with no indication that other languages are supported or that the locale restriction is intentional and user-selected. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares powerful capabilities such as shell, file read/write, environment access, and network access, but does not define any explicit tool scope or permission boundaries. In a skill that handles credentials and can reach a remote business system, this lack of restriction materially increases the chance of unintended file access, secret exposure, or arbitrary command execution beyond the stated business workflow.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The skill stores reusable credentials in a persistent local file and uses session-based access to a remote ERP system. While persistence is common, it creates a real security risk in this context because compromise of the local environment or overly broad file/tool access could expose credentials and enable ongoing unauthorized access to sensitive operational and customer data.

Content

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

md
inventory ("山隐主垫还有几张" "库存查询" "型号 C3 有货吗"), quality ("待检"
  "质检合格率" "最近有没有不合格"), purchasing ("采购到货了吗" "哪些采购单逾期"),
  customers ("亿美诺的档案" "这个客户成交多少"), daily overview ("今日总览"
  "晨报" "今天接了几单/发了几单"), write actions ("给这个单留言" "@张三跟进"
  "提醒冯广权周一回复客户" "交期改到20号" "生产提前到周三" "改这单报价"
  "把这个客户存一下" "工艺要求发给车间" "这个跟进做完了"), or documents
  ("打印合同" "发我唛头标签" "要个施工单 PDF"). Backed by the 和栖家居

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
channel analysis ("电商单占多少" "渠道分布"). Also triggers on: 和栖,
  heysleep, 床垫订单, 跟单, 交期, 制造单, 生产单, 发货状态, 山隐, 山宿,
  销售合约, 唛头, 拍照质检, 非标报价. First run: python3 scripts/login.py init
  (地址/数据库/账号/密码 → ~/.huo15/tools.md, chmod 600). Pure standard
  library, zero dependencies. Write actions are two-step confirm-gated
  (dry-run preview → user approves → --yes).
version: 1.4.0

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The alias list includes generic phrases such as "订单跟踪", "生产进度", "库存查询", "客户档案", and "今日总览" that are common user intents rather than narrowly scoped skill activators. The file does not provide exclusion conditions or negative examples to distinguish when these phrases should invoke this specific skill versus a different order, CRM, or reporting skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction "把脚本输出转成口语化中文摘要" forces a specific language for responses. There is no nearby opt-in, fallback, or user preference mechanism indicating that Chinese is optional or limited to a justified region-specific deployment.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example trigger phrases are broad, conversational, and overlap with normal chat about orders, production, inventory, and reminders. In an agent environment that auto-selects skills from natural-language cues, this can cause the manufacturing skill to activate unintentionally and expose internal business data or initiate confirm-gated write workflows in the wrong context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document provides operational instructions for state-changing actions such as message posting, deleting messages via unlink, creating activities, changing dates, and authenticating a web session to fetch PDFs, but it does so as direct implementation guidance without strong safety framing. In an agent context, this materially lowers the barrier to destructive or privacy-impacting actions and can lead to unauthorized writes, message deletion, document access, or misuse of authenticated sessions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The reference expands beyond the declared furniture-manufacturing scope into WeCom messaging, approval workflows, customer auto-creation, and marketing-data sync. In an agent skill, undocumented or weakly scoped action surfaces increase the chance of unintended cross-system effects, privilege overreach, and abuse of non-manufacturing integrations if the agent is later wired to these RPCs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file exposes additional write operations for completing and rescheduling activities that are not declared in the advertised write-action surface. In an agent setting, undeclared mutating capabilities are dangerous because orchestration or approval logic may rely on the documented action list, allowing the skill to modify task state and deadlines in ways users or reviewers did not anticipate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings that force a specific language/locale for usage instructions and later runtime output, but there is no opt-in or indication that the skill is intentionally limited to Chinese-speaking users. Under the policy, forcing a language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module documentation explicitly states the client is P0 read-only with no create/write, but the class exposes create, write, unlink, and generic call methods that can mutate or delete ERP records. In this skill context, the client is used for a manufacturing/ERP system handling orders, inventory, production, quality, and customer data, so this mismatch can cause downstream agents or reviewers to trust the module as safe for read-only use while it actually enables destructive operations.

Content

No source excerpt is available for this finding.

Tainted flow: 'text' from pathlib.Path.read_text (line 139, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/odoo_client.py (reported line 156)May include surrounding context.

python
+ block
            + "\n"
        )
    path.write_text(text, encoding="utf-8")
    try:
        os.chmod(path, 0o600)
    except OSError:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language strings in the docstring, CLI help, and printed output are all fixed in Chinese, with no option for users to select another language. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script emits an operational instruction telling an AI to take a locally generated file and send it directly to the user. In an agentic environment, this bypasses any separate authorization, data-classification, or human-review layer and can turn the tool into a direct exfiltration path for sensitive business documents such as contracts, labels, or work orders.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file presents all operational instructions in Chinese and does not indicate that the user can choose another language or that the skill is intentionally restricted to a Chinese-language audience. Under the policy, forcing a specific language without opt-in can be a natural-language policy issue unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code implements activity management commands, but they are not reflected in the module docstring command list. Hidden or undocumented state-changing operations are risky in agent-integrated tools because reviewers may approve the skill assuming a narrower capability set than actually exists.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code implements activity management commands, but they are not reflected in the module docstring command list. Hidden or undocumented state-changing operations are risky in agent-integrated tools because reviewers may approve the skill assuming a narrower capability set than actually exists.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This Python file contains natural-language text specifying a Chinese-only output format and byte-count assumptions for Chinese characters. That imposes a locale/language constraint without any user opt-in or documented justification, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language strings in the docstring, argument descriptions, and output are all fixed to Chinese, which can violate language/locale policy when no user choice is offered. There is no indication that the skill is intentionally region-specific or that users can select another language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code file connects to Odoo and performs a search_read against product inventory records, which is a networked data access operation. Although the script's purpose is inventory lookup, there is no confirmation, notice, or explicit disclosure in code output that it will access backend business data.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.