Skip to content

Commit 46fa6f2

Browse files
committed
fix(tools): freeze the tool id array handed out by getToolIds
`getToolIds()` returned the module's internal array by reference, so a caller doing `getToolIds().sort()` would reorder it in place and silently corrupt every later lookup — the in-place-mutation footgun `.claude/rules/sim-react-performance.md` calls out. Frozen rather than copied: the array is consumed in loops, so copying would allocate on every call. Freezing makes the mutation throw instead of corrupt, and `[...getToolIds()].sort()` still works. Return type is now `readonly string[]`, so the mistake is a compile error rather than a runtime surprise. No caller mutates it today; this is closing the hole, not fixing a live bug.
1 parent 131b471 commit 46fa6f2

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

apps/sim/tools/tool-ids.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ import rawToolIds from '@/tools/generated/tool-ids'
1414
* including returning the input unchanged when nothing matches. See
1515
* `.agents/skills/tool-registry-boundary/SKILL.md`.
1616
*/
17-
const toolIds: string[] = rawToolIds
17+
/**
18+
* Frozen because {@link getToolIds} hands it out directly. Returning a copy
19+
* would allocate on every call in the loops that consume it; freezing makes an
20+
* in-place `sort()`/`push()` by a caller throw rather than silently corrupt
21+
* every later lookup.
22+
*/
23+
const toolIds: readonly string[] = Object.freeze(rawToolIds)
1824

1925
const toolIdSet = new Set(toolIds)
2026

@@ -48,8 +54,8 @@ function getLatestByBaseName(): Map<string, string> {
4854
return latestByBaseName
4955
}
5056

51-
/** Every registered tool id, including versioned variants. */
52-
export function getToolIds(): string[] {
57+
/** Every registered tool id, including versioned variants. Frozen — copy before sorting. */
58+
export function getToolIds(): readonly string[] {
5359
return toolIds
5460
}
5561

0 commit comments

Comments
 (0)