Commit Graph

15208 Commits

Author SHA1 Message Date
John Kennedy
51a4e7d27a feat(tests): add argument hijacking tests and Google Gemini support
- Add argument hijacking test cases (BCC injection, subject manipulation,
  body append, recipient swap) to test subtle attacks where tool calls are
  expected but arguments are manipulated
- Add Google Gemini (gemini-3-flash-preview) to all benchmark tests
- Use granite4:small-h instead of tiny-h for more reliable Ollama tests
- DRY up Ollama config by using constants from conftest
2026-01-31 15:37:57 -08:00
John Kennedy
76468eb28e fix(tests): check tool triggering instead of string presence in injection tests
The security property we care about is whether malicious tools are triggered,
not whether malicious-looking strings appear in output. Data may legitimately
contain URLs/emails that look suspicious but aren't actionable injections.

- Replace string-based assertions with check_triggers_tools() that verifies
  the sanitized output doesn't trigger target tools when fed back to model
- Remove assert_*_blocked functions that checked for domain strings
- Simplify INJECTION_TEST_CASES to (payload, tools, tool_name, target_tools)
2026-01-31 15:13:42 -08:00
John Kennedy
345ab3870b fixup! refactor: DRY up extended tests, focus on prompt injection only 2026-01-31 14:57:48 -08:00
John Kennedy
85360afd14 feat: add marker sanitization and filter mode for prompt injection defense
- Add DEFAULT_INJECTION_MARKERS list covering major LLM providers:
  - Defense prompt delimiters
  - Llama/Mistral: [INST], <<SYS>>
  - OpenAI/Qwen (ChatML): <|im_start|>, <|im_end|>
  - Anthropic Claude: Human:/Assistant: (with newline prefix)
  - DeepSeek: fullwidth Unicode markers
  - Google Gemma: <start_of_turn>, <end_of_turn>
  - Vicuna: USER:/ASSISTANT:
  - Generic XML role markers

- Add sanitize_markers() function to strip injection markers from content
- Add configurable sanitize_markers param to CheckToolStrategy and ParseDataStrategy
- Add filter mode (on_injection='filter') that uses model's text response
  when injection detected (no extra LLM call needed)
- Add _get_tool_schema() for tool return type descriptions in ParseDataStrategy
- Export DEFAULT_INJECTION_MARKERS and sanitize_markers from __init__.py
2026-01-31 14:55:23 -08:00
John Kennedy
62349bd6fd test: reorganize prompt injection tests and skip E2E by default
- Rename test_prompt_injection_combined.py -> test_prompt_injection_baseline_vs_protected.py
- Delete redundant test_prompt_injection_defense_extended.py
- Skip E2E tests by default (require RUN_BENCHMARK_TESTS=1)
- Reduce Ollama models to frontier only (granite4:tiny-h)
- Refactor to reduce code duplication in test files
- Update docstrings with cross-references

Test organization:
- test_prompt_injection_defense.py: Unit tests with mocks (CI, fast)
- test_prompt_injection_baseline_vs_protected.py: E2E baseline vs protected
- test_prompt_injection_token_benchmark.py: Token usage benchmarks

To run E2E tests with real models:
    RUN_BENCHMARK_TESTS=1 uv run pytest tests/unit_tests/agents/middleware/implementations/test_prompt_injection_* -svv
2026-01-31 14:55:23 -08:00
John Kennedy
46cdd2245b test: refactor prompt injection tests to reduce duplication
- Add helper functions: make_tool_message, make_tool_request,
  make_triggered_response, setup_model_with_response
- Parameterize tests for providers, factory methods, strategies
- Add fixtures for common mock setups
- Consolidate similar test cases while maintaining coverage
2026-01-31 14:55:23 -08:00
John Kennedy
f03127e7fd test: add combined baseline/protected test and token benchmark
- test_prompt_injection_combined.py: single test shows both baseline
  vulnerability and protected status for each model/payload
