Investigated and Dismissed

ID Original Threat Investigation Evidence Conclusion
D1 SQL injection via filter keys in PostgreSQL store Traced filter key handling through libs/checkpoint-postgres/langgraph/store/postgres/base.py:_get_filter_condition. All filter operations use parameterized queries with %s placeholders. Keys map to json_extract path operators with type-safe wrappers. libs/checkpoint-postgres/langgraph/store/postgres/base.py:_get_filter_condition — parameterized %s for all value bindings; key names used in value->%s path expressions are also parameterized Disproven: All SQL operations in PostgreSQL store are fully parameterized. No injection vector.
D2 SQL injection via filter keys in SQLite store (post-fix) Traced current filter handling through libs/checkpoint-sqlite/langgraph/store/sqlite/base.py and libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/utils.py:_validate_filter_key. Regex ^[a-zA-Z0-9_.-]+$ applied to all filter keys before use in json_extract() expressions. libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/utils.py:_validate_filter_key — regex validation blocks injection characters. Published advisories GHSA-9rwj-6rc7-p77c and GHSA-7p73-8jqx-23r8 confirmed fixed. Disproven: SQL injection in SQLite store filter keys is remediated by regex validation.
D3 Command injection via CLI subprocess execution Traced CLI subprocess invocation path. libs/cli/langgraph_cli/exec.py:subp_exec uses asyncio.create_subprocess_exec with list-based arguments (not shell=True). has_disallowed_build_command_content blocks shell metacharacters in user-provided Dockerfile lines. libs/cli/langgraph_cli/exec.py:subp_exec — explicit exec-style invocation; libs/cli/langgraph_cli/config.py:has_disallowed_build_command_content — regex blocks \|, ;, $, >, <, backtick, \, single & Disproven: CLI uses exec-style subprocess and validates build command content. No shell injection vector.
D4 Tool argument injection via InjectedState/InjectedStore dict-splatting Investigated whether LLM-generated tool call arguments could override system-injected values (InjectedState, InjectedStore, ToolRuntime) via key collision in the dict merge at libs/prebuilt/langgraph/prebuilt/tool_node.py:ToolNode._inject_tool_args line 1380. Traced four independent defense layers. (1) tool_call_schema at langchain-core base.py filters injected params from LLM schema. (2) {**llm_args, **injected_args} merge puts system values last — system wins on collision. (3) Pydantic model_validate with extra="ignore" drops unknown keys. (4) Output construction at base.py only includes declared model fields. Disproven: Four-layer defense prevents LLM arguments from overriding system-injected values. Merge order guarantees system values win. No adversarial collision path exists.