Task 4: Network Topology Discovery#29
Conversation
- Add HostNetworkDiscoveryService for comprehensive network analysis - Discover network interfaces with IP addresses, states, and statistics - Extract routing table information (IPv4 and IPv6) - Analyze DNS configuration and resolution testing - Detect NTP configuration across different implementations (chrony, ntp, systemd-timesyncd) - Identify network services and listening ports - Perform connectivity tests to common destinations - Assess network security configuration and hardening - Add network security assessment with scoring and recommendations - Create network topology mapping for multiple hosts - Include comprehensive parsing utilities for various network commands - Support both modern (ip, ss) and legacy (ifconfig, netstat) network tools ## API Endpoints - Individual and bulk network discovery (max 10 hosts for intensive operations) - Network security assessment with vulnerability identification - Network topology mapping with connectivity matrix - Network discovery capabilities reference ## Security Features - Identifies risky open ports and services - Assesses firewall status and configuration - Evaluates TCP/IP stack hardening parameters - Provides security recommendations and vulnerability reporting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
| from .routes import auth, hosts, scans, content, scap_content, monitoring, users, audit, host_groups, scan_templates, webhooks, mfa | ||
| from .routes.system_settings_unified import router as system_settings_router | ||
| from .routes import credentials, api_keys, remediation_callback, integration_metrics, bulk_operations, compliance, rule_scanning, capabilities | ||
| from .routes import credentials, api_keys, remediation_callback, integration_metrics, bulk_operations, compliance, rule_scanning, capabilities, host_network_discovery |
Check notice
Code scanning / CodeQL
Unused import
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix the issue, we need to remove capabilities from the import statement on line 22 in backend/app/main.py. The other imported modules in the list should remain unless also flagged as unused. This change is safe as long as capabilities is not required elsewhere in the codebase for side effects (e.g., automatic route registration), which has not been indicated in the snippet.
Specifically, edit the import statement so that capabilities is omitted.
Only change line 22 of backend/app/main.py. No other changes or additions are required.
| @@ -19,7 +19,7 @@ | ||
| from .database import engine, create_tables, get_db | ||
| from .routes import auth, hosts, scans, content, scap_content, monitoring, users, audit, host_groups, scan_templates, webhooks, mfa | ||
| from .routes.system_settings_unified import router as system_settings_router | ||
| from .routes import credentials, api_keys, remediation_callback, integration_metrics, bulk_operations, compliance, rule_scanning, capabilities, host_network_discovery | ||
| from .routes import credentials, api_keys, remediation_callback, integration_metrics, bulk_operations, compliance, rule_scanning, host_network_discovery | ||
| # Import security routes only if available | ||
| try: | ||
| from .routes import automated_fixes |
| NetworkDiscoveryResponse containing discovered network information | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") |
Check failure
Code scanning / CodeQL
Wrong number of arguments in a call
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix the problem, we must match the check_permission function signature by passing all required arguments. Specifically, we need to add the db argument to the function call at line 82. The db variable is available in the local context because it is a parameter of the endpoint function, so we can simply add it as the third argument. No additional imports or definitions are needed since everything required is already present within the provided code.
- Change file:
backend/app/routes/host_network_discovery.py - Locate the call to
check_permissionat line 82. - Update it to include the
dbargument:check_permission(current_user, "hosts:read", db).
| @@ -79,7 +79,7 @@ | ||
| NetworkDiscoveryResponse containing discovered network information | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") | ||
| check_permission(current_user, "hosts:read", db) | ||
|
|
||
| try: | ||
| # Convert string UUID to UUID object |
| detail=f"Invalid host ID format: {str(e)}" | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"Network discovery failed for host {host_id}: {str(e)}") |
Check failure
Code scanning / CodeQL
Log Injection
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix this issue, we must sanitize the host_id value before including it in log messages. The recommended approach for plain text logs is to remove newline characters (\r\n, \n, and optionally \r) from the user input. We can do this by creating a sanitized version of host_id (e.g. sanitized_host_id = host_id.replace('\r', '').replace('\n', '')) and using this sanitized value in the logger call on line 116. This fix should be applied only at the point where the user-supplied value is included in the logger call; elsewhere, retain the original value for functional purposes. If no utility function exists, perform sanitization inline before logging.
Edit only lines around the logger call in backend/app/routes/host_network_discovery.py (specifically, the exception handling block in discover_host_network_topology). No external dependencies are needed.
| @@ -113,7 +113,8 @@ | ||
| detail=f"Invalid host ID format: {str(e)}" | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"Network discovery failed for host {host_id}: {str(e)}") | ||
| sanitized_host_id = host_id.replace('\r', '').replace('\n', '') | ||
| logger.error(f"Network discovery failed for host {sanitized_host_id}: {str(e)}") | ||
| raise HTTPException( | ||
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | ||
| detail=f"Network discovery failed: {str(e)}" |
| BulkNetworkDiscoveryResponse with results for all hosts | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") |
Check failure
Code scanning / CodeQL
Wrong number of arguments in a call
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To resolve the error, identify what the third required argument for check_permission should be. In most FastAPI + SQLAlchemy setups, permission checks typically need the current database session, which is db in this function. Therefore, the best fix is to add db as the third argument to the call check_permission(current_user, "hosts:read"), making it check_permission(current_user, "hosts:read", db). This should be changed directly at the highlighted line (139) in the bulk_discover_network_topology route.
No new methods or definitions are needed, assuming that this pattern matches other usages and that db is the expected argument.
| @@ -136,7 +136,7 @@ | ||
| BulkNetworkDiscoveryResponse with results for all hosts | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") | ||
| check_permission(current_user, "hosts:read", db) | ||
|
|
||
| if not request.host_ids: | ||
| raise HTTPException( |
| errors[host_id] = f"Invalid host ID format: {str(e)}" | ||
| failed_discoveries += 1 | ||
| except Exception as e: | ||
| logger.error(f"Network discovery failed for host {host_id}: {str(e)}") |
Check failure
Code scanning / CodeQL
Log Injection
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix the log injection vulnerability, any untrusted user input written to logs should be sanitized to prevent special characters (especially newline and carriage return characters) from affecting the integrity of log entries. Specifically, before logging host_id on line 191, ensure that any carriage returns (\r) and line feeds (\n) are removed or replaced. This can be accomplished by adding a helper function to sanitize input, or inline using replace.
In this case, best practice is to define a small utility function (e.g., sanitize_for_log) within the file to sanitize any string going into logs. Then, before logging host_id, call this function.
Changes needed:
- Add a helper function such as
sanitize_for_log(value)that removes/escapes problematic characters. - Use this function on
host_idbefore passing it to any log call (e.g., line 191). - Do NOT change any logic or functionality of the route or its error handling.
| @@ -17,6 +17,13 @@ | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| def sanitize_for_log(value: str) -> str: | ||
| """ | ||
| Remove carriage return and line feed characters to prevent log injection. | ||
| """ | ||
| if not isinstance(value, str): | ||
| value = str(value) | ||
| return value.replace('\r', '').replace('\n', '') | ||
| router = APIRouter(prefix="/host-network-discovery", tags=["Host Network Discovery"]) | ||
|
|
||
|
|
||
| @@ -188,7 +195,7 @@ | ||
| errors[host_id] = f"Invalid host ID format: {str(e)}" | ||
| failed_discoveries += 1 | ||
| except Exception as e: | ||
| logger.error(f"Network discovery failed for host {host_id}: {str(e)}") | ||
| logger.error(f"Network discovery failed for host {sanitize_for_log(host_id)}: {str(e)}") | ||
| errors[host_id] = f"Network discovery failed: {str(e)}" | ||
| failed_discoveries += 1 | ||
|
|
| NetworkSecurityAssessment with security evaluation | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") |
Check failure
Code scanning / CodeQL
Wrong number of arguments in a call
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix this problem, we must update the call to check_permission on line 223 to supply the required third parameter. We must determine, from context or convention, what the missing third argument represents. Based on typical RBAC function parameterization, it's likely to be something like a database session, request object, or similar contextual information—very commonly the database session (db), which is available in this function's parameters. Since db is provided by dependency injection and is present in nearby code, and because check_permission is often expected to have access to the database/session to check permissions, supplying db as the third parameter is the safest and cleanest solution. Only the call on line 223 needs editing; the rest of the code does not require modification.
| @@ -220,7 +220,7 @@ | ||
| NetworkSecurityAssessment with security evaluation | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") | ||
| check_permission(current_user, "hosts:read", db) | ||
|
|
||
| try: | ||
| # Convert string UUID to UUID object |
| detail=f"Invalid host ID format: {str(e)}" | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"Network security assessment failed for host {host_id}: {str(e)}") |
Check failure
Code scanning / CodeQL
Log Injection
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix the log injection vulnerability, sanitize the user-provided host_id before interpolating it into log messages. Specifically, remove all newline (\n, \r) characters from host_id when logging. This can be done with host_id.replace('\n', '').replace('\r', ''). The fix should only apply to the value used in logging to avoid interfering with the actual logic where the original value may be needed. The affected region is line 252 in the error logging within the exception handler in the assess_host_network_security route function in backend/app/routes/host_network_discovery.py.
No import is needed; simply sanitize inline before logging.
| @@ -249,7 +249,8 @@ | ||
| detail=f"Invalid host ID format: {str(e)}" | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"Network security assessment failed for host {host_id}: {str(e)}") | ||
| safe_host_id = host_id.replace('\n', '').replace('\r', '') | ||
| logger.error(f"Network security assessment failed for host {safe_host_id}: {str(e)}") | ||
| raise HTTPException( | ||
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | ||
| detail=f"Network security assessment failed: {str(e)}" |
| NetworkTopologyMap with network topology visualization data | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") |
Check failure
Code scanning / CodeQL
Wrong number of arguments in a call
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix the problem, we need to supply the missing third argument to the check_permission function call at line 275. Since the function call is protecting bulk network topology mapping actions for multiple hosts, the most sensible resource argument to pass is either the list of host IDs or the request object containing them. The function’s likely usage pattern is: check_permission(user, permission, resource). The resource here would be the specific hosts being targeted. As the request object on this endpoint contains host_ids, it is appropriate to pass either request.host_ids or the whole request object, depending on convention elsewhere in the codebase. To minimize risk and maximize correctness, we will pass request.host_ids as the third argument, giving the access check direct visibility of the relevant resources.
No other significant code changes, imports, or external dependencies are required.
| @@ -272,7 +272,7 @@ | ||
| NetworkTopologyMap with network topology visualization data | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") | ||
| check_permission(current_user, "hosts:read", request.host_ids) | ||
|
|
||
| if not request.host_ids: | ||
| raise HTTPException( |
| Dictionary of supported network discovery features | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") |
Check failure
Code scanning / CodeQL
Wrong number of arguments in a call
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
The fix is to ensure the call to check_permission on line 317 supplies the correct number of arguments—as per its definition (at least three). Since the other call on line 275 passes the arguments current_user, "hosts:read" (possibly missing the third argument too), but the context here is the /network-discovery-capabilities route and probably needs the database session as the third parameter. Given the context of FastAPI dependency injection, it is likely missing the db argument. To fix, modify the route function to accept db: Session = Depends(get_db) and then pass db as the third argument to check_permission. Edit lines 307–317 to introduce the db argument and update the call accordingly.
| @@ -305,7 +305,8 @@ | ||
|
|
||
| @router.get("/network-discovery-capabilities") | ||
| async def get_network_discovery_capabilities( | ||
| current_user=Depends(get_current_user) | ||
| current_user=Depends(get_current_user), | ||
| db: Session = Depends(get_db) | ||
| ): | ||
| """ | ||
| Get information about network discovery capabilities | ||
| @@ -314,7 +315,7 @@ | ||
| Dictionary of supported network discovery features | ||
| """ | ||
| # Check permissions | ||
| check_permission(current_user, "hosts:read") | ||
| check_permission(current_user, "hosts:read", db) | ||
|
|
||
| capabilities = { | ||
| "network_interfaces": { |
| Identifies network interfaces, routing, DNS, NTP, and connectivity configuration on target hosts | ||
| """ | ||
| import re | ||
| import json |
Check notice
Code scanning / CodeQL
Unused import
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
The best way to fix this problem is to remove the unused import statement for json from the file backend/app/services/host_network_discovery.py. Specifically, delete the line import json on line 6. No other changes are necessary, as this import is not used elsewhere in the visible code. Removing this will clean up the file and slightly reduce unnecessary dependencies, improving readability and avoiding confusion.
| @@ -3,7 +3,6 @@ | ||
| Identifies network interfaces, routing, DNS, NTP, and connectivity configuration on target hosts | ||
| """ | ||
| import re | ||
| import json | ||
| import logging | ||
| from typing import Dict, Any, Optional, List | ||
| from datetime import datetime |




Summary
Features
Advanced Capabilities
API Endpoints
POST /api/host-network-discovery/hosts/{host_id}/network-discovery- Full network discoveryPOST /api/host-network-discovery/bulk-network-discovery- Bulk discovery (max 10 hosts)GET /api/host-network-discovery/hosts/{host_id}/network-security-assessment- Security evaluationPOST /api/host-network-discovery/network-topology-map- Topology mappingGET /api/host-network-discovery/network-discovery-capabilities- Feature referenceNetwork Security Assessment
Topology Mapping Features
Test Plan
🤖 Generated with Claude Code