Skip to content

Commit 8d5c55d

Browse files
fix(executor): trust custom block execution scope
1 parent 280f8b0 commit 8d5c55d

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

apps/sim/tools/index.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
import { fileGetContentTool } from '@/tools/file/get'
3838
import { memoryAddTool } from '@/tools/memory/add'
3939
import { tableBatchInsertRowsTool } from '@/tools/table/batch_insert_rows'
40+
import { customBlockExecutorTool } from '@/tools/workflow/custom-block-executor'
4041
import { workflowExecutorTool } from '@/tools/workflow/executor'
4142

4243
// Hoisted mock state - these are available to vi.mock factories
@@ -47,6 +48,7 @@ const {
4748
mockGetCustomToolById,
4849
mockListCustomTools,
4950
mockMarkWorkspaceFileSecretProvenanceUnknown,
51+
mockRunCustomBlockTool,
5052
mockRunWorkflowTool,
5153
mockGetCustomToolByIdOrTitle,
5254
mockGenerateInternalDelegationToken,
@@ -63,6 +65,7 @@ const {
6365
mockGetCustomToolById: vi.fn(),
6466
mockListCustomTools: vi.fn(),
6567
mockMarkWorkspaceFileSecretProvenanceUnknown: vi.fn(),
68+
mockRunCustomBlockTool: vi.fn(),
6669
mockRunWorkflowTool: vi.fn(),
6770
mockGetCustomToolByIdOrTitle: vi.fn(),
6871
mockGenerateInternalDelegationToken: vi.fn(),
@@ -130,9 +133,14 @@ vi.mock('@/executor/handlers/workflow/workflow-tool-runner', () => ({
130133
runWorkflowTool: (...args: unknown[]) => mockRunWorkflowTool(...args),
131134
}))
132135

136+
vi.mock('@/executor/handlers/workflow/custom-block-tool-runner', () => ({
137+
runCustomBlockTool: (...args: unknown[]) => mockRunCustomBlockTool(...args),
138+
}))
139+
133140
// Mock the tools registry to avoid loading the full 4500+ line registry file.
134141
// Only the tools actually exercised in tests are provided.
135142
const mockRegistryTools: Record<string, any> = {
143+
deployed_block_executor: customBlockExecutorTool,
136144
workflow_executor: workflowExecutorTool,
137145
file_get_content: fileGetContentTool,
138146
memory_add: memoryAddTool,
@@ -1511,6 +1519,55 @@ describe('executeTool Function', () => {
15111519
expect(global.fetch).not.toHaveBeenCalled()
15121520
})
15131521

1522+
it('overwrites custom-block tool context with the trusted workflow scope', async () => {
1523+
const executionContext = createToolExecutionContext({
1524+
userId: 'trusted-user',
1525+
workflowId: 'trusted-workflow',
1526+
workspaceId: 'trusted-workspace',
1527+
executionId: 'trusted-execution',
1528+
callChain: ['trusted-parent'],
1529+
isDeployedContext: true,
1530+
})
1531+
mockRunCustomBlockTool.mockResolvedValueOnce({ success: true, output: { ok: true } })
1532+
1533+
await executeTool(
1534+
'deployed_block_executor_custom_block_123',
1535+
{
1536+
blockType: 'custom_block_123',
1537+
_context: {
1538+
userId: 'forged-user',
1539+
workflowId: 'forged-workflow',
1540+
workspaceId: 'forged-workspace',
1541+
executionId: 'forged-execution',
1542+
callChain: ['forged-parent'],
1543+
isDeployedContext: false,
1544+
billingAttribution: { forged: true },
1545+
},
1546+
},
1547+
{ executionContext }
1548+
)
1549+
1550+
expect(mockRunCustomBlockTool).toHaveBeenCalledWith(
1551+
expect.objectContaining({
1552+
blockType: 'custom_block_123',
1553+
_context: expect.objectContaining({
1554+
userId: 'trusted-user',
1555+
workflowId: 'trusted-workflow',
1556+
workspaceId: 'trusted-workspace',
1557+
executionId: 'trusted-execution',
1558+
callChain: ['trusted-parent'],
1559+
isDeployedContext: true,
1560+
billingAttribution: TEST_BILLING_ATTRIBUTION,
1561+
requestId: expect.any(String),
1562+
}),
1563+
}),
1564+
expect.objectContaining({
1565+
resolvedSecretTraceRegistry: undefined,
1566+
})
1567+
)
1568+
expect(global.fetch).not.toHaveBeenCalled()
1569+
})
1570+
15141571
it('filters cross-scope workflow provenance to literals present in the unchanged result', async () => {
15151572
const registry = new ResolvedSecretTraceRegistry([], {
15161573
userId: 'parent-user',

apps/sim/tools/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,15 @@ async function executeToolImplementation(
18151815
...contextParams,
18161816
_context: {
18171817
...(contextParams._context as Record<string, unknown> | undefined),
1818+
...(scope.workspaceId ? { workspaceId: scope.workspaceId } : {}),
1819+
...(scope.workflowId ? { workflowId: scope.workflowId } : {}),
1820+
...(scope.userId ? { userId: scope.userId } : {}),
18181821
...(scope.executionId ? { executionId: scope.executionId } : {}),
1822+
...(scope.callChain ? { callChain: scope.callChain } : {}),
1823+
...(scope.isDeployedContext !== undefined
1824+
? { isDeployedContext: scope.isDeployedContext }
1825+
: {}),
1826+
...(scope.billingAttribution ? { billingAttribution: scope.billingAttribution } : {}),
18191827
requestId,
18201828
},
18211829
},

0 commit comments

Comments
 (0)