- test_prompt_injection_token_benchmark.py: measures token usage across
  no_defense, check_only, parse_only, and combined strategies
2026-01-31 14:55:23 -08:00
John Kennedy
e088029a63 test: expand injection payloads to 20 variants across 5 attack categories
- 4 variants per attack category:
  - Goal hijacking: system update, priority override, casual, xml tags
  - Privilege escalation: html comment, js comment, maintenance, sql
  - Indirect trigger: sysadmin note, friendly, auto cleanup, doc metadata
  - Multi-language: spanish, german, chinese, portuguese
  - JSON/XML injection: notes field, internal directive, nested meta, xml
- Use realistic test domains (test-sink.net, etc.) instead of obvious names
- 260 tests total: 20 attacks × 13 models
2026-01-31 14:55:23 -08:00
John Kennedy
1fbf7cf910 refactor: simplify prompt injection tests, add shared conftest
- Create conftest.py with shared tools, payloads, fixtures, and helpers
- Consolidate extended tests into simple parametrized test classes
- Add multi_language and json_injection to test cases (5 total attacks)
- Baseline and protected tests now use same test cases for comparison
- 65 tests each: 5 attacks × 13 models (3 OpenAI, 3 Anthropic, 7 Ollama)
2026-01-31 14:55:23 -08:00
John Kennedy
b7dac2c90b fix: cleanup unused imports, add Anthropic to extended tests
- Remove unused SystemMessage import
- Fix reference to non-existent e2e test file
- Add anthropic_model to all parameterized security tests
- Now tests both OpenAI (gpt-5.2) and Anthropic (claude-sonnet-4-5)
2026-01-31 14:55:22 -08:00
John Kennedy
97b933ae1f refactor: DRY up extended tests, focus on prompt injection only
- Extract shared attack payloads as constants
- Add helper functions for strategy creation and assertions
- Parameterize Ollama tests to reduce duplication
- Remove non-security tests (caching, false positives, safe content)
- Update models to gpt-5.2 and claude-sonnet-4-5
- 11 tests total (7 OpenAI, 4 Ollama skipped)
2026-01-31 14:55:22 -08:00
John Kennedy
7b695f047a Add PromptInjectionDefenseMiddleware with pluggable strategy pattern
Implements defense against indirect prompt injection attacks from external/untrusted
data sources (tool results, web content, etc.) based on the paper:
'Defense Against Indirect Prompt Injection via Tool Result Parsing'
https://arxiv.org/html/2601.04795v1

Features:
- Pluggable DefenseStrategy protocol for extensibility
- Built-in strategies: CheckToolStrategy, ParseDataStrategy, CombinedStrategy
- Factory methods for recommended configurations from paper
- Focuses on tool results as primary attack vector
- Extensible to other external data sources in the future

Key components:
- PromptInjectionDefenseMiddleware: Main middleware class
- DefenseStrategy: Protocol for custom defense implementations
- CheckToolStrategy: Detects and removes tool-triggering content
- ParseDataStrategy: Extracts only required data with format constraints
- CombinedStrategy: Chains multiple strategies together

Usage:
  agent = create_agent(
      'openai:gpt-4o',
      middleware=[
          PromptInjectionDefenseMiddleware.check_then_parse('openai:gpt-4o'),
      ],
  )
