From 1966c731128ca0021050a635cc3aa42652145ef5 Mon Sep 17 00:00:00 2001 From: Emir Karabeg Date: Sun, 23 Mar 2025 16:28:36 -0700 Subject: [PATCH] improvement(marketplace): sanitize api key from marketplace state --- .../marketplace-modal/marketplace-modal.tsx | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx b/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx index 4ea0febb7..be60040e9 100644 --- a/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx +++ b/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx @@ -25,6 +25,7 @@ import { } from 'lucide-react' import { useForm } from 'react-hook-form' import { z } from 'zod' +import { AlertDescription, AlertTitle } from '@/components/ui/alert' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { @@ -47,12 +48,48 @@ import { import { Separator } from '@/components/ui/separator' import { Textarea } from '@/components/ui/textarea' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' import { useNotificationStore } from '@/stores/notifications/store' import { getWorkflowWithValues } from '@/stores/workflows' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' +const logger = createLogger('MarketplaceModal') + +/** + * Sanitizes sensitive data from workflow state before publishing + * Removes API keys, tokens, and environment variable references + */ +const sanitizeWorkflowData = (workflowData: any) => { + if (!workflowData) return workflowData + + const sanitizedData = JSON.parse(JSON.stringify(workflowData)) + let sanitizedCount = 0 + + // Handle workflow state format + if (sanitizedData.state?.blocks) { + Object.values(sanitizedData.state.blocks).forEach((block: any) => { + if (block.subBlocks) { + // Check for sensitive fields in subBlocks + Object.entries(block.subBlocks).forEach(([key, subBlock]: [string, any]) => { + // Check for API key related fields in any block type + const isSensitiveField = + key.toLowerCase() === 'apikey' || key.toLowerCase().includes('api_key') + + if (isSensitiveField && subBlock.value) { + subBlock.value = '' + sanitizedCount++ + } + }) + } + }) + } + + logger.info(`Sanitized ${sanitizedCount} API keys from workflow data`) + return sanitizedData +} + interface MarketplaceModalProps { open: boolean onOpenChange: (open: boolean) => void @@ -219,6 +256,14 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps) return } + // Sanitize the workflow data + const sanitizedWorkflowData = sanitizeWorkflowData(workflowData) + logger.info('Publishing sanitized workflow to marketplace', { + workflowId: activeWorkflowId, + workflowName: data.name, + category: data.category, + }) + const response = await fetch('/api/marketplace/publish', { method: 'POST', headers: { @@ -230,7 +275,7 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps) description: data.description, category: data.category, authorName: data.authorName, - workflowState: workflowData.state, + workflowState: sanitizedWorkflowData.state, }), }) @@ -414,6 +459,13 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps) const renderPublishForm = () => (
+
+

+ Security: API keys and environment + variables will be automatically removed before publishing. +

+
+