T09 · Insecure Skill Coding Practices
Error
- Location
- playwright_test_generator.py:192
- Finding
- Unrestricted URL Analysis Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `playwright_test_generator.py:192-225`; `src/generator.js:366-397` **Vulnerability Type**: Server-Side Request Forgery through unrestricted headless-browser navigation **Risk Level**: High ### Vulnerable Code ```python def generate_from_url(url: str, language: str = 'python', pom: bool = False) -> str: """Generate test code from a URL.""" from playwright.sync_api import sync_playwright code_blocks = [] with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context() page = context.new_page() try: page.goto(url, wait_until='domcontentloaded', timeout=30000) page.wait_for_timeout(1000) analyzer = PageAnalyzer(page) if pom: code_blocks.append(_generate_pom_code(analyzer, language)) else: code_blocks.append(_generate_test_code(analyzer, language)) finally: page.close() context.close() browser.close() return '\n\n'.join(code_blocks) ``` The JavaScript implementation has the same weakness: ```javascript async analyzeUrl(url, options = {}) { if (!url) throw new Error('URL is required for analyzeUrl'); const { mock = false } = options; if (mock) { return { url, title: 'Mock Page Title', locators: { 'main-heading': 'h1', 'login-form': '#login-form', 'username-input': '[data-testid="username-input"]', 'password-input': '[data-testid="password-input"]', 'submit-button': '[data-testid="submit-button"]' }, elements: [] }; } const { chromium } = await import('playwright'); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); await page.goto(url, { waitUntil: 'domcontentloaded' }); const html = await page.content(); const title = await page.title() ...[truncated 2528 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse URLs with a standards-compliant URL parser and permit only `http:` and `https:`. 2. Reject URLs containing embedded credentials or malformed hostnames. 3. Resolve the hostname before navigation and reject every resolved address in: - Loopback ranges. - RFC1918/private ranges. - Link-local ranges. - Multicast and unspecified ranges. - Reserved and documentation ranges. - IPv4-mapped IPv6 representations of blocked addresses. 4. Intercept browser requests and validate each destination, including subresources and redirect targets. 5. Prefer an explicit destination-domain allowlist when URLs are expected to come from a known environment. 6. Run the browser in a network sandbox that cannot reach metadata services, localhost, or internal networks. 7. Add response-size, navigation-time, and redirect-count limits. 8. Add tests for direct private IPs, alternative numeric IP representations, DNS rebinding, IPv6 loopback, and public-to-private redirects. ]]>
