Skip to content

Commit 8c0616a

Browse files
committed
fix(tailscale): safe response.json() pattern, trim apiKey, guard expirySeconds
1 parent f6c6c34 commit 8c0616a

20 files changed

Lines changed: 64 additions & 63 deletions

apps/sim/tools/tailscale/authorize_device.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const tailscaleAuthorizeDeviceTool: ToolConfig<
4242
`https://api.tailscale.com/api/v2/device/${encodeURIComponent(params.deviceId.trim())}/authorized`,
4343
method: 'POST',
4444
headers: (params) => ({
45-
Authorization: `Bearer ${params.apiKey}`,
45+
Authorization: `Bearer ${params.apiKey.trim()}`,
4646
'Content-Type': 'application/json',
4747
}),
4848
body: (params) => ({

apps/sim/tools/tailscale/create_auth_key.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export const tailscaleCreateAuthKeyTool: ToolConfig<
7070
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/keys`,
7171
method: 'POST',
7272
headers: (params) => ({
73-
Authorization: `Bearer ${params.apiKey}`,
73+
Authorization: `Bearer ${params.apiKey.trim()}`,
7474
'Content-Type': 'application/json',
7575
}),
7676
body: (params) => {
@@ -100,16 +100,16 @@ export const tailscaleCreateAuthKeyTool: ToolConfig<
100100
}
101101

102102
if (params.description) body.description = params.description
103-
if (params.expirySeconds) body.expirySeconds = params.expirySeconds
103+
if (params.expirySeconds !== undefined && params.expirySeconds !== null)
104+
body.expirySeconds = params.expirySeconds
104105

105106
return body
106107
},
107108
},
108109

109110
transformResponse: async (response) => {
110-
const data = await response.json()
111-
112111
if (!response.ok) {
112+
const data = await response.json().catch(() => ({}))
113113
return {
114114
success: false,
115115
output: {
@@ -121,10 +121,11 @@ export const tailscaleCreateAuthKeyTool: ToolConfig<
121121
revoked: '',
122122
capabilities: { reusable: false, ephemeral: false, preauthorized: false, tags: [] },
123123
},
124-
error: data.message ?? 'Failed to create auth key',
124+
error: (data as Record<string, string>).message ?? 'Failed to create auth key',
125125
}
126126
}
127127

128+
const data = await response.json()
128129
const deviceCaps = data.capabilities?.devices?.create ?? {}
129130

130131
return {

apps/sim/tools/tailscale/delete_auth_key.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const tailscaleDeleteAuthKeyTool: ToolConfig<
4848
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/keys/${encodeURIComponent(params.keyId.trim())}`,
4949
method: 'DELETE',
5050
headers: (params) => ({
51-
Authorization: `Bearer ${params.apiKey}`,
51+
Authorization: `Bearer ${params.apiKey.trim()}`,
5252
}),
5353
},
5454

apps/sim/tools/tailscale/delete_device.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const tailscaleDeleteDeviceTool: ToolConfig<
3636
`https://api.tailscale.com/api/v2/device/${encodeURIComponent(params.deviceId.trim())}`,
3737
method: 'DELETE',
3838
headers: (params) => ({
39-
Authorization: `Bearer ${params.apiKey}`,
39+
Authorization: `Bearer ${params.apiKey.trim()}`,
4040
}),
4141
},
4242

apps/sim/tools/tailscale/get_acl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const tailscaleGetAclTool: ToolConfig<TailscaleBaseParams, TailscaleGetAc
3434
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/acl`,
3535
method: 'GET',
3636
headers: (params) => ({
37-
Authorization: `Bearer ${params.apiKey}`,
37+
Authorization: `Bearer ${params.apiKey.trim()}`,
3838
Accept: 'application/json',
3939
}),
4040
},

apps/sim/tools/tailscale/get_auth_key.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,13 @@ export const tailscaleGetAuthKeyTool: ToolConfig<
5757
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/keys/${encodeURIComponent(params.keyId.trim())}`,
5858
method: 'GET',
5959
headers: (params) => ({
60-
Authorization: `Bearer ${params.apiKey}`,
60+
Authorization: `Bearer ${params.apiKey.trim()}`,
6161
}),
6262
},
6363

