Back to skill

Security audit

huo15-huihuo-suite

Security checks for vulnerabilities and agentic risk

Overview

This Odoo ERP skill is mostly coherent, but it can perform major business changes without enforceable confirmation safeguards.

Review before installing. Use a limited Odoo account and a revocable API key, do not configure an http:// server, and require human confirmation outside the skill before posting payments, posting or canceling invoices, confirming sales or purchase orders, validating stock, approving HR items, deleting records, changing another person's RSVP, or sharing tokenized document links. Enable heartbeat or cron polling only if users understand what data will be checked and how often.

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:183
Finding

Odoo credentials can be transmitted over plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/odoo_client.py:183-187, scripts/odoo_client.py:229-237, scripts/odoo_client.py:259-264
Vulnerability Type: Cleartext transmission of authentication credentials
Risk Level: High

Technical Analysis

normalize_url() adds HTTPS only when the supplied address has no recognized scheme. An explicitly supplied http:// address remains unchanged:

python
def normalize_url(url: str) -> str:
    """Normalize the system address and add HTTPS when no scheme is present."""
    url = (url or "").strip().rstrip("/")
    if url and not url.startswith(("http://", "https://")):
        url = "https://" + url
    return url

The resulting URL is then used for authentication. Both supported transports include the Odoo password or API key in requests to the configured server:

python
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, {})

The JSON-RPC path likewise sends its request directly to the configured scheme:

python
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"))

The URL can originate from interactive initialization, login.py set --url, HUO15_ODOO_URL, or the saved configuration. Although the default address is HTTPS and scheme-less addresses are upgraded, explicit HTTP remains accepted without warning or an unsafe-mode gate.

