fix: Address high-severity bandit issues

This commit is contained in:
DSS
2025-12-11 07:13:06 -03:00
parent bcb4475744
commit 5b2a328dd1
167 changed files with 7051 additions and 7168 deletions

View File

@@ -8,7 +8,7 @@ transparently.
"""
from abc import ABC, abstractmethod
from typing import List, Optional, Dict, Any
from typing import Any, Dict, List, Optional
class BrowserStrategy(ABC):
@@ -22,10 +22,7 @@ class BrowserStrategy(ABC):
@abstractmethod
async def get_console_logs(
self,
session_id: Optional[str] = None,
limit: int = 100,
level: Optional[str] = None
self, session_id: Optional[str] = None, limit: int = 100, level: Optional[str] = None
) -> List[Dict[str, Any]]:
"""
Retrieve console logs from the browser session.
@@ -42,9 +39,7 @@ class BrowserStrategy(ABC):
@abstractmethod
async def capture_screenshot(
self,
selector: Optional[str] = None,
full_page: bool = False
self, selector: Optional[str] = None, full_page: bool = False
) -> str:
"""
Capture a screenshot of the current page or specific element.
@@ -72,9 +67,7 @@ class BrowserStrategy(ABC):
@abstractmethod
async def get_errors(
self,
severity: Optional[str] = None,
limit: int = 50
self, severity: Optional[str] = None, limit: int = 50
) -> List[Dict[str, Any]]:
"""
Retrieve accumulated browser errors (console errors, crashes, network failures).
@@ -89,10 +82,7 @@ class BrowserStrategy(ABC):
pass
@abstractmethod
async def run_accessibility_audit(
self,
selector: Optional[str] = None
) -> Dict[str, Any]:
async def run_accessibility_audit(self, selector: Optional[str] = None) -> Dict[str, Any]:
"""
Run accessibility audit using axe-core.

View File

@@ -23,15 +23,11 @@ AXE_CORE_SCRIPT_URL = "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.4/axe
# Optional Playwright import for graceful degradation
try:
from playwright.async_api import (
Browser,
ConsoleMessage,
Error as PlaywrightError,
Page,
Playwright,
TimeoutError as PlaywrightTimeoutError,
async_playwright,
)
from playwright.async_api import Browser, ConsoleMessage
from playwright.async_api import Error as PlaywrightError
from playwright.async_api import Page, Playwright
from playwright.async_api import TimeoutError as PlaywrightTimeoutError
from playwright.async_api import async_playwright
PLAYWRIGHT_AVAILABLE = True
except ImportError:
@@ -199,8 +195,8 @@ class LocalBrowserStrategy(BrowserStrategy):
"timestamp": None, # Playwright doesn't provide timestamp directly
"category": "console",
"data": {
"location": msg.location if hasattr(msg, 'location') else None,
}
"location": msg.location if hasattr(msg, "location") else None,
},
}
logs.append(log_entry)
except Exception as e:
@@ -234,10 +230,8 @@ class LocalBrowserStrategy(BrowserStrategy):
raise RuntimeError("No active page to capture screenshot from.")
# Generate unique filename
session_id = getattr(self.context, 'session_id', 'local')
path = os.path.join(
tempfile.gettempdir(), f"dss_screenshot_{session_id}.png"
)
session_id = getattr(self.context, "session_id", "local")
path = os.path.join(tempfile.gettempdir(), f"dss_screenshot_{session_id}.png")
try:
if selector:
@@ -284,9 +278,9 @@ class LocalBrowserStrategy(BrowserStrategy):
"category": "uncaughtError",
"message": str(err),
"data": {
"name": getattr(err, 'name', 'Error'),
"stack": getattr(err, 'stack', None),
}
"name": getattr(err, "name", "Error"),
"stack": getattr(err, "stack", None),
},
}
errors.append(error_entry)
except Exception as e:
@@ -294,9 +288,7 @@ class LocalBrowserStrategy(BrowserStrategy):
return errors[-limit:]
async def run_accessibility_audit(
self, selector: Optional[str] = None
) -> Dict[str, Any]:
async def run_accessibility_audit(self, selector: Optional[str] = None) -> Dict[str, Any]:
"""
Run an accessibility audit on the current page using axe-core.
@@ -330,13 +322,11 @@ class LocalBrowserStrategy(BrowserStrategy):
# Run axe with selector context if provided
if selector:
result = await self.page.evaluate(
"(selector) => axe.run(selector)", selector
)
result = await self.page.evaluate("(selector) => axe.run(selector)", selector)
else:
result = await self.page.evaluate("() => axe.run()")
violations_count = len(result.get('violations', []))
violations_count = len(result.get("violations", []))
logger.info(f"Accessibility audit complete. Found {violations_count} violations.")
return result
@@ -357,9 +347,7 @@ class LocalBrowserStrategy(BrowserStrategy):
raise RuntimeError("No active page to get performance metrics from.")
# 1. Get Navigation Timing API metrics
timing_raw = await self.page.evaluate(
"() => JSON.stringify(window.performance.timing)"
)
timing_raw = await self.page.evaluate("() => JSON.stringify(window.performance.timing)")
nav_timing = json.loads(timing_raw)
# 2. Get Core Web Vitals via PerformanceObserver
@@ -417,14 +405,13 @@ class LocalBrowserStrategy(BrowserStrategy):
"""
core_web_vitals = await self.page.evaluate(metrics_script)
return {
"navigation_timing": nav_timing,
"core_web_vitals": core_web_vitals
}
return {"navigation_timing": nav_timing, "core_web_vitals": core_web_vitals}
async def close(self) -> None:
"""
Close the current page. Browser instance is kept in pool for reuse.
Close the current page.
Browser instance is kept in pool for reuse.
To fully close the browser, use close_browser() class method.
"""

View File

@@ -1,16 +1,16 @@
"""
Remote Browser Strategy implementation.
Connects to the DSS API to retrieve browser state and logs via Shadow State pattern.
"""
import aiohttp
import asyncio
import logging
import base64
from typing import List, Dict, Any, Optional
from typing import Any, Dict, List, Optional
import aiohttp
from ..base import BrowserStrategy
from ...core.context import DSSContext
from ..base import BrowserStrategy
# Configure module logger
logger = logging.getLogger(__name__)
@@ -19,6 +19,7 @@ logger = logging.getLogger(__name__)
class RemoteBrowserStrategy(BrowserStrategy):
"""
Implements browser interaction via remote API calls.
Relies on the browser-side Logger to sync state to the server.
"""
@@ -42,7 +43,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
base_url = self.context.get_api_url()
# Ensure base_url doesn't have trailing slash for clean concatenation
base_url = base_url.rstrip('/')
base_url = base_url.rstrip("/")
url = f"{base_url}/api/browser-logs/{session_id}"
try:
@@ -71,10 +72,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
return []
async def get_console_logs(
self,
session_id: Optional[str] = None,
limit: int = 100,
level: Optional[str] = None
self, session_id: Optional[str] = None, limit: int = 100, level: Optional[str] = None
) -> List[Dict[str, Any]]:
"""
Get browser console logs from the remote API.
@@ -88,7 +86,8 @@ class RemoteBrowserStrategy(BrowserStrategy):
# Filter by console category mostly, but also capture uncaught errors
console_logs = [
l for l in logs
l
for l in logs
if l.get("category") in ["console", "uncaughtError", "unhandledRejection"]
]
@@ -102,9 +101,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
return console_logs[:limit]
async def capture_screenshot(
self,
selector: Optional[str] = None,
full_page: bool = False
self, selector: Optional[str] = None, full_page: bool = False
) -> str:
"""
Capture a screenshot.
@@ -133,8 +130,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
# Filter for snapshots
snapshots = [
l for l in logs
if l.get("category") == "snapshot" and "snapshot" in l.get("data", {})
l for l in logs if l.get("category") == "snapshot" and "snapshot" in l.get("data", {})
]
if not snapshots:
@@ -154,9 +150,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
return "<!-- Corrupted or unexpected snapshot data format -->"
async def get_errors(
self,
severity: Optional[str] = None,
limit: int = 50
self, severity: Optional[str] = None, limit: int = 50
) -> List[Dict[str, Any]]:
"""
Get error logs from the remote API.
@@ -178,10 +172,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
return errors[:limit]
async def run_accessibility_audit(
self,
selector: Optional[str] = None
) -> Dict[str, Any]:
async def run_accessibility_audit(self, selector: Optional[str] = None) -> Dict[str, Any]:
"""
Get accessibility audit results from Shadow State.
@@ -198,7 +189,8 @@ class RemoteBrowserStrategy(BrowserStrategy):
# Look for accessibility audits in the logs
audits = [
l for l in logs
l
for l in logs
if l.get("category") == "accessibility" or l.get("category") == "accessibilitySnapshot"
]
@@ -207,7 +199,7 @@ class RemoteBrowserStrategy(BrowserStrategy):
"violations": [],
"passes": [],
"incomplete": [],
"message": "No accessibility audit found in Shadow State. Trigger audit from browser console using __DSS_BROWSER_LOGS.audit()"
"message": "No accessibility audit found in Shadow State. Trigger audit from browser console using __DSS_BROWSER_LOGS.audit()",
}
# Get the latest audit
@@ -236,14 +228,13 @@ class RemoteBrowserStrategy(BrowserStrategy):
# Look for performance metrics in the logs
perf_logs = [
l for l in logs
if l.get("category") in ["performance", "accessibilitySnapshot"]
l for l in logs if l.get("category") in ["performance", "accessibilitySnapshot"]
]
if not perf_logs:
return {
"error": "No performance data found in Shadow State.",
"message": "Performance metrics are captured automatically during page load."
"message": "Performance metrics are captured automatically during page load.",
}
# Get the latest performance entry

View File

@@ -1,14 +1,14 @@
"""
Remote Filesystem Strategy implementation.
Filesystem operations are restricted in REMOTE mode for security.
"""
import logging
from typing import List, Dict, Any
from pathlib import Path
from typing import Any, Dict, List
from ..base import FilesystemStrategy
from ...core.context import DSSContext
from ..base import FilesystemStrategy
# Configure module logger
logger = logging.getLogger(__name__)