(
self,
*,
do_ports: bool = True,
ports: Optional[List[int]] = None,
do_dns: bool = True,
do_tls: bool = True,
do_headers: bool = True,
do_tech: bool = True,
do_cors: bool = True,
do_methods: bool = True,
do_sensitive: bool = True,
do_crawl: bool = True,
crawl_depth: int = 2,
max_pages: int = 200,
do_js: bool = True,
do_dirb: bool = False,
dir_wordlist: Optional[List[str]] = None,
dirb_extensions: Optional[List[str]] = None,
dirb_force_extensions: bool = False,
dirb_recursive: bool = False,
dirb_recursion_depth: int = 2,
do_wayback: bool = False,
)
| 1604 | # ---------- orchestrator ---------- |
| 1605 | |
| 1606 | async def scan( |
| 1607 | self, |
| 1608 | *, |
| 1609 | do_ports: bool = True, |
| 1610 | ports: Optional[List[int]] = None, |
| 1611 | do_dns: bool = True, |
| 1612 | do_tls: bool = True, |
| 1613 | do_headers: bool = True, |
| 1614 | do_tech: bool = True, |
| 1615 | do_cors: bool = True, |
| 1616 | do_methods: bool = True, |
| 1617 | do_sensitive: bool = True, |
| 1618 | do_crawl: bool = True, |
| 1619 | crawl_depth: int = 2, |
| 1620 | max_pages: int = 200, |
| 1621 | do_js: bool = True, |
| 1622 | do_dirb: bool = False, |
| 1623 | dir_wordlist: Optional[List[str]] = None, |
| 1624 | dirb_extensions: Optional[List[str]] = None, |
| 1625 | dirb_force_extensions: bool = False, |
| 1626 | dirb_recursive: bool = False, |
| 1627 | dirb_recursion_depth: int = 2, |
| 1628 | do_wayback: bool = False, |
| 1629 | ) -> None: |
| 1630 | await self._start_live_pipeline() |
| 1631 | try: |
| 1632 | limits = httpx.Limits(max_connections=self.concurrency, max_keepalive_connections=max(10, self.concurrency // 2)) |
| 1633 | timeout = httpx.Timeout(self.timeout) |
| 1634 | async with httpx.AsyncClient(limits=limits, timeout=timeout, verify=True) as client: |
| 1635 | self._client = client |
| 1636 | |
| 1637 | self.logger.info(f"Target: {self.base_url} (host={self.hostname}, port={self.port or 'default'})") |
| 1638 | if not self.unsafe_active_tests: |
| 1639 | self.logger.info("Safe mode enabled: active probes disabled (remove --safe-mode to re-enable).") |
| 1640 | |
| 1641 | if do_dns: |
| 1642 | await self.resolve_dns() |
| 1643 | |
| 1644 | # Baseline |
| 1645 | body, headers, setcookies, final = await self.fetch_baseline() |
| 1646 | if body is None: |
| 1647 | self.add_finding(Finding( |
| 1648 | category="Target_Unreachable", |
| 1649 | severity="High", |
| 1650 | url=self.base_url, |
| 1651 | details="Failed to fetch baseline page.", |
| 1652 | remediation="Verify the target is reachable and that you have permission to test it." |
| 1653 | )) |
| 1654 | else: |
| 1655 | if do_headers: |
| 1656 | await self.check_security_headers(headers, final) |
| 1657 | await self.check_server_disclosure(headers, final) |
| 1658 | await self.check_clickjacking(headers, final) |
| 1659 | await self.check_cache_control(headers, final) |
| 1660 | await self.check_csp_quality(headers, final) |
| 1661 | await self.check_http_to_https_redirect(final) |
| 1662 | if do_tech: |
| 1663 | await self.detect_tech(headers, body, final) |
no test coverage detected