{
  "parent_claim_id": "CVE-2026-49869",
  "parent_root_cause": "AuthenticationFilter.doFilter whitelists public endpoints with an over-permissive path string-match (endsWith('/configs')) that treats any /api/v1/** path whose final segment is 'configs' as the public config endpoint, bypassing Basic Auth. Combined with tenant aliasing and path-variable collision (flow namespace/id = 'configs'), an unauthenticated attacker reaches FlowController create + ExecutionController /trigger and achieves RCE.",
  "variant_root_cause": "AuthenticationFilter.doFilter has a SECOND over-permissive path string-match whitelist branch, isOpenUrl, that uses request.getPath().startsWith(s) for each entry in the production-default open-urls. The default open-urls include /api/v1/main/executions/webhook/, so the ExecutionController webhook trigger endpoints (/webhook/{namespace}/{id}/{key}) are reachable unauthenticated on every version. This is the SAME bug CLASS (over-permissive string-match whitelist in the SAME filter) but a DIFFERENT branch (isOpenUrl startsWith vs isConfigEndpoint endsWith) and a DIFFERENT controller endpoint (/webhook vs /trigger).",
  "shared_sink": "ExecutionController webhook()/triggerExecution -> flow execution -> io.kestra.plugin.scripts.shell.Commands task runs an attacker OS command in the Kestra worker (RCE).",
  "shared_filter": "webserver/src/main/java/io/kestra/webserver/filter/AuthenticationFilter.java",
  "equivalence_class": "AuthenticationFilter over-permissive path-whitelist string-match (suffix endsWith OR prefix startsWith) permitting path-variable/tenant-aliasing collision to bypass Basic Auth.",
  "differences_from_parent": {
    "whitelist_branch": "isOpenUrl (startsWith) instead of isConfigEndpoint (endsWith).",
    "trigger_endpoint": "ExecutionController /webhook/{ns}/{id}/{key} instead of /trigger/{ns}/{id}.",
    "trigger_path_terminator": "the webhook key (attacker-controlled), NOT the literal '/configs'.",
    "create_step": "unchanged -- still the /configs suffix bypass (isConfigEndpoint) for flow creation on the vulnerable version.",
    "fix_coverage": "fix 28ff533d8 hardens isConfigEndpoint only; isOpenUrl is untouched -> the trigger branch remains open on fixed/latest (documented behavior)."
  },
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "high",
  "same_sink_confidence": "high",
  "same_trust_boundary": true,
  "trust_boundary_note": "Both the parent and the variant cross the same trust boundary: unauthenticated remote HTTP -> Kestra webserver /api/v1/** -> authenticated controller -> worker OS command. The webhook trigger being open is an accepted, documented trust boundary (webhook key = secret), so the variant's TRIGGER step is documented behavior; the CVE-relevant element (unauthenticated RCE) comes from pairing it with the unauthenticated flow CREATE (the /configs bypass) on the vulnerable version.",
  "is_bypass_of_fix": false,
  "bypass_note": "Not a bypass: on the fixed version the /configs create-bypass is closed (401), so the attacker cannot plant the webhook flow and the open webhook returns 404 (no RCE). The fix is complete for the disclosed CVE; the variant identifies a defense-in-depth gap (isOpenUrl branch untouched by the fix)."
}
