dbt-mcp node_selection/resource_type Argument Injection (CVE-2026-44968)
Detects CVE-2026-44968 / GHSA-xpww-f6pm-cfhq (CWE-88): dbt-mcp's _run_dbt_command() in src/dbt_mcp/dbt_cli/tools.py appends the MCP-client-supplied node_selection string (split on space) and resource_type JSON array verbatim to the dbt subprocess argv without validating that tokens don't begin with a dash. Because Popen is called with shell=False, shell metacharacters are inert, but an attacker can still inject dbt global flags — --profiles-dir, --project-dir, --target, --profile — as independent argv elements on the build/compile/run/test/ clone/list/get_node_details_dev tools, redirecting dbt's configuration, project root, or execution target (demonstrated PoC: node_selection = "my_model --profiles-dir /tmp/evil" loads an attacker-controlled profiles.yml and writes to an attacker-chosen database path). Detection covers: (a) a node_selection value containing an injected dbt global flag token after the legitimate selector (space-separated, so the flag rides along as an extra "word"); (b) a resource_type JSON array containing an injected flag token as an array element instead of a valid resource type; (c) explicit CVE-2026-44968 / GHSA-xpww-f6pm-cfhq exploitation framing. The detection target is the request shape — a dash-prefixed dbt global flag riding inside a selector/resource-type value that should only ever contain a selector or resource-type token — which is the exact argument- injection primitive, caught before _run_dbt_command() extends argv. Bound to the dbt-mcp tool surface (node_selection/resource_type params) so a benign selector string elsewhere does not fire.
建議回應
參考資料
偵測條件
組合方式: any- 01node_selection value whose space-separated tokens include an injected dbt global flag (--profiles-dir/--project-dir/--target/ --profile) after the legitimate selector — CVE-2026-44968 Vector 1.欄位: tool_args運算子: regex
- 02resource_type JSON array containing an injected dbt global flag token as an array element instead of a valid resource type — CVE-2026-44968 Vector 2.欄位: tool_args運算子: regex
- 03An injected dbt global flag pointing at an attacker-controlled path appearing alongside the vulnerable --select/--resource-type argv construction.欄位: tool_args運算子: regex
- 04Explicit CVE-2026-44968 / GHSA-xpww-f6pm-cfhq reference combined with dbt-mcp argument-injection language — attack framing in a skill or tool description.欄位: content運算子: regex
攻擊範例(規則會觸發)
以上為真實攻擊 payload 的脫敏版本,與規則一同版本化,作為 regression test——確保未來的修訂不會悄悄漏掉它們。
正常樣本(規則不會觸發)
- Legitimate dbt selector syntax with plus-operator and tag: method, no injected flag
- Valid resource_type array with only real dbt resource type names
- Benign question about dbt-mcp node_selection usage
- Simple model selector, no flags, read-only compile intent
已知誤報情境
- ▸A node_selection value that legitimately contains a dbt selector method using a colon (tag:, config:) rather than a dash-prefixed flag.
- ▸Security advisory or PR text quoting the CVE-2026-44968 / GHSA-xpww-f6pm-cfhq payload for review purposes.
- ▸A resource_type array containing only valid dbt resource type names (model, test, snapshot, source, etc.) with no injected flag.
完整 YAML 定義
在 GitHub 編輯 →title: "dbt-mcp node_selection/resource_type Argument Injection (CVE-2026-44968)"
id: ATR-2026-01982
rule_version: 1
status: draft
description: >
Detects CVE-2026-44968 / GHSA-xpww-f6pm-cfhq (CWE-88): dbt-mcp's
_run_dbt_command() in src/dbt_mcp/dbt_cli/tools.py appends the
MCP-client-supplied node_selection string (split on space) and
resource_type JSON array verbatim to the dbt subprocess argv without
validating that tokens don't begin with a dash. Because Popen is called
with shell=False, shell metacharacters are inert, but an attacker can still
inject dbt global flags — --profiles-dir, --project-dir, --target,
--profile — as independent argv elements on the build/compile/run/test/
clone/list/get_node_details_dev tools, redirecting dbt's configuration,
project root, or execution target (demonstrated PoC: node_selection =
"my_model --profiles-dir /tmp/evil" loads an attacker-controlled
profiles.yml and writes to an attacker-chosen database path).
Detection covers:
(a) a node_selection value containing an injected dbt global flag token
after the legitimate selector (space-separated, so the flag rides
along as an extra "word");
(b) a resource_type JSON array containing an injected flag token as an
array element instead of a valid resource type;
(c) explicit CVE-2026-44968 / GHSA-xpww-f6pm-cfhq exploitation framing.
The detection target is the request shape — a dash-prefixed dbt global
flag riding inside a selector/resource-type value that should only ever
contain a selector or resource-type token — which is the exact argument-
injection primitive, caught before _run_dbt_command() extends argv. Bound
to the dbt-mcp tool surface (node_selection/resource_type params) so a
benign selector string elsewhere does not fire.
author: "ATR Community"
date: "2026/07/04"
schema_version: "0.1"
detection_tier: pattern
maturity: test
severity: medium
references:
owasp_llm:
- "LLM06:2025 - Excessive Agency"
owasp_agentic:
- "ASI06:2026 - Tool Misuse"
mitre_atlas:
- "AML.T0053 - LLM Plugin Compromise"
mitre_attack:
- "T1059 - Command and Scripting Interpreter"
cve:
- "CVE-2026-44968"
ghsa:
- "GHSA-xpww-f6pm-cfhq"
metadata_provenance:
mitre_atlas: human-reviewed
owasp_llm: human-reviewed
owasp_agentic: human-reviewed
compliance:
eu_ai_act:
- { article: "15", context: "Article 15 cybersecurity — runtime detection of dbt-mcp node_selection/resource_type argument injection.", strength: primary }
- { article: "9", context: "Article 9 risk management — runtime risk-treatment control for dbt-mcp node_selection/resource_type argument injection.", strength: secondary }
nist_ai_rmf:
- { subcategory: "MP.5.1", context: "MAP 5.1 — adversarial input characterised/detected for dbt-mcp node_selection/resource_type argument injection.", strength: primary }
- { subcategory: "MG.3.2", context: "MANAGE 3.2 — runtime monitoring control for dbt-mcp node_selection/resource_type argument injection.", strength: secondary }
iso_42001:
- { clause: "8.1", context: "Clause 8.1 operational control — detection of dbt-mcp node_selection/resource_type argument injection payload.", strength: primary }
- { clause: "8.3", context: "Clause 8.3 AI risk treatment — runtime detection as treatment control.", strength: secondary }
tags:
category: tool-poisoning
subcategory: argument-injection
scan_target: mcp
confidence: high
source: cve-disclosure
vendor_sources: dbt-mcp-cve-2026-44968
agent_source:
type: tool_call
framework:
- dbt-mcp
- any
provider:
- any
detection:
condition: any
false_positives:
- "A node_selection value that legitimately contains a dbt selector method using a colon (tag:, config:) rather than a dash-prefixed flag."
- "Security advisory or PR text quoting the CVE-2026-44968 / GHSA-xpww-f6pm-cfhq payload for review purposes."
- "A resource_type array containing only valid dbt resource type names (model, test, snapshot, source, etc.) with no injected flag."
conditions:
- field: tool_args
operator: regex
value: '(?i)\bnode_selection["\x27]?\s*[:=]\s*["\x27][^"\x27\n]{0,200}\s(?:--profiles-dir|--project-dir|--target|--profile)\b'
description: >
node_selection value whose space-separated tokens include an
injected dbt global flag (--profiles-dir/--project-dir/--target/
--profile) after the legitimate selector — CVE-2026-44968 Vector 1.
- field: tool_args
operator: regex
value: '(?i)\bresource_type["\x27]?\s*[:=]\s*\[[^\]\n]{0,200}["\x27](?:--profiles-dir|--project-dir|--target|--profile)["\x27][^\]\n]{0,200}\]'
description: >
resource_type JSON array containing an injected dbt global flag
token as an array element instead of a valid resource type —
CVE-2026-44968 Vector 2.
- field: tool_args
operator: regex
value: '(?i)--(?:profiles-dir|project-dir|target|profile)\s+["\x27]?/tmp/[^"\x27\s\n]{0,80}["\x27]?[\s\S]{0,120}\b(?:node_selection|resource_type|--select|--resource-type)\b'
description: >
An injected dbt global flag pointing at an attacker-controlled path
appearing alongside the vulnerable --select/--resource-type argv
construction.
- field: content
operator: regex
value: '(?i)(?:CVE-2026-44968|GHSA-xpww-f6pm-cfhq)[\s\S]{0,200}(?:dbt-mcp|node_selection|resource_type|profiles-dir|argument\s*inject)'
description: >
Explicit CVE-2026-44968 / GHSA-xpww-f6pm-cfhq reference combined with
dbt-mcp argument-injection language — attack framing in a skill or
tool description.
response:
actions:
- alert
- block_tool
message_template: >
[ATR-2026-01982] MEDIUM: dbt-mcp node_selection/resource_type argument
injection detected (CVE-2026-44968, CWE-88). A tool argument injects a
dbt global flag (--profiles-dir/--project-dir/--target) as an argv
element; dbt-mcp before 1.17.1 appends this to the dbt subprocess
unsanitized. Block the tool call and upgrade dbt-mcp to >= 1.17.1.
confidence: 80
wild_fp_rate: 0
test_cases:
true_positives:
- tool_args: 'node_selection="my_first_model --profiles-dir /tmp/evil-profiles"'
expected: triggered
description: "PoC Vector 1: node_selection injects --profiles-dir pointing at attacker path"
- tool_args: 'resource_type=["model", "--profiles-dir", "/tmp/evil-profiles"]'
expected: triggered
description: "PoC Vector 2: resource_type array smuggles --profiles-dir as an element"
- tool_description: "Exploiting CVE-2026-44968 (GHSA-xpww-f6pm-cfhq) in dbt-mcp: craft node_selection to inject --profiles-dir for argument injection against the dbt CLI."
expected: triggered
description: "Explicit CVE-2026-44968 dbt-mcp exploitation framing"
true_negatives:
- tool_args: 'node_selection="my_first_model+ tag:nightly"'
expected: not_triggered
description: "Legitimate dbt selector syntax with plus-operator and tag: method, no injected flag"
- tool_args: 'resource_type=["model", "test", "source"]'
expected: not_triggered
description: "Valid resource_type array with only real dbt resource type names"
- content: "How do I filter dbt models using node_selection in the dbt-mcp run tool?"
expected: not_triggered
description: "Benign question about dbt-mcp node_selection usage"
- tool_args: 'node_selection="staging.orders"'
expected: not_triggered
description: "Simple model selector, no flags, read-only compile intent"