6464
transformResponse: async (response) => {
65-
const data = await response.json()
66-
6765
if (!response.ok) {
66+
const data = await response.json().catch(() => ({}))
6867
return {
6968
success: false,
7069
output: {
@@ -75,10 +74,11 @@ export const tailscaleGetAuthKeyTool: ToolConfig<
7574
revoked: '',
7675
capabilities: { reusable: false, ephemeral: false, preauthorized: false, tags: [] },
7776
},
78-
error: data.message ?? 'Failed to get auth key',
77+
error: (data as Record<string, string>).message ?? 'Failed to get auth key',
7978
}
8079
}
8180

81+
const data = await response.json()
8282
const deviceCaps = data.capabilities?.devices?.create ?? {}
8383

8484
return {

apps/sim/tools/tailscale/get_device.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,13 @@ export const tailscaleGetDeviceTool: ToolConfig<TailscaleDeviceParams, Tailscale
3434
`https://api.tailscale.com/api/v2/device/${encodeURIComponent(params.deviceId.trim())}`,
3535
method: 'GET',
3636
headers: (params) => ({
37-
Authorization: `Bearer ${params.apiKey}`,
37+
Authorization: `Bearer ${params.apiKey.trim()}`,
3838
}),
3939
},
4040

4141
transformResponse: async (response) => {
42-
const data = await response.json()
43-
4442
if (!response.ok) {
43+
const data = await response.json().catch(() => ({}))
4544
return {
4645
success: false,
4746
output: {
@@ -62,10 +61,11 @@ export const tailscaleGetDeviceTool: ToolConfig<TailscaleDeviceParams, Tailscale
6261
machineKey: '',
6362
nodeKey: '',
6463
},
65-
error: data.message ?? 'Failed to get device',
64+
error: (data as Record<string, string>).message ?? 'Failed to get device',
6665
}
6766
}
6867

68+
const data = await response.json()
6969
return {
7070
success: true,
7171
output: {

apps/sim/tools/tailscale/get_device_routes.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ export const tailscaleGetDeviceRoutesTool: ToolConfig<
3636
`https://api.tailscale.com/api/v2/device/${encodeURIComponent(params.deviceId.trim())}/routes`,
3737
method: 'GET',
3838
headers: (params) => ({
39-
Authorization: `Bearer ${params.apiKey}`,
39+
Authorization: `Bearer ${params.apiKey.trim()}`,
4040
}),
4141
},
4242

4343
transformResponse: async (response) => {
44-
const data = await response.json()
45-
4644
if (!response.ok) {
45+
const data = await response.json().catch(() => ({}))
4746
return {
4847
success: false,
4948
output: { advertisedRoutes: [], enabledRoutes: [] },
50-
error: data.message ?? 'Failed to get device routes',
49+
error: (data as Record<string, string>).message ?? 'Failed to get device routes',
5150
}
5251
}
5352

53+
const data = await response.json()
5454
return {
5555
success: true,
5656
output: {

apps/sim/tools/tailscale/get_dns_preferences.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ export const tailscaleGetDnsPreferencesTool: ToolConfig<
3636
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/dns/preferences`,
3737
method: 'GET',
3838
headers: (params) => ({
39-
Authorization: `Bearer ${params.apiKey}`,
39+
Authorization: `Bearer ${params.apiKey.trim()}`,
4040
}),
4141
},
4242

4343
transformResponse: async (response) => {
44-
const data = await response.json()
45-
4644
if (!response.ok) {
45+
const data = await response.json().catch(() => ({}))
4746
return {
4847
success: false,
4948
output: { magicDNS: false },
50-
error: data.message ?? 'Failed to get DNS preferences',
49+
error: (data as Record<string, string>).message ?? 'Failed to get DNS preferences',
5150
}
5251
}
5352

53+
const data = await response.json()
5454
return {
5555
success: true,
5656
output: {

apps/sim/tools/tailscale/get_dns_searchpaths.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ export const tailscaleGetDnsSearchpathsTool: ToolConfig<
3636
`https://api.tailscale.com/api/v2/tailnet/${encodeURIComponent(params.tailnet.trim())}/dns/searchpaths`,
3737
method: 'GET',
3838
headers: (params) => ({
39-
Authorization: `Bearer ${params.apiKey}`,
39+
Authorization: `Bearer ${params.apiKey.trim()}`,
4040
}),
4141
},
4242

4343
transformResponse: async (response) => {
44-
const data = await response.json()
45-
4644
if (!response.ok) {
45+
const data = await response.json().catch(() => ({}))
4746
return {
4847
success: false,
4948
output: { searchPaths: [] },
50-
error: data.message ?? 'Failed to get DNS search paths',
49+
error: (data as Record<string, string>).message ?? 'Failed to get DNS search paths',
5150
}
5251
}
5352

53+
const data = await response.json()
5454
return {
5555
success: true,
5656
output: {

0 commit comments

Comments
 (0)