Attack Path

  1. The Skill is configured with an Odoo endpoint beginning with http://.
  2. The user supplies a password or API key during ...[truncated 800 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject all non-HTTPS remote endpoints in normalize_url() and again immediately before authentication.
  • If plaintext HTTP is required for local development, require an explicit unsafe option and restrict it to loopback addresses such as 127.0.0.1 and ::1.
  • Never permit the unsafe option when password authentication is selected.
  • Emit a clear error before reading or sending the secret when the URL does not satisfy the transport policy.
  • Consider validating TLS certificates using the platform trust store and documenting any supported private certificate-authority configuration.
  • Add tests confirming that http://example.com is rejected while scheme-less addresses are normalized to HTTPS.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/accounting.py:301
Finding

Consequential ERP operations bypass the documented confirmation requirement

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:328, references/commands.md:205, references/odoo-sales-purchase-stock-api.md:11, scripts/accounting.py:232-240, scripts/accounting.py:301-325, scripts/sales.py:133-146, scripts/purchase.py:138-155, scripts/stock.py:134-143, scripts/hr.py:310-318, scripts/hr.py:388-402
Vulnerability Type: Missing enforceable authorization confirmation for high-impact operations
Risk Level: High

Technical Analysis

The Skill documentation requires confirmation before deletion, archival, bulk state changes, and consequential sales, purchasing, inventory, and invoice operations. However, the executable interfaces contain no confirmation parameter, interactive approval prompt, confirmation token, or dry-run gate.

For example, payment creation immediately proceeds to posting:

python
def cmd_pay(odoo: Odoo, args):
    """Register a payment."""
    partner_id = _resolve(odoo, "res.partner", args.partner, "Customer/Supplier")
    journals = odoo.search_read(
        AJ, [("type", "in", ("bank", "cash")), ("active", "=", True)],
        ["name", "type"], limit=1)
    if not journals:
        raise OdooError("No available bank or cash payment journal was found.")
    journal_id = journals[0]["id"]

    vals = {
        "payment_type": args.type,
        "partner_type": args.partner_type,
        "partner_id": partner_id,
        "amount": args.amount,
        "journal_id": journal_id,
        "date": args.date or today(),
    }
    if args.memo:
        vals["memo"] = args.memo
    pid = odoo.create(AP, vals)
    odoo.execute_kw(AP, "action_post", [[pid]])

Sales confirmation directly changes the order state and can create a delivery order:

python
def cmd_confirm(odoo: Odoo, args):
    odoo.execute_kw(SO, "action_confirm", [[args.id]])
    print(f"Sales order #{args.id} was confirmed.")

Inventory validation is partic ...[truncated 2903 chars]

Remediation
View remediation

Remediation Suggestions

  • Require a mandatory confirmation mechanism for every consequential command, such as a short-lived confirmation token bound to the exact operation and arguments.
  • Do not rely solely on a generic --yes flag that an Agent can add automatically. Bind approval to a preview containing the record ID, operation, amount, partner, quantities, and side effects.
  • Implement a two-phase workflow:
    1. A read-only preview returns normalized operation details and a digest.
    2. Execution requires the user-approved digest or confirmation token.
  • Add dry-run support and make it the default for payment, posting, cancellation, order confirmation, invoice or bill generation, stock validation, and HR approval operations.
  • For inventory, display each product, requested quantity, actual completed quantity, and backorder decision. Do not automatically set all quantities to the requested amount unless the user explicitly approved that exact behavior.
  • For payments, display the direction, amount, currency, partner, journal, date, and memo before posting.
  • Apply the confirmation gate inside executable code so direct script invocation cannot bypass it.
  • Add automated tests proving that consequential methods are not called without a valid, operation-bound confirmation.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description represents a one-stop, multi-domain Odoo enterprise assistant, but the supplied code is narrowly scoped to testing acceptance workflows. Its primary purpose is bug tracking and sprint/tag management in custom Odoo testing models, including state-machine transitions like confirm/start/resolve/verify/reopen and bug statistics. That is materially different from the declared broad coverage of CRM, calendar, documents, accounting, HR, attendance, and similar modules. While both target the same huo15 Odoo environment, the behavior here is a specialized subset that is not accurately described, and it also adds a distinct testing/QA capability not mentioned in the declaration.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger rules are extremely broad and auto-bind ordinary workplace terms like tasks, meetings, invoices, attendance, and reminders to a high-privilege enterprise system skill. This creates a prompt-routing vulnerability where unrelated conversation can invoke credentialed actions or data access in Odoo without sufficiently specific user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Lines L011-L015 state a mandatory external-branding policy using Chinese terms such as '辉火云企业套件 / 辉火云' and require README content to follow that naming, with no indication that users may choose another language or locale. This is a natural-language locale policy constraint that appears unconditional rather than opt-in or region-justified within the file.

Content

No source excerpt is available for this finding.

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 · README.md (reported line 72)May include surrounding context.

--url www.huo15.com --db huo15 --login 你的账号 --auth-type apikey

text

凭据保存在个人文件 `~/.huo15/tools.md`(自动 `chmod 600`),可用环境变量 `HUO15_TOOLS_MD` 改路径。**该文件含明文凭据,请勿提交 git。**

### ② 待办

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes capabilities that involve shell execution, filesystem access, environment-variable use, and networked Odoo operations, but it does not declare an explicit tool scope such as allowed-tools or permissions. In a credential-handling enterprise skill, that omission is dangerous because it leaves the runtime with broad, implicit authority and weakens policy enforcement around secret files, command execution, and outbound connections.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Many aliases are common conversational phrases such as '提醒我', '加任务', '本周安排', and '员工管理', which can collide with normal assistant interactions. In the context of a skill that can access enterprise records and perform writes, ambiguous aliases increase the chance of unintended activation, data exposure, or accidental modification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

L180 明确要求 bug-delete 在非管理员账号下报“友好中文提示”,这属于自然语言层面的语言/locale 约束。文档未说明该技能仅面向中文用户或提供语言选择,因此存在强制单一语言输出的组织政策风险。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The guidance explicitly recommends running heartbeat checks on a schedule and proactively notifying users based on task, activity, and meeting data, but it does not require clear user consent or a prominent disclosure that continuous monitoring is occurring. In an enterprise Odoo context, this can normalize background surveillance of work patterns and calendar metadata, creating privacy and trust risks even if the data access is otherwise legitimate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This documentation explicitly describes state-changing accounting operations such as posting, reverting to draft, canceling, and reversing entries, all of which can modify financial records and trigger side effects in Odoo. In the context of an agent skill that may operationalize these instructions, the lack of an explicit confirmation/warning pattern increases the risk that an automated workflow or user could perform irreversible or audit-relevant actions without understanding the consequences.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The example shows creating a payment and immediately calling action_post, which records a financial transaction with real accounting effect. In this skill's enterprise Odoo context, an agent could mirror this pattern and post payments without a clear user-facing warning or confirmation, causing unauthorized ledger changes, reconciliation issues, or fraudulent/erroneous payment records.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation explicitly instructs callers to invoke public attendee methods to accept, decline, or tentatively respond on behalf of any partner, rather than restricting changes to the authenticated user. In a company Odoo skill handling internal meetings and reminders, this enables unauthorized modification of attendance records, which can misrepresent approvals, disrupt scheduling, and undermine auditability and trust in calendar workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file describes hr.py expense-post as invoking hr.expense.action_post, which earlier in the document is noted to automatically create accounting entries and be irreversible. However, the command mapping where a user would likely look for available actions does not repeat or foreground that warning, increasing the risk of unintended destructive use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document explicitly recommends a public download endpoint that is accessible with an access token, but it does not warn that the token functions as a bearer secret. If this guidance is copied into an agent workflow, the agent may expose share links in logs, chats, or notes, allowing anyone with the tokenized URL to download the document without normal authentication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example shows reading access_token values and constructing download URLs without any caution about secure handling. In an agent skill context, examples strongly shape implementation behavior, so this can lead to token extraction, storage, or replay in insecure channels, effectively turning private documents into publicly retrievable resources.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file presents all operational guidance, warnings, and examples exclusively in Chinese. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, which is not present here.

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 file contains extensive natural-language instructions, help text, and examples entirely in Chinese, and the CLI help/output strings throughout the file also enforce that locale. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The cancel command deletes events or recurring series via unlink and action_mass_deletion, which are irreversible operations affecting user data. Although a success message is printed after deletion, there is no confirmation prompt or explicit warning immediately before performing the destructive action in this code file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The rsvp command allows the operator to change any attendee's response status by specifying --who, without verifying that the caller is that attendee or has an elevated calendar-management role. In a corporate Odoo environment this can falsify meeting attendance, override another user's intent, and create audit/integrity issues for scheduling and business workflows.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file’s own guidance correctly states that probability should not be manually written because Odoo CRM uses stage-driven/business-method invariants for win/loss and probability modeling, yet the update command exposes --probability and writes it directly to crm.lead. This creates an integrity flaw: users or downstream agents can set arbitrary probabilities that misstate pipeline health, forecasts, and sales KPIs, bypassing the intended workflow methods.

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 extensive natural-language descriptions, CLI help text, and status messages exclusively in Chinese. Because there is no opt-in, locale switch, or documented region-specific justification, it violates the language/locale policy for natural-language content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and all user-facing prompts/messages are written in Chinese, and the script provides no option to select another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Tainted flow: 'text' from pathlib.Path.read_text (line 148, 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 165)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
89% confidence
Finding

This Python file contains natural-language strings and output labels entirely in Chinese, including the module description, error messages, empty-state text, and status/priority labels. For a general-purpose utility module, this hard-codes a specific language/locale without offering user choice or documenting that the skill is intentionally limited to a Chinese-only context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

All natural-language descriptions, examples, help text, and status messages in the file are written in Chinese, with no indication that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The cancel subcommand invokes Odoo's purchase-order cancellation action immediately with no in-code confirmation, dry-run, or contextual warning. In this skill's ERP context, a mistaken or prompt-injected invocation could cancel real procurement records, disrupt receiving/invoicing workflows, and create business-process harm even if it does not directly enable code execution or privilege escalation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.