mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
refactor(ui): change Lighthouse AI MCP tool filtering from blacklist to whitelist (#9802)
This commit is contained in:
committed by
GitHub
parent
d8c1273a57
commit
31845df1a7
@@ -14,6 +14,7 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
|
||||
### 🔄 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)
|
||||
- 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)
|
||||
|
||||
@@ -6,7 +6,7 @@ import { addBreadcrumb, captureException } from "@sentry/nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
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 */
|
||||
interface DescribeToolInput {
|
||||
@@ -34,8 +34,8 @@ function getAllTools(): StructuredTool[] {
|
||||
*/
|
||||
export const describeTool = tool(
|
||||
async ({ toolName }: DescribeToolInput) => {
|
||||
// Block destructive tools from being described
|
||||
if (isBlockedTool(toolName)) {
|
||||
// Only allow whitelisted tools to be described
|
||||
if (!isAllowedTool(toolName)) {
|
||||
return {
|
||||
found: false,
|
||||
message: `Tool '${toolName}' is not available.`,
|
||||
@@ -116,11 +116,11 @@ Returns:
|
||||
*/
|
||||
export const executeTool = tool(
|
||||
async ({ toolName, toolInput }: ExecuteToolInput) => {
|
||||
// Block destructive tools from being executed
|
||||
if (isBlockedTool(toolName)) {
|
||||
// Only allow whitelisted tools to be executed
|
||||
if (!isAllowedTool(toolName)) {
|
||||
addBreadcrumb({
|
||||
category: "meta-tool",
|
||||
message: `execute_tool: Blocked tool attempted: ${toolName}`,
|
||||
message: `execute_tool: Non-whitelisted tool attempted: ${toolName}`,
|
||||
level: "warning",
|
||||
data: { toolName, toolInput },
|
||||
});
|
||||
|
||||
@@ -40,33 +40,59 @@ function truncateDescription(desc: string | undefined, maxLen: number): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tools that are blocked from being listed and executed by the LLM.
|
||||
* These are destructive or sensitive operations that should only be
|
||||
* performed through the UI with explicit user action.
|
||||
* Tools explicitly allowed for the LLM to list and execute.
|
||||
* Follows the principle of least privilege - only these tools are accessible.
|
||||
* All other tools are blocked by default.
|
||||
*/
|
||||
const BLOCKED_TOOLS = new Set([
|
||||
"prowler_app_connect_provider",
|
||||
"prowler_app_delete_provider",
|
||||
"prowler_app_trigger_scan",
|
||||
"prowler_app_schedule_daily_scan",
|
||||
"prowler_app_update_scan",
|
||||
"prowler_app_delete_mutelist",
|
||||
"prowler_app_set_mutelist",
|
||||
"prowler_app_create_mute_rule",
|
||||
"prowler_app_update_mute_rule",
|
||||
"prowler_app_delete_mute_rule",
|
||||
const ALLOWED_TOOLS = new Set([
|
||||
// === Prowler Hub Tools - read-only ===
|
||||
"prowler_hub_list_checks",
|
||||
"prowler_hub_semantic_search_checks",
|
||||
"prowler_hub_get_check_details",
|
||||
"prowler_hub_get_check_code",
|
||||
"prowler_hub_get_check_fixer",
|
||||
"prowler_hub_list_compliances",
|
||||
"prowler_hub_semantic_search_compliances",
|
||||
"prowler_hub_get_compliance_details",
|
||||
"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 {
|
||||
return BLOCKED_TOOLS.has(toolName);
|
||||
export function isAllowedTool(toolName: string): boolean {
|
||||
return ALLOWED_TOOLS.has(toolName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate dynamic tool listing from MCP tools
|
||||
* Filters out blocked/destructive tools
|
||||
* Generate dynamic tool listing from MCP tools.
|
||||
* Only includes tools that are explicitly whitelisted.
|
||||
*/
|
||||
function generateToolListing(): string {
|
||||
if (!isMCPAvailable()) {
|
||||
@@ -79,8 +105,8 @@ function generateToolListing(): string {
|
||||
return TOOLS_UNAVAILABLE_MESSAGE;
|
||||
}
|
||||
|
||||
// Filter out blocked tools
|
||||
const safeTools = mcpTools.filter((tool) => !isBlockedTool(tool.name));
|
||||
// Only include whitelisted tools
|
||||
const safeTools = mcpTools.filter((tool) => isAllowedTool(tool.name));
|
||||
|
||||
let listing = "\n## Available Prowler Tools\n\n";
|
||||
listing += `${safeTools.length} tools loaded from Prowler MCP\n\n`;
|
||||
|
||||
Reference in New Issue
Block a user