Compare commits

...

1 Commits

Author SHA1 Message Date
Vikhyath Mondreti
a0fd7c8ddf improvement(inputs): sanitize trigger inputs better 2026-01-28 10:47:57 -08:00
2 changed files with 34 additions and 19 deletions

View File

@@ -4,6 +4,7 @@ import {
containsUserFileWithMetadata,
hydrateUserFilesWithBase64,
} from '@/lib/uploads/utils/user-file-base64.server'
import { sanitizeInputFormat, sanitizeTools } from '@/lib/workflows/comparison/normalize'
import {
BlockType,
buildResumeApiUrl,
@@ -34,6 +35,7 @@ import { validateBlockType } from '@/executor/utils/permission-check'
import type { VariableResolver } from '@/executor/variables/resolver'
import type { SerializedBlock } from '@/serializer/types'
import type { SubflowType } from '@/stores/workflows/workflow/types'
import { SYSTEM_SUBBLOCK_IDS } from '@/triggers/constants'
const logger = createLogger('BlockExecutor')
@@ -87,7 +89,7 @@ export class BlockExecutor {
resolvedInputs = this.resolver.resolveInputs(ctx, node.id, block.config.params, block)
if (blockLog) {
blockLog.input = this.parseJsonInputs(resolvedInputs)
blockLog.input = this.sanitizeInputsForLog(resolvedInputs)
}
} catch (error) {
cleanupSelfReference?.()
@@ -162,7 +164,7 @@ export class BlockExecutor {
ctx,
node,
block,
this.parseJsonInputs(resolvedInputs),
this.sanitizeInputsForLog(resolvedInputs),
displayOutput,
duration
)
@@ -241,7 +243,7 @@ export class BlockExecutor {
blockLog.durationMs = duration
blockLog.success = false
blockLog.error = errorMessage
blockLog.input = this.parseJsonInputs(input)
blockLog.input = this.sanitizeInputsForLog(input)
blockLog.output = filterOutputForLog(block.metadata?.id || '', errorOutput, { block })
}
@@ -260,7 +262,7 @@ export class BlockExecutor {
ctx,
node,
block,
this.parseJsonInputs(input),
this.sanitizeInputsForLog(input),
displayOutput,
duration
)
@@ -352,29 +354,41 @@ export class BlockExecutor {
}
/**
* Parse JSON string inputs to objects for log display only.
* Attempts to parse any string that looks like JSON.
* Sanitizes inputs for log display.
* - Filters out system fields (UI-only, readonly, internal flags)
* - Removes UI state from inputFormat items (e.g., collapsed)
* - Parses JSON strings to objects for readability
* Returns a new object - does not mutate the original inputs.
*/
private parseJsonInputs(inputs: Record<string, any>): Record<string, any> {
let result = inputs
let hasChanges = false
private sanitizeInputsForLog(inputs: Record<string, any>): Record<string, any> {
const result: Record<string, any> = {}
for (const [key, value] of Object.entries(inputs)) {
// isJSONString is a quick heuristic (checks for { or [), not a validator.
// Invalid JSON is safely caught below - this just avoids JSON.parse on every string.
if (typeof value !== 'string' || !isJSONString(value)) {
if (SYSTEM_SUBBLOCK_IDS.includes(key) || key === 'triggerMode') {
continue
}
try {
if (!hasChanges) {
result = { ...inputs }
hasChanges = true
if (key === 'inputFormat' && Array.isArray(value)) {
result[key] = sanitizeInputFormat(value)
continue
}
if (key === 'tools' && Array.isArray(value)) {
result[key] = sanitizeTools(value)
continue
}
// isJSONString is a quick heuristic (checks for { or [), not a validator.
// Invalid JSON is safely caught below - this just avoids JSON.parse on every string.
if (typeof value === 'string' && isJSONString(value)) {
try {
result[key] = JSON.parse(value.trim())
} catch {
// Not valid JSON, keep original string
result[key] = value
}
result[key] = JSON.parse(value.trim())
} catch {
// Not valid JSON, keep original string
} else {
result[key] = value
}
}

View File

@@ -10,6 +10,7 @@ export const SYSTEM_SUBBLOCK_IDS: string[] = [
'webhookUrlDisplay', // Webhook URL display
'samplePayload', // Example payload display
'setupScript', // Setup script code (e.g., Apps Script)
'scheduleInfo', // Schedule status display (next run, last run)
]
/**