33 * Enforces the two tool execution boundaries: external ToolConfig requests are materialized only
44 * by request-transport.ts, while same-process work uses registered InternalToolConfig operations.
55 * Tool definitions may not point back to Sim API routes or revive the retired request.internal
6- * escape hatch.
6+ * escape hatch. Dynamic provider origins remain supported because the executor rejects their
7+ * resolved URL when it targets Sim; only the two generic user-directed HTTP tools may opt out.
78 */
89import { existsSync , readdirSync , readFileSync , statSync } from 'node:fs'
910import { dirname , extname , join , relative , resolve } from 'node:path'
@@ -28,6 +29,7 @@ const FUNCTION_NODE_TYPES = new Set([
2829 'ObjectMethod' ,
2930] )
3031const URL_VALUE_WRAPPER_CALLS = new Set ( [ 'String' , 'encodeURI' , 'encodeURIComponent' ] )
32+ const APPROVED_SAME_ORIGIN_TOOL_IDS = new Set ( [ 'http_request' , 'webhook_request' ] )
3133
3234interface Violation {
3335 file : string
@@ -39,7 +41,11 @@ export interface ToolSelfHopViolation {
3941 file : string
4042 line : number
4143 toolId ?: string
42- reason : 'same-origin-tool-request' | 'legacy-internal-policy' | 'unresolved-request-policy'
44+ reason :
45+ | 'same-origin-tool-request'
46+ | 'legacy-internal-policy'
47+ | 'unresolved-request-policy'
48+ | 'unapproved-same-origin-policy'
4349}
4450
4551export interface ToolSelfHopAudit {
@@ -1619,8 +1625,16 @@ export function auditToolSelfHops(source: string, file = 'source.ts'): ToolSelfH
16191625 for ( const request of requests . requests ) {
16201626 const urlProperties = getResolvedObjectProperties ( request , 'url' )
16211627 const internalProperties = getResolvedObjectProperties ( request , 'internal' )
1628+ const allowSameOriginProperties = getResolvedObjectProperties (
1629+ request ,
1630+ 'allowSameOrigin'
1631+ )
16221632 let hasLegacyInternalPolicy = false
1623- if ( ! urlProperties . complete || ! internalProperties . complete ) {
1633+ if (
1634+ ! urlProperties . complete ||
1635+ ! internalProperties . complete ||
1636+ ! allowSameOriginProperties . complete
1637+ ) {
16241638 reportUnresolved ( requestProperty . loc ?. start . line ?? 1 )
16251639 }
16261640 for ( const resolvedInternal of internalProperties . properties ) {
@@ -1635,6 +1649,28 @@ export function auditToolSelfHops(source: string, file = 'source.ts'): ToolSelfH
16351649 reason : 'legacy-internal-policy' ,
16361650 } )
16371651 }
1652+ for ( const resolvedPolicy of allowSameOriginProperties . properties ) {
1653+ if ( ! resolvedPolicy ) continue
1654+ const policyProperty = resolvedPolicy . property
1655+ const policyValue =
1656+ policyProperty . type === 'ObjectProperty' && isSyntaxNode ( policyProperty . value )
1657+ ? unwrapExpression ( policyProperty . value )
1658+ : undefined
1659+ if ( ! policyValue || policyValue . type !== 'BooleanLiteral' ) {
1660+ reportUnresolved (
1661+ policyProperty . loc ?. start . line ?? requestProperty . loc ?. start . line ?? 1
1662+ )
1663+ continue
1664+ }
1665+ if ( policyValue . value === true && ! APPROVED_SAME_ORIGIN_TOOL_IDS . has ( toolId ) ) {
1666+ violations . push ( {
1667+ file,
1668+ line : policyProperty . loc ?. start . line ?? requestProperty . loc ?. start . line ?? 1 ,
1669+ toolId,
1670+ reason : 'unapproved-same-origin-policy' ,
1671+ } )
1672+ }
1673+ }
16381674 for ( const resolvedUrl of urlProperties . properties ) {
16391675 if ( ! resolvedUrl ) continue
16401676 const { property : urlProperty , request : urlRequest } = resolvedUrl
0 commit comments