Root cause
SSRF & network boundaries introduced
The client is constructed from the configured base URL without a pinned network address.
How AI contributed: Direct introductionPublished May 4, 2026 in
czlonkowski/n8n-mcpAll 11 findings in this repository
Provisional finding. Full causal and release verification remains incomplete.
Root cause
The client is constructed from the configured base URL without a pinned network address.
Fix
The request interceptor installs transport agents pinned to the validated address.
Case facts
@@ -0,0 +43,18 @@++ // Ensure baseUrl ends with /api/v1+ const apiUrl = baseUrl.endsWith('/api/v1') + ? baseUrl + : `${baseUrl.replace(/\/$/, '')}/api/v1`;++ this.client = axios.create({+ baseURL: apiUrl,+ timeout,+ headers: {+ 'X-N8N-API-KEY': apiKey,+ 'Content-Type': 'application/json',+ },+ });++ // Request interceptor for logging+ this.client.interceptors.request.use(+ (config: InternalAxiosRequestConfig) => {@@ -94,8 +100,13 @@- // Request interceptor for logging+ // Request interceptor for logging + transport pinning this.client.interceptors.request.use(- (config: InternalAxiosRequestConfig) => {+ async (config: InternalAxiosRequestConfig) => {+ // SECURITY (GHSA-cmrh-wvq6-wm9r): pin transport to validated IP.+ const agents = await this.getPinnedAgents();+ config.httpAgent = agents.httpAgent;+ config.httpsAgent = agents.httpsAgent;+ // Redact request body for credential endpoints to prevent secret leakage const isSensitive = config.url?.includes('/credentials') && config.method !== 'get'; logger.debug(`n8n API Request: ${config.method?.toUpperCase()} ${config.url}`, { params: config.params, data: isSensitive ? '[REDACTED]' : config.data,AI-assisted change b9e86decd66b9a58163f84b1b88f44938faf446d68c0780e17c593991225ba75 · Fix 2ad09ef35279b6f144764197ce451144f79bc2115aebaedfb1f96baebc56200a