fix(execute-command): extend env blocklist, add error output, fix tag regex

- Extend BLOCKED_ENV_KEYS with NODE_OPTIONS, LD_AUDIT, DYLD_LIBRARY_PATH,
  DYLD_FRAMEWORK_PATH, GLIBC_TUNABLES, NODE_PATH, PYTHONPATH, PERL5LIB,
  RUBYLIB to prevent process-influencing env var injection.

- Add error field to block and tool output schemas so downstream blocks
  can inspect timeout/buffer errors via <executeCommand.error>. Handler
  returns error: null on success for consistency.

- Use permissive tag regex ([^<>]+) matching createReferencePattern() so
  block names with hyphens (e.g. <my-block.output>) resolve correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Waleed Latif
2026-03-05 14:16:25 -08:00
parent 3d0b07b555
commit 7b7ab8d2c2
4 changed files with 19 additions and 2 deletions

View File

@@ -38,11 +38,20 @@ function getSafeBaseEnv(): NodeJS.ProcessEnv {
const BLOCKED_ENV_KEYS = new Set([
...SAFE_ENV_KEYS,
'NODE_ENV',
'NODE_OPTIONS',
'LD_PRELOAD',
'LD_LIBRARY_PATH',
'LD_AUDIT',
'DYLD_INSERT_LIBRARIES',
'DYLD_LIBRARY_PATH',
'DYLD_FRAMEWORK_PATH',
'BASH_ENV',
'ENV',
'GLIBC_TUNABLES',
'NODE_PATH',
'PYTHONPATH',
'PERL5LIB',
'RUBYLIB',
])
/**
@@ -140,7 +149,7 @@ function collectTagReplacements(
blockOutputSchemas: Record<string, OutputSchema>
): Replacement[] {
const tagPattern = new RegExp(
`${REFERENCE.START}([a-zA-Z_](?:[a-zA-Z0-9_${REFERENCE.PATH_DELIMITER}]*[a-zA-Z0-9_])?)${REFERENCE.END}`,
`${REFERENCE.START}([^${REFERENCE.START}${REFERENCE.END}]+)${REFERENCE.END}`,
'g'
)

View File

@@ -71,5 +71,9 @@ IMPORTANT FORMATTING RULES:
stdout: { type: 'string', description: 'Standard output from the command' },
stderr: { type: 'string', description: 'Standard error output from the command' },
exitCode: { type: 'number', description: 'Exit code of the command (0 = success)' },
error: {
type: 'string',
description: 'Error message if the command timed out or exceeded buffer limits',
},
},
}

View File

@@ -53,6 +53,6 @@ export class ExecuteCommandBlockHandler implements BlockHandler {
throw new Error(result.error || 'Command execution failed')
}
return result.output
return { ...result.output, error: null }
}
}

View File

@@ -114,5 +114,9 @@ export const executeCommandRunTool: ToolConfig<ExecuteCommandInput, ExecuteComma
stdout: { type: 'string', description: 'Standard output from the command' },
stderr: { type: 'string', description: 'Standard error output from the command' },
exitCode: { type: 'number', description: 'Exit code of the command (0 = success)' },
error: {
type: 'string',
description: 'Error message if the command timed out or exceeded buffer limits',
},
},
}