@@ -25,6 +25,7 @@ import {
2525} from 'lucide-react'
2626import { useForm } from 'react-hook-form'
2727import { z } from 'zod'
28+ import { AlertDescription , AlertTitle } from '@/components/ui/alert'
2829import { Button } from '@/components/ui/button'
2930import { Dialog , DialogContent , DialogHeader , DialogTitle } from '@/components/ui/dialog'
3031import {
@@ -47,12 +48,48 @@ import {
4748import { Separator } from '@/components/ui/separator'
4849import { Textarea } from '@/components/ui/textarea'
4950import { Tooltip , TooltipContent , TooltipTrigger } from '@/components/ui/tooltip'
51+ import { createLogger } from '@/lib/logs/console-logger'
5052import { cn } from '@/lib/utils'
5153import { useNotificationStore } from '@/stores/notifications/store'
5254import { getWorkflowWithValues } from '@/stores/workflows'
5355import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
5456import { useWorkflowStore } from '@/stores/workflows/workflow/store'
5557
58+ const logger = createLogger ( 'MarketplaceModal' )
59+
60+ /**
61+ * Sanitizes sensitive data from workflow state before publishing
62+ * Removes API keys, tokens, and environment variable references
63+ */
64+ const sanitizeWorkflowData = ( workflowData : any ) => {
65+ if ( ! workflowData ) return workflowData
66+
67+ const sanitizedData = JSON . parse ( JSON . stringify ( workflowData ) )
68+ let sanitizedCount = 0
69+
70+ // Handle workflow state format
71+ if ( sanitizedData . state ?. blocks ) {
72+ Object . values ( sanitizedData . state . blocks ) . forEach ( ( block : any ) => {
73+ if ( block . subBlocks ) {
74+ // Check for sensitive fields in subBlocks
75+ Object . entries ( block . subBlocks ) . forEach ( ( [ key , subBlock ] : [ string , any ] ) => {
76+ // Check for API key related fields in any block type
77+ const isSensitiveField =
78+ key . toLowerCase ( ) === 'apikey' || key . toLowerCase ( ) . includes ( 'api_key' )
79+
80+ if ( isSensitiveField && subBlock . value ) {
81+ subBlock . value = ''
82+ sanitizedCount ++
83+ }
84+ } )
85+ }
86+ } )
87+ }
88+
89+ logger . info ( `Sanitized ${ sanitizedCount } API keys from workflow data` )
90+ return sanitizedData
91+ }
92+
5693interface MarketplaceModalProps {
5794 open : boolean
5895 onOpenChange : ( open : boolean ) => void
@@ -219,6 +256,14 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps)
219256 return
220257 }
221258
259+ // Sanitize the workflow data
260+ const sanitizedWorkflowData = sanitizeWorkflowData ( workflowData )
261+ logger . info ( 'Publishing sanitized workflow to marketplace' , {
262+ workflowId : activeWorkflowId ,
263+ workflowName : data . name ,
264+ category : data . category ,
265+ } )
266+
222267 const response = await fetch ( '/api/marketplace/publish' , {
223268 method : 'POST' ,
224269 headers : {
@@ -230,7 +275,7 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps)
230275 description : data . description ,
231276 category : data . category ,
232277 authorName : data . authorName ,
233- workflowState : workflowData . state ,
278+ workflowState : sanitizedWorkflowData . state ,
234279 } ) ,
235280 } )
236281
@@ -414,6 +459,13 @@ export function MarketplaceModal({ open, onOpenChange }: MarketplaceModalProps)
414459 const renderPublishForm = ( ) => (
415460 < Form { ...form } >
416461 < form onSubmit = { form . handleSubmit ( onSubmit ) } className = "space-y-6" >
462+ < div className = "mb-4 rounded-md bg-amber-50 p-3 border border-amber-200" >
463+ < p className = "text-sm text-amber-800" >
464+ < span className = "font-medium text-amber-800" > Security:</ span > API keys and environment
465+ variables will be automatically removed before publishing.
466+ </ p >
467+ </ div >
468+
417469 < FormField
418470 control = { form . control }
419471 name = "name"
0 commit comments