Back to skill

Security audit

Clawhub Package Full

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Odoo connector, but it needs review because it can change important business records and ships unsafe defaults for credentials, webhooks, and installation.

Install only after review by someone who administers the Odoo instance. Use a sandbox first, a dedicated least-privilege Odoo API user, HTTPS for any non-local Odoo URL, protected secret storage, and explicit human confirmation for creates, deletes, postings, approvals, receipts, manufacturing completion, and fuzzy smart actions. Disable the webhook unless needed; if enabled, bind it to localhost or a protected network, require a strong HMAC secret, and put body-size and rate limits in front of it. Prefer a pinned, verified installer rather than the unversioned npx command.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
odoo_skill/sync/webhook.py:31
Finding

Network-Exposed Webhook Server Permits Unauthenticated Event Injection by Default

Content
View full analysis
None: """Handle an incoming webhook POST request.""" content_length = int(self.headers.get("Content-Length", 0)) if content_length == 0: self._respond(400, {"error": "Empty body"}) return body = self.rfile.read(content_length) # Signature verification if self.webhook_secret: signature = self.headers.get("X-Odoo-Signature", "") expected = hmac.new( self.webhook_secret.encode("utf-8"), body, hashlib.sha256, ).hexdigest() if not hmac.compare_digest(signature, expected): logger.warning( "Webhook signature mismatch (remote=%s)", self.client_address[0], ) self._respond(401, {"error": "Invalid signature"}) return ``` ```python def __init__( self, port: int = 8069, host: str = "0.0.0.0", secret: str = "", ) -> None: self.port = port self.host = host self.secret = secret ``` ```python def start(self) -> None: """Start the webhook server in a background thread.""" _WebhookHandler.webhook_secret = self.secret _WebhookHandler.callbacks = self._callbacks _WebhookHandler.default_callback = self._default_callback self._server = HTTPServer((self.host, self.port), _WebhookHandler) ``` ### Technical Analysis The webhook server binds to `0.0.0.0` by default, making it reachable th ...[truncated 2012 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
odoo_skill/sync/webhook.py:36
Finding

Unbounded Webhook Request Body Enables Remote Resource Exhaustion

Content
View full analysis
None: """Handle an incoming webhook POST request.""" content_length = int(self.headers.get("Content-Length", 0)) if content_length == 0: self._respond(400, {"error": "Empty body"}) return body = self.rfile.read(content_length) ``` ### Technical Analysis The handler accepts the client-provided `Content-Length` value without imposing a maximum size. It then attempts to read the entire declared request body into memory before authentication or JSON parsing. The implementation uses the standard single-threaded `HTTPServer`. A client that sends data very slowly can occupy the sole request-processing thread, while a client that sends a very large body can force excessive memory allocation. Authentication does not mitigate this issue because body acquisition occurs before signature validation. Malformed or extreme `Content-Length` values can also raise uncaught conversion or input-processing exceptions because only JSON and Unicode errors are handled later in the request flow. ### Attack Path 1. The webhook listener is reachable by an attacker. 2. The attacker opens a connection and sends a POST request with an extremely large `Content-Length`. 3. The attacker either: - streams the body slowly to occupy the only server thread, or - sends a very large body to consume process memory. 4. The server blocks in `self.rfile.read(content_length)` or allocates resources proportional to the attacker-controlled size. 5. Legitimate webhook requests cannot be processed, and the hosting process may become unresponsive or terminate due to memory exhaustion. ### Impact Assessment A remote unauthenticated attacker can disrupt webhook availability. Because the server is single-threaded, one slow r ...[truncated 380 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
odoo_skill/config.py:61
Finding

Odoo API Credentials Can Be Transmitted over Plaintext HTTP

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
README.md:31
Finding

Installation Instructions Execute an Unpinned Runtime-Resolved NPM Package

Content
View full analysis
Remediation
View remediation
`. 2. Use lockfiles and registry integrity metadata where supported. 3. Prefer an already installed and independently verified CLI rather than downloading executable code during each installation. 4. Publish and document checksums or signatures for Skill artifacts. 5. Use a trusted registry and avoid registry overrides during installation. 6. Review new installer versions before updating the documented pin. 7. Run installation with a least-privileged account and avoid administrator or root privileges. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (32)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 74)May include surrounding context.

md
1. Log in to Odoo
2. Go to **Settings** → **Users & Companies** → **Users**
3. Open your user record
4. Scroll to **Access Tokens**
5. Click **Generate**
6. Copy the key into `config.json`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
1. Log in to Odoo
2. Go to **Settings** → **Users & Companies** → **Users**
3. Open your user record
4. Scroll to **Access Tokens**
5. Click **Generate**
6. Copy the key into `config.json`

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description represents a broad, full-featured Odoo connector with many operational capabilities across numerous ERP modules. The actual code chunk is narrowly focused on configuration management: loading Odoo credentials and related settings from environment variables or JSON, validating required fields, and configuring logging. This is a supporting component of such a connector, not evidence of the claimed end-user functionality. Because the supplied code chunk does not actually implement the declared connector behavior and instead only handles setup/configuration, the description does not accurately represent what this code chunk does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad Odoo ERP connector with many business-module operations and XML-RPC integration. This code chunk instead provides a narrow webhook receiver: it starts an HTTP server, handles inbound POST/GET requests, verifies an HMAC signature, parses JSON, and routes events to callbacks. That is materially different from the claimed primary purpose and exposes an undeclared network-listening webhook capability. While this file could be a supporting component of a larger connector, the supplied code itself does not match the declared description.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · requirements.txt (reported line 6)May include surrounding context.

text
# json — built-in Python
# http.server — built-in Python

# Optional: for .env file support
python-dotenv>=1.0.0

# Testing

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README encourages configuring live Odoo credentials and showcases natural-language commands that create, confirm, and modify ERP records, but it does not prominently warn that these actions operate against production business data. In an ERP context, accidental execution can alter sales, inventory, HR, and financial records, making the omission materially risky.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README references a webhook server, background polling, and XML-RPC network communication but does not clearly disclose what business data may be transmitted, stored, or exposed over the network. Because this connector handles sensitive ERP domains like HR, sales, invoices, and inventory, missing privacy and network-boundary disclosure can lead users to deploy it without understanding exposure or data flow implications.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill advertises extensive code-backed capabilities, including configuration loading, local file access, environment-variable use, and network connectivity to an ERP, but it does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, this increases the risk of overbroad execution because users and reviewers cannot tell what resources the skill is intended to access before installation or invocation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is designed to autonomously create, modify, and post business records across ERP modules, but the description lacks clear user-facing warnings about the operational and financial consequences of those actions. In an ERP context, silent or ambiguous automation can lead to unintended orders, invoices, HR records, inventory movements, or other business-state changes from natural-language prompts.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The install instruction uses an unpinned NPX package reference, which can pull the latest published code at execution time. That creates a supply-chain risk: a future malicious or compromised release of the package could be installed and run without users realizing they are no longer getting the reviewed version.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented smart-action workflow performs fuzzy matching and auto-creates missing customers, products, projects, and other records without an explicit approval step. In an ERP system, this can be dangerous because ambiguous names or prompt mistakes can silently generate incorrect master data and transactional records, leading to financial errors, inventory corruption, and downstream automation on bad records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The unlink method performs record deletion, which is irreversible in many Odoo workflows, but the code only provides a neutral docstring and directly invokes the delete RPC. There is no confirmation prompt, warning log, or explicit disclosure in this file highlighting the destructive nature of the operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The delete_event method performs an irreversible delete via client.unlink and only logs after the action. There is no confirmation prompt, safeguard, or user-facing warning in the method about the destructive nature of deleting calendar events.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The method deactivates a CRM opportunity by setting active to False, which is a potentially destructive business-state change. Although there is an internal log message, there is no confirmation prompt or user-facing disclosure in this method's docstring or comments warning that the record will be deactivated.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module-level documentation says it provides "read-only access" to website orders and product publishing controls. However, the implementation includes write operations in publish_product and unpublish_product that change product.template.website_published, directly contradicting the stated read-only behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The approve_leave method directly calls action_approve to approve a leave request, which is a consequential business action affecting employee records. Although it logs after the fact, there is no confirmation prompt, warning, or docstring note indicating that this operation changes approval state and may have organizational impact.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The submit_expense method invokes action_submit, which moves expense records into an approval process and can affect financial workflows. The docstring describes what the method does, but there is no explicit warning or user confirmation mechanism for this state-changing operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The method finalizes a manufacturing order and, if needed, force-sets qty_produced to the expected quantity before attempting completion, all without any built-in confirmation, guardrail, or validation of business preconditions. In an agent/integration context, this makes accidental or unauthorized inventory/production state changes easier, which can corrupt stock, costing, and operational records even if the code is not overtly malicious.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The method documentation frames the operation as 'Delete (archive)' and notes archival behavior, which suggests a non-destructive action. In practice, the code first calls unlink to permanently delete the partner and only archives by setting active=False if deletion fails, which materially differs from the documented intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This file implements multiple 'smart' create workflows that resolve entities via fuzzy ilike name matching and then immediately create or modify Odoo records without any explicit confirmation, disambiguation, or safety gate. In an ERP context, ambiguous matches or malformed natural-language inputs can cause unauthorized or unintended creation of customers, products, employees, tasks, events, invoices, quotations, and purchase orders, directly affecting business data and downstream financial/operational workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

These functions prepare customer records including email, phone, city, country, and sales statistics specifically for Telegram/chat output. The code documents the chat destination but provides no warning, confirmation, or user-facing disclosure that potentially sensitive business data will be displayed or transmitted through a chat channel.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The order formatter includes customer identity, order totals, taxes, and notes, while the invoice formatters include payment state, due dates, totals, and amounts due. Although formatting is the stated purpose of the module, there is no user-facing warning or documented disclosure that this business-sensitive data is intended for Telegram/chat output.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code reads sensitive configuration values including ODOO_API_KEY and ODOO_WEBHOOK_SECRET from environment variables, which falls under access to credentials. While the module docstrings describe configuration loading, there is no user-facing warning, prompt, or explicit disclosure that secrets will be read from the environment.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · odoo_skill/config.py (reported line 136)May include surrounding context.

python
)

    # ── Apply log level ──────────────────────────────────────────────
    logging.getLogger("odoo_skill").setLevel(getattr(logging, config.log_level, logging.INFO))

    logger.info(
        "Odoo config loaded — url=%s  db=%s  user=%s  timeout=%ds",

Static analysis

No suspicious patterns detected.