T09 · Insecure Skill Coding Practices
Error
- Location
- src/shopify.py:45
- Finding
- Shopify access token can be transmitted to an unvalidated host without publishing consent<![CDATA[ ## Vulnerability Details **File Location**: `src/shopify.py:45-55`, `src/shopify.py:82-95`, `src/main.py:81`, `src/main.py:268-287`, `src/main.py:625-626` **Vulnerability Type**: Unvalidated credential destination and constructor-triggered network access **Risk Level**: High ### Vulnerable Code ```python self.store_url = store_url or os.environ.get("SHOPIFY_STORE_URL", "") self.access_token = access_token or os.environ.get("SHOPIFY_ACCESS_TOKEN", "") self.api_version = "2024-01" self.base_url = f"https://{self.store_url}/admin/api/{self.api_version}" self.headers = { "Content-Type": "application/json", "X-Shopify-Access-Token": self.access_token } if self.access_token else {} self.connected = bool(self.store_url and self.access_token) ``` ```python try: response = requests.get( f"{self.base_url}/shop.json", headers=self.headers, timeout=10 ) ``` The connection check is invoked automatically during initialization: ```python # Check connections self._check_connections() ``` The JSON execution path allows the store URL to come from input while silently obtaining the token from the environment: ```python shopify_url = input_data.get("shopify_store_url") or os.environ.get("SHOPIFY_STORE_URL") shopify_token = input_data.get("shopify_access_token") or os.environ.get("SHOPIFY_ACCESS_TOKEN") ``` ### Technical Analysis The Shopify destination is built by directly interpolating `store_url` into an HTTPS URL. The implementation does not parse or validate the hostname, reject user-information components, enforce an approved Shopify domain, or prevent unexpected path and port components. More importantly, the code combines independently sourced trust domains: an input-controlled store URL may be paired with a privileged Shopify token obtained from the process environment. `EcommerceAutomator.__init__()` then calls `_check_connections()` unconditionally. Consequently, a network request carrying the `X-Shopify-Access ...[truncated 1647 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not instantiate or test Shopify connectivity unless direct Shopify publishing has been explicitly authorized for the current operation. 2. Never combine an input-supplied URL with a credential silently loaded from the environment. 3. Parse the URL using a strict URL parser and require: - HTTPS only. - No embedded username or password. - No fragments or unexpected query parameters. - No unexpected port. - A hostname ending in `.myshopify.com`, or a separately configured administrator-approved allowlist. 4. Store a trusted Shopify origin together with its credential rather than allowing callers to choose the destination. 5. Disable cross-origin redirects or verify every redirect destination before forwarding authentication headers. 6. Request a Shopify token containing only the scopes required for product export. 7. Replace constructor-side network activity with an explicit `connect()` or `publish()` operation invoked only after authorization. 8. Enforce the declared input schema before reading any fields. ]]>