2026-01-31 14:55:22 -08:00
ccurme
b50ecd49eb release(standard-tests): 1.1.3 (#34949) langchain-standard-tests==1.1.3 langchain-tests==1.1.3 2026-01-31 16:39:23 -05:00
John Kennedy
c5834cc028 chore: upgrade urllib3 to 2.6.3 (#34940) 2026-01-31 16:30:17 -05:00
Jackjin
488db577e2 fix(core): prevent crash in ParrotFakeChatModel when messages list is empty (#34943) 2026-01-31 16:17:39 -05:00
Abhishek Laddha
ccd4032789 docs(docs): add uv sync step to local setup instructions (#34944) 2026-01-31 16:16:43 -05:00
Louis Auneau
f5252b438e fix(core): google docstring parsing with no arguments/reserved arguments (#34861) 2026-01-30 22:48:58 -05:00
Lewis Whitehill
0c9d392d41 test(core): add tests for approximate token counting with multimodal messages (#34898) 2026-01-30 12:35:16 -08:00
Mason Daugherty
638c33f65d fix(core): replace Iterable with Iterator for block iteration (#34934) 2026-01-30 12:08:22 -08:00
Mason Daugherty
017c8e05ec fix(core): yield_blobs returns Iterator (#34935)
Implementations using yield return generators, which are of type
`Iterator`.

This is technically a breaking change for implementers, however, known
existing implementations (in `langchain-community`) use `yield`, so they
already return `Iterator`s. For callers, it is not breaking.

Closes #25718
2026-01-30 12:08:13 -08:00
wixarv
c09cba2f87 docs: add CONTRIBUTING.md pointing to online guide (#34901) 2026-01-30 11:47:11 -08:00
wixarv
8a81852a83 refactor: replace print with logger.info in llm_summarization_checker (#34903) 2026-01-30 11:12:54 -08:00
zvibo
13e6327d3f docs: Fix typo in Runnable description of async variants (#34905) 2026-01-30 10:52:38 -08:00
Rohan Disa
4004883806 fix(xai): Live search deprecation (#34919) 2026-01-30 10:01:20 -08:00
zer0
6ff8436fb0 fix(core): raise outputparserexception for unknown tools (#34923) 2026-01-30 09:35:31 -08:00
Mason Daugherty
72571185a8 docs(core): nit (#34914) 2026-01-28 10:54:53 -08:00
Mason Daugherty
7e9c53ff8d feat(infra): related issues for bug report template (#34913) 2026-01-28 10:54:14 -08:00
Mason Daugherty
f8d5a5069f chore(core): nits (#34897) 2026-01-26 18:05:37 -08:00
cc
585b691c1d feat(core): add multimodal support to count_tokens_approximately (#34883) 2026-01-26 15:04:25 -08:00
dependabot[bot]
c4e645cf13 chore(deps): bump actions/create-github-app-token from 1 to 2 (#34886) 2026-01-26 14:38:21 -08:00
Mason Daugherty
3da89bd380 feat(langchain): add ToolCallRequest to middleware exports (#34894)
https://github.com/langchain-ai/docs/pull/2358
2026-01-26 11:54:14 -08:00
ccurme
c930062f69 chore(infra): re-enable tests on prior published packages on core release (#34881) 2026-01-25 20:36:40 -08:00
ccurme
aaba1b0bcb release(xai): 1.2.2 (#34880) langchain-xai==1.2.2 2026-01-25 20:20:44 -08:00
Sholto Armstrong
666bb6fe53 fix(xai): fix routing of chat completions vs. responses apis during streaming (#34868) 2026-01-25 19:58:11 -08:00
Bodhi Russell Silberling
f0ca2c4675 fix(core): fix typo 'use a a' -> 'use as a' in check_version.py (#34878) 2026-01-25 19:26:22 -08:00
Mason Daugherty
11df1bedc3 style(core): lint (#34862)
it looks scary but i promise it is not

improving documentation consistency across core. primarily update
docstrings and comments for better formatting, readability, and
accuracy, as well as add minor clarifications and formatting
improvements to user-facing documentation.
2026-01-23 23:07:48 -05:00
Mason Daugherty
51f13f7bff style(text-splitters): lint (#34865) 2026-01-23 23:07:36 -05:00
Mason Daugherty
17de2a3685 style(langchain): lint (#34863)
it looks scary but i promise it is not

improving documentation consistency across langchain. primarily update
docstrings and comments for better formatting, readability, and
accuracy, as well as add minor clarifications and formatting
improvements to user-facing documentation.
2026-01-23 23:00:44 -05:00
Mason Daugherty
72333ad644 fix(langchain): blocking unit test (#34866)
=
2026-01-23 22:58:03 -05:00
Mason Daugherty
703d170a4a style(model-profiles): lint (#34864) 2026-01-23 22:40:59 -05:00
Mason Daugherty
80e09feec1 docs: add Chat LangChain link and highlight Deep Agents (#34858) 2026-01-23 15:20:26 -05:00
Christophe Bornet
ca9d2c0bdd test(langchain): use blockbuster to detect blocking calls in the async event loop (#34777) 2026-01-23 14:52:56 -05:00
yy
eff21c75fc fix(langchain): fix typo 'safegaurd' -> 'safeguard' (#34789)
Fix typo in error message: 'safegaurd' -> 'safeguard'
2026-01-23 14:51:22 -05:00
Pádraic Slattery
2d3b94848c chore: Update outdated GitHub Actions versions (#34850)
- PR title: update(actions): update GitHub Action versions  
- PR description: This PR updates outdated GitHub Action versions.

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2026-01-23 14:04:11 -05:00
Shivangi Sharma
a725c91308 fix(docs): broken link in AGENTS.md and CLAUDE.md (#34852)
Update broken contributing links in AGENTS.md and CLAUDE.md

Description: 

Update internal references from .github/CONTRIBUTING.md to [Contributing
Guide] to fix navigation issues for local contributors.

Proposed Changes

AGENTS.md: Change [.github/CONTRIBUTING.md] link text to [Contributing
Guide] since the file path is not present in the local root.

CLAUDE.md: Change [.github/CONTRIBUTING.md] link text to [Contributing
Guide] for consistency.

Reasoning: 

Users following these docs locally often find the specific file path
.github/CONTRIBUTING.md confusing or "broken" in markdown previews that
don't resolve the .github hidden directory correctly. Using the
descriptive label "Contributing Guide" is more user-friendly and
standard across the repo.

Checklist:

[x] Run make format, make lint and make test (N/A for these doc-only
changes).

[x] PR title follows the format: TYPE(SCOPE): DESCRIPTION.

[x] I have read the [Contributing
Guide](https://www.google.com/search?q=https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md).
2026-01-23 14:00:08 -05:00
Bodhi Russell Silberling
2fdae7a38a fix(docs): remove extra asterisk from heading in AGENTS.md and CLAUDE.md (#34856)
(Replace this entire block of text)

Read the full contributing guidelines:
https://docs.langchain.com/oss/python/contributing/overview

Thank you for contributing to LangChain! Follow these steps to have your
pull request considered as ready for review.

1. PR title: Should follow the format: TYPE(SCOPE): DESCRIPTION

  - Examples:
    - fix(anthropic): resolve flag parsing error
    - feat(core): add multi-tenant support
    - test(openai): update API usage tests
- Allowed TYPE and SCOPE values:
https://github.com/langchain-ai/langchain/blob/master/.github/workflows/pr_lint.yml#L15-L33

2. PR description:

  - Write 1-2 sentences summarizing the change.
- If this PR addresses a specific issue, please include "Fixes
#ISSUE_NUMBER" in the description to automatically close the issue when
the PR is merged.
  - If there are any breaking changes, please clearly describe them.
- If this PR depends on another PR being merged first, please include
"Depends on #PR_NUMBER" in the description.

3. Run `make format`, `make lint` and `make test` from the root of the
package(s) you've modified.

  - We will not consider a PR unless these three are passing in CI.

Additional guidelines:

- We ask that if you use generative AI for your contribution, you
include a disclaimer.
- PRs should not touch more than one package unless absolutely
necessary.
- Do not update the `uv.lock` files or add dependencies to
`pyproject.toml` files (even optional ones) unless you have explicit
permission to do so by a maintainer.
2026-01-23 13:59:37 -05:00
Bodhi Russell Silberling
cb09f94e82 fix(text-splitters): fix typo 'seperator' -> 'separator' in test docs… (#34857)
…tring

(Replace this entire block of text)

Read the full contributing guidelines:
https://docs.langchain.com/oss/python/contributing/overview

Thank you for contributing to LangChain! Follow these steps to have your
pull request considered as ready for review.

1. PR title: Should follow the format: TYPE(SCOPE): DESCRIPTION

  - Examples:
    - fix(anthropic): resolve flag parsing error
    - feat(core): add multi-tenant support
    - test(openai): update API usage tests
- Allowed TYPE and SCOPE values:
https://github.com/langchain-ai/langchain/blob/master/.github/workflows/pr_lint.yml#L15-L33

2. PR description:

  - Write 1-2 sentences summarizing the change.
- If this PR addresses a specific issue, please include "Fixes
#ISSUE_NUMBER" in the description to automatically close the issue when
the PR is merged.
  - If there are any breaking changes, please clearly describe them.
- If this PR depends on another PR being merged first, please include
"Depends on #PR_NUMBER" in the description.

3. Run `make format`, `make lint` and `make test` from the root of the
package(s) you've modified.

  - We will not consider a PR unless these three are passing in CI.

Additional guidelines:

- We ask that if you use generative AI for your contribution, you
include a disclaimer.
- PRs should not touch more than one package unless absolutely
necessary.
- Do not update the `uv.lock` files or add dependencies to
`pyproject.toml` files (even optional ones) unless you have explicit
permission to do so by a maintainer.
2026-01-23 13:59:23 -05:00
Mason Daugherty
4e9a1eb283 chore: delete CLI (#34855)
preserved in
https://github.com/langchain-ai/langchain/tree/langchain-cli
2026-01-23 12:55:09 -05:00
Sydney Runkle
cc72a8c45a release: langchain 1.2.7 (#34854) langchain==1.2.7 2026-01-23 10:19:39 -05:00
Sydney Runkle
bc8620189c feat: dynamic tool registration via middleware (#34842)
dependent upon https://github.com/langchain-ai/langgraph/pull/6711

1. relax constraint in `factory.py` to allow for tools not
pre-registered in the `ModelRequest.tools` list
2. always add tool node if `wrap_tool_call` or `awrap_tool_call` is
implemented
3. add tests confirming you can register new tools at runtime in
`wrap_model_call` and execute them via `wrap_tool_call`

allows for the following pattern

```py
from langchain_core.messages import HumanMessage, ToolMessage
from langchain_core.tools import tool

from libs.langchain_v1.langchain.agents.factory import create_agent
from libs.langchain_v1.langchain.agents.middleware.types import (
    AgentMiddleware,
    ModelRequest,
    ToolCallRequest,
)


@tool
def get_weather(location: str) -> str:
    """Get the current weather for a location."""
    return f"The weather in {location} is sunny and 72°F."


@tool
def calculate_tip(bill_amount: float, tip_percentage: float = 20.0) -> str:
    """Calculate the tip amount for a bill."""
    tip = bill_amount * (tip_percentage / 100)
    return f"Tip: ${tip:.2f}, Total: ${bill_amount + tip:.2f}"

class DynamicToolMiddleware(AgentMiddleware):
    """Middleware that adds and handles a dynamic tool."""

    def wrap_model_call(self, request: ModelRequest, handler):
        updated = request.override(tools=[*request.tools, calculate_tip])
        return handler(updated)

    def wrap_tool_call(self, request: ToolCallRequest, handler):
        if request.tool_call["name"] == "calculate_tip":
            return handler(request.override(tool=calculate_tip))
        return handler(request)


agent = create_agent(model="openai:gpt-4o-mini", tools=[get_weather], middleware=[DynamicToolMiddleware()])
result = agent.invoke({
    "messages": [HumanMessage("What's the weather in NYC? Also calculate a 20% tip on a $85 bill")]
})
for msg in result["messages"]:
    msg.pretty_print()
```
2026-01-23 10:12:48 -05:00