refactor(ui): change Lighthouse AI MCP tool filtering from blacklist to whitelist (#9802)

This commit is contained in:
Rubén De la Torre Vico
2026-01-15 13:53:05 +01:00
committed by GitHub
parent d8c1273a57
commit 31845df1a7
3 changed files with 54 additions and 27 deletions

View File

@@ -14,6 +14,7 @@ All notable changes to the **Prowler UI** are documented in this file.
### 🔄 Changed ### 🔄 Changed
- Refactor Lighthouse AI MCP tool filtering from blacklist to whitelist approach for improved security [(#9802)](https://github.com/prowler-cloud/prowler/pull/9802)
- Refactor ScatterPlot as reusable generic component with TypeScript generics [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664) - Refactor ScatterPlot as reusable generic component with TypeScript generics [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664)
- Swap Risk Plot axes: X = Fail Findings, Y = Prowler ThreatScore [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664) - Swap Risk Plot axes: X = Fail Findings, Y = Prowler ThreatScore [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664)
- Remove duplicate scan_id filter badge from Findings page [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664) - Remove duplicate scan_id filter badge from Findings page [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664)

View File

@@ -6,7 +6,7 @@ import { addBreadcrumb, captureException } from "@sentry/nextjs";
import { z } from "zod"; import { z } from "zod";
import { getMCPTools, isMCPAvailable } from "@/lib/lighthouse/mcp-client"; import { getMCPTools, isMCPAvailable } from "@/lib/lighthouse/mcp-client";
import { isBlockedTool } from "@/lib/lighthouse/workflow"; import { isAllowedTool } from "@/lib/lighthouse/workflow";
/** Input type for describe_tool */ /** Input type for describe_tool */
interface DescribeToolInput { interface DescribeToolInput {
@@ -34,8 +34,8 @@ function getAllTools(): StructuredTool[] {
*/ */
export const describeTool = tool( export const describeTool = tool(
async ({ toolName }: DescribeToolInput) => { async ({ toolName }: DescribeToolInput) => {
// Block destructive tools from being described // Only allow whitelisted tools to be described
if (isBlockedTool(toolName)) { if (!isAllowedTool(toolName)) {
return { return {
found: false, found: false,
message: `Tool '${toolName}' is not available.`, message: `Tool '${toolName}' is not available.`,
@@ -116,11 +116,11 @@ Returns:
*/ */
export const executeTool = tool( export const executeTool = tool(
async ({ toolName, toolInput }: ExecuteToolInput) => { async ({ toolName, toolInput }: ExecuteToolInput) => {
// Block destructive tools from being executed // Only allow whitelisted tools to be executed
if (isBlockedTool(toolName)) { if (!isAllowedTool(toolName)) {
addBreadcrumb({ addBreadcrumb({
category: "meta-tool", category: "meta-tool",
message: `execute_tool: Blocked tool attempted: ${toolName}`, message: `execute_tool: Non-whitelisted tool attempted: ${toolName}`,
level: "warning", level: "warning",
data: { toolName, toolInput }, data: { toolName, toolInput },
}); });

View File

@@ -40,33 +40,59 @@ function truncateDescription(desc: string | undefined, maxLen: number): string {
} }
/** /**
* Tools that are blocked from being listed and executed by the LLM. * Tools explicitly allowed for the LLM to list and execute.
* These are destructive or sensitive operations that should only be * Follows the principle of least privilege - only these tools are accessible.
* performed through the UI with explicit user action. * All other tools are blocked by default.
*/ */
const BLOCKED_TOOLS = new Set([ const ALLOWED_TOOLS = new Set([
"prowler_app_connect_provider", // === Prowler Hub Tools - read-only ===
"prowler_app_delete_provider", "prowler_hub_list_checks",
"prowler_app_trigger_scan", "prowler_hub_semantic_search_checks",
"prowler_app_schedule_daily_scan", "prowler_hub_get_check_details",
"prowler_app_update_scan", "prowler_hub_get_check_code",
"prowler_app_delete_mutelist", "prowler_hub_get_check_fixer",
"prowler_app_set_mutelist", "prowler_hub_list_compliances",
"prowler_app_create_mute_rule", "prowler_hub_semantic_search_compliances",
"prowler_app_update_mute_rule", "prowler_hub_get_compliance_details",
"prowler_app_delete_mute_rule", "prowler_hub_list_providers",
"prowler_hub_get_provider_services",
// === Prowler Docs Tools - read-only ===
"prowler_docs_search",
"prowler_docs_get_document",
// === Prowler App Tools - read-only ===
// Findings
"prowler_app_search_security_findings",
"prowler_app_get_finding_details",
"prowler_app_get_findings_overview",
// Providers
"prowler_app_search_providers",
// Scans
"prowler_app_list_scans",
"prowler_app_get_scan",
// Muting
"prowler_app_get_mutelist",
"prowler_app_list_mute_rules",
"prowler_app_get_mute_rule",
// Compliance
"prowler_app_get_compliance_overview",
"prowler_app_get_compliance_framework_state_details",
// Resources
"prowler_app_list_resources",
"prowler_app_get_resource",
"prowler_app_get_resources_overview",
]); ]);
/** /**
* Check if a tool is blocked * Check if a tool is allowed for LLM access.
* Returns true only if the tool is explicitly in the whitelist.
*/ */
export function isBlockedTool(toolName: string): boolean { export function isAllowedTool(toolName: string): boolean {
return BLOCKED_TOOLS.has(toolName); return ALLOWED_TOOLS.has(toolName);
} }
/** /**
* Generate dynamic tool listing from MCP tools * Generate dynamic tool listing from MCP tools.
* Filters out blocked/destructive tools * Only includes tools that are explicitly whitelisted.
*/ */
function generateToolListing(): string { function generateToolListing(): string {
if (!isMCPAvailable()) { if (!isMCPAvailable()) {
@@ -79,8 +105,8 @@ function generateToolListing(): string {
return TOOLS_UNAVAILABLE_MESSAGE; return TOOLS_UNAVAILABLE_MESSAGE;
} }
// Filter out blocked tools // Only include whitelisted tools
const safeTools = mcpTools.filter((tool) => !isBlockedTool(tool.name)); const safeTools = mcpTools.filter((tool) => isAllowedTool(tool.name));
let listing = "\n## Available Prowler Tools\n\n"; let listing = "\n## Available Prowler Tools\n\n";
listing += `${safeTools.length} tools loaded from Prowler MCP\n\n`; listing += `${safeTools.length} tools loaded from Prowler MCP\n\n`;