(
tools: Array<ToolLike>,
options: {
handler?: SecretParameterHandler
dedupCache?: Set<string>
} = {},
)
| 157 | * Best-effort heuristic, not a security boundary. |
| 158 | */ |
| 159 | export function warnIfBindingsExposeSecrets( |
| 160 | tools: Array<ToolLike>, |
| 161 | options: { |
| 162 | handler?: SecretParameterHandler |
| 163 | dedupCache?: Set<string> |
| 164 | } = {}, |
| 165 | ): void { |
| 166 | const { handler = 'warn', dedupCache } = options |
| 167 | if (handler === 'ignore') return |
| 168 | |
| 169 | for (const tool of tools) { |
| 170 | const schema = tool.inputSchema as JsonSchemaLike | undefined |
| 171 | if (!schema) continue |
| 172 | |
| 173 | const found: Array<{ path: Array<string>; name: string }> = [] |
| 174 | findSecretParams(schema, schema, new Set(), [], found) |
| 175 | |
| 176 | for (const entry of found) { |
| 177 | const dedupKey = `${tool.name}::${entry.path.join('.')}` |
| 178 | if (dedupCache) { |
| 179 | if (dedupCache.has(dedupKey)) continue |
| 180 | dedupCache.add(dedupKey) |
| 181 | } |
| 182 | |
| 183 | const info: SecretParameterInfo = { |
| 184 | toolName: tool.name, |
| 185 | paramName: entry.name, |
| 186 | paramPath: entry.path, |
| 187 | } |
| 188 | |
| 189 | if (typeof handler === 'function') { |
| 190 | handler(info) |
| 191 | } else if (handler === 'throw') { |
| 192 | throw new Error(buildMessage(tool.name, entry.path)) |
| 193 | } else { |
| 194 | console.warn(buildMessage(tool.name, entry.path)) |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | } |
no test coverage detected