Skip to content

Commit 51242f6

Browse files
committed
fix(workflows): retain tool context when masking encoded params
1 parent d563d65 commit 51242f6

2 files changed

Lines changed: 32 additions & 27 deletions

File tree

‎apps/sim/app/workspace/[workspaceId]/w/components/workflow-diff/utils.test.ts‎

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,35 @@ describe('structured field rendering', () => {
107107
expect(toDiffText([1])).not.toBe(toDiffText(['1']))
108108
})
109109

110-
it('masks declared tool password fields without projecting away other tool data', () => {
111-
declareSubBlocks({
112-
convex: [
113-
{ id: 'deployKey', type: 'short-input', password: true },
114-
{ id: 'secretAccess', type: 'dropdown' },
115-
],
116-
})
117-
const tools = [
118-
{
119-
type: 'convex',
120-
customToolId: 'tool-a',
121-
params: { deployKey: 'private', secretAccess: 'none', query: 'ok' },
122-
},
123-
]
124-
const rendered = toDiffText(tools, 'agent', 'tools')
125-
expect(rendered).not.toContain('private')
126-
expect(JSON.parse(rendered)).toEqual([
127-
{
128-
type: 'convex',
129-
customToolId: 'tool-a',
130-
params: { deployKey: '•••', secretAccess: 'none', query: 'ok' },
131-
},
132-
])
133-
})
110+
it.each([false, true])(
111+
'masks declared tool passwords without discarding other params (encoded: %s)',
112+
(encoded) => {
113+
declareSubBlocks({
114+
convex: [
115+
{ id: 'deployKey', type: 'short-input', password: true },
116+
{ id: 'secretAccess', type: 'dropdown' },
117+
],
118+
})
119+
const stored = (params: Record<string, unknown>) =>
120+
encoded ? JSON.stringify(params) : params
121+
const tools = [
122+
{
123+
type: 'convex',
124+
customToolId: 'tool-a',
125+
params: stored({ deployKey: 'private', secretAccess: 'none', query: 'ok' }),
126+
},
127+
]
128+
const rendered = toDiffText(tools, 'agent', 'tools')
129+
expect(rendered).not.toContain('private')
130+
expect(JSON.parse(rendered)).toEqual([
131+
{
132+
type: 'convex',
133+
customToolId: 'tool-a',
134+
params: stored({ deployKey: '•••', secretAccess: 'none', query: 'ok' }),
135+
},
136+
])
137+
}
138+
)
134139

135140
it('masks nested secrets in objects, encoded JSON and table cells', () => {
136141
const value = {

‎apps/sim/app/workspace/[workspaceId]/w/components/workflow-diff/utils.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ function isSecretKey(key: string): boolean {
193193
* Tool params persist structured values as JSON strings, so a header map with
194194
* an Authorization entry arrives encoded; decode, mask and re-encode it.
195195
*/
196-
function maskEncodedSecrets(value: string): string {
196+
function maskEncodedSecrets(value: string, blockType?: string): string {
197197
const trimmed = value.trimStart()
198198
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return value
199199
let parsed: unknown
@@ -203,7 +203,7 @@ function maskEncodedSecrets(value: string): string {
203203
return value
204204
}
205205
if (parsed === null || typeof parsed !== 'object') return value
206-
const masked = maskSecretsDeep(parsed)
206+
const masked = maskSecretsDeep(parsed, blockType)
207207
return JSON.stringify(masked) === JSON.stringify(parsed) ? value : JSON.stringify(masked)
208208
}
209209

@@ -214,7 +214,7 @@ function maskEncodedSecrets(value: string): string {
214214
*/
215215
export function maskSecretsDeep(value: unknown, blockType?: string): unknown {
216216
if (Array.isArray(value)) return value.map((entry) => maskSecretsDeep(entry))
217-
if (typeof value === 'string') return maskEncodedSecrets(value)
217+
if (typeof value === 'string') return maskEncodedSecrets(value, blockType)
218218
if (value === null || typeof value !== 'object') return value
219219
let record = value as Record<string, unknown>
220220
const cells = record.cells

0 commit comments

Comments
 (0)