Date: 2026-06-17 Target: n8n (master, post fresh ~30-CVE disclosure 2026-06-16) Verdict: WALK CLEAN (fresh cluster #3).
4 high-severity related advisories (GHSA-2j5h Cross-Tenant Credential Takeover via Dynamic Credential, 6h4j
Cross-user Authz Bypass in Dynamic Credential, r4v6 Credential Authz Bypass in dynamic-node-parameters, pmqw
Credential Exfiltration via Permission Bypass) all center on the dynamic-node-parameters controller. Read it via
raw github (no clone). The controller has 5 @Post endpoints (/options, /resource-locator-results,
/resource-mapper-fields, /local-resource-mapper-fields, /action-result) - ALL 5 call
dynamicNodeParametersService.refineResourceIds(req.user, payload) at the top. refineResourceIds collects every
credential ID in the payload and calls credentialsFinderService.findCredentialIdsWithScopeForUser(ids, user,
['credential:read']); any id the user can't access -> throw new ForbiddenError(). Centralized check, applied
to every endpoint, throws on forbidden. Set-difference within the named surface = EMPTY. Swept.
fix is usually a single centralized guard applied across the whole surface -> walk. n8n joins Symfony/undici/ axios/aiohttp/Django-most as a sweeper. Contrast the POINT-FIXERS that yielded (PyJWT, form-data, Django-Truncator, PHPNuxBill). The tell held: read the fix's SCOPE - here, ONE helper (refineResourceIds) on ALL endpoints = swept; a per-endpoint inline check missing one = would have been the hunt.
github (master = post-fix) and enumerate {endpoints} vs {the new guard}. Resolved the whole cluster in ~3 file reads. A deeper monorepo-wide sibling hunt (other credential-resolving endpoints: execution, credential-test, OAuth) is a large dedicated effort with uncertain yield against a thorough sweeper -> warrants explicit operator go-ahead before the spend, not a unilateral launch.
directive. (PHPNuxBill, an operator-named priority, yielded 2 findings in between.)