Skip to main content
Glama
2025-12-security-audit-fixes.md3.91 kB
--- title: "Security Audit Fixes - December 2025" category: security-issues date: 2025-12-21 severity: critical components: - skills/runner.py - observability/store.py - server.py commits: - f3eeb19 - faa3f10 - e6cc929 tags: - ssrf - sql-injection - memory-leak - toctou --- # Security Audit Fixes - December 2025 Three critical security and reliability issues identified and fixed during code audit. ## Fix 1: SSRF via DNS Rebinding (TOCTOU) **Component:** `skills/runner.py:449-459` **Severity:** Critical **Commit:** `f3eeb19` ### Problem DNS rebinding attack window existed between URL validation and fetch: - Initial validation resolves domain to public IP - Attacker rebinds DNS to private IP (127.0.0.1, 192.168.x.x) - Fetch executes against internal resources ### Solution Re-validate URL immediately before fetch to close TOCTOU window: ```python # Before: Single validation at request time url = request.build_url(params) options = request.to_fetch_options(params) # After: Re-validate immediately before fetch url = request.build_url(params) try: await validate_url_safe(url) # Re-validate at fetch time except ValueError as e: return SkillRunResult(success=False, error=f"SSRF blocked: {e}") options = request.to_fetch_options(params) ``` ### Prevention - **Best Practice:** Validate URL at check-time AND immediately before network operations - **Review Checklist:** All external network calls preceded by `validate_url_safe()` immediately before fetch - **Test Strategy:** Mock `socket.getaddrinfo()` to return localhost on second call; test obfuscated IPs --- ## Fix 2: SQL Injection via F-string **Component:** `observability/store.py:133-177` **Severity:** High **Commit:** `faa3f10` ### Problem Dynamic SQL UPDATE building via f-string without validation: ```python # Vulnerable await db.execute(f"UPDATE tasks SET {', '.join(updates)} WHERE id = ?", params) ``` ### Solution Whitelist allowed columns and validate before query execution: ```python ALLOWED_UPDATES = {"status = ?", "result = ?", "error = ?", ...} for update in updates: if update not in ALLOWED_UPDATES: raise ValueError(f"Invalid update: {update}") query = "UPDATE tasks SET " + ", ".join(updates) + " WHERE id = ?" await db.execute(query, params) ``` ### Prevention - **Best Practice:** Always use `?` placeholders; whitelist dynamic column names - **Review Checklist:** No string interpolation in SQL; all dynamic components validated - **Test Strategy:** Inject SQL metacharacters (`'; DROP TABLE--`); verify whitelist rejects unknowns --- ## Fix 3: Memory Leak from CDP Listeners **Component:** `server.py:345-489` **Severity:** High **Commit:** `e6cc929` ### Problem CDP listener cleanup only in try/except blocks, missed on exceptions: ```python # Cleanup scattered, easily missed except Exception as e: if recorder: try: await recorder.detach() except: pass # Swallowed ``` ### Solution Track attachment state and use `finally` block for guaranteed cleanup: ```python recorder_attached = False try: await recorder.attach(...) recorder_attached = True # ... work ... finally: if recorder and recorder_attached: await recorder.detach() # Always runs ``` ### Prevention - **Best Practice:** Track resource state with boolean; move cleanup to `finally` - **Review Checklist:** All long-lived resources have attachment flag; no cleanup in except-only - **Test Strategy:** Raise exceptions at different points; verify cleanup runs exactly once --- ## Cross-References - **Test Suite:** `tests/test_skills_security.py` - comprehensive SSRF protection tests - **Guidelines:** `CLAUDE.md` Security Considerations section - **Architecture:** `docs/skills-design.md` ## Verification All fixes verified with: ```bash uv run ruff format . uv run ruff check . uv run pyright uv run pytest ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Saik0s/mcp-browser-use'

If you have feedback or need assistance with the MCP directory API, please join our Discord server