T09 · Insecure Skill Coding Practices
- Location
scripts/shopify_analyzer.py:15- Finding
Server-Side Request Forgery Through Unrestricted Shopify Store URLs
- Content
View full analysis
bool: """Check if URL is a Shopify store.""" try: parsed = urlparse(url) domain = parsed.netloc or parsed.path # Direct Shopify domain if '.myshopify.com' in domain: return True # Check for Shopify indicators req = urllib.request.Request( f"https://{domain}", headers={'User-Agent': 'Mozilla/5.0 (compatible; Analyzer/1.0)'} ) try: with urllib.request.urlopen(req, timeout=10) as response: content = response.read().decode('utf-8', errors='ignore').lower() return 'shopify' in content or 'cdn.shopify.com' in content except: return False except: return False def get_shopify_products(store_url: str, limit: int = 250) -> List[Dict]: """ Fetch products from Shopify store using public API. """ parsed = urlparse(store_url) domain = parsed.netloc or parsed.path if not domain.startswith('http'): domain = f"https://{domain}" products_url = f"{domain}/products.json?limit={limit}" try: req = urllib.request.Request( products_url, headers={'User-Agent': 'Mozilla/5.0 (compatible; Analyzer/1.0)'} ) with urllib.request.urlopen(req, timeout=15) as response: data = json.loads(response.read().decode('utf-8')) return data.get('products', []) ``` ### Technical Analysis The analyzer accepts a store URL from the command line and uses its parsed host directly in outbound `urllib.request.urlopen` calls. It does not restrict requests to approved Shopify domains and does not reject loopback, private, link-l ...[truncated 2875 chars]- Remediation
View remediation
