Initial commit: hardened DeerFlow factory
Vendored deer-flow upstream (bytedance/deer-flow) plus prompt-injection hardening: - New deerflow.security package: content_delimiter, html_cleaner, sanitizer (8 layers — invisible chars, control chars, symbols, NFC, PUA, tag chars, horizontal whitespace collapse with newline/tab preservation, length cap) - New deerflow.community.searx package: web_search, web_fetch, image_search backed by a private SearX instance, every external string sanitized and wrapped in <<<EXTERNAL_UNTRUSTED_CONTENT>>> delimiters - All native community web providers (ddg_search, tavily, exa, firecrawl, jina_ai, infoquest, image_search) replaced with hard-fail stubs that raise NativeWebToolDisabledError at import time, so a misconfigured tool.use path fails loud rather than silently falling back to unsanitized output - Native client back-doors (jina_client.py, infoquest_client.py) stubbed too - Native-tool tests quarantined under tests/_disabled_native/ (collect_ignore_glob via local conftest.py) - Sanitizer Layer 7 fix: only collapse horizontal whitespace, preserve newlines and tabs so list/table structure survives - Hardened runtime config.yaml references only the searx-backed tools - Factory overlay (backend/) kept in sync with deer-flow tree as a reference / source See HARDENING.md for the full audit trail and verification steps.
This commit is contained in:
55
deer-flow/backend/tests/test_subagent_prompt_security.py
Normal file
55
deer-flow/backend/tests/test_subagent_prompt_security.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""Tests for subagent availability and prompt exposure under local bash hardening."""
|
||||
|
||||
from deerflow.agents.lead_agent import prompt as prompt_module
|
||||
from deerflow.subagents import registry as registry_module
|
||||
|
||||
|
||||
def test_get_available_subagent_names_hides_bash_when_host_bash_disabled(monkeypatch) -> None:
|
||||
monkeypatch.setattr(registry_module, "is_host_bash_allowed", lambda: False)
|
||||
|
||||
names = registry_module.get_available_subagent_names()
|
||||
|
||||
assert names == ["general-purpose"]
|
||||
|
||||
|
||||
def test_get_available_subagent_names_keeps_bash_when_allowed(monkeypatch) -> None:
|
||||
monkeypatch.setattr(registry_module, "is_host_bash_allowed", lambda: True)
|
||||
|
||||
names = registry_module.get_available_subagent_names()
|
||||
|
||||
assert names == ["general-purpose", "bash"]
|
||||
|
||||
|
||||
def test_build_subagent_section_hides_bash_examples_when_unavailable(monkeypatch) -> None:
|
||||
monkeypatch.setattr(prompt_module, "get_available_subagent_names", lambda: ["general-purpose"])
|
||||
|
||||
section = prompt_module._build_subagent_section(3)
|
||||
|
||||
assert "Not available in the current sandbox configuration" in section
|
||||
assert 'bash("npm test")' not in section
|
||||
assert 'read_file("/mnt/user-data/workspace/README.md")' in section
|
||||
assert "available tools (ls, read_file, web_search, etc.)" in section
|
||||
|
||||
|
||||
def test_build_subagent_section_includes_bash_when_available(monkeypatch) -> None:
|
||||
monkeypatch.setattr(prompt_module, "get_available_subagent_names", lambda: ["general-purpose", "bash"])
|
||||
|
||||
section = prompt_module._build_subagent_section(3)
|
||||
|
||||
assert "For command execution (git, build, test, deploy operations)" in section
|
||||
assert 'bash("npm test")' in section
|
||||
assert "available tools (bash, ls, read_file, web_search, etc.)" in section
|
||||
|
||||
|
||||
def test_bash_subagent_prompt_mentions_workspace_relative_paths() -> None:
|
||||
from deerflow.subagents.builtins.bash_agent import BASH_AGENT_CONFIG
|
||||
|
||||
assert "Treat `/mnt/user-data/workspace` as the default working directory for file IO" in BASH_AGENT_CONFIG.system_prompt
|
||||
assert "`hello.txt`, `../uploads/input.csv`, and `../outputs/result.md`" in BASH_AGENT_CONFIG.system_prompt
|
||||
|
||||
|
||||
def test_general_purpose_subagent_prompt_mentions_workspace_relative_paths() -> None:
|
||||
from deerflow.subagents.builtins.general_purpose import GENERAL_PURPOSE_CONFIG
|
||||
|
||||
assert "Treat `/mnt/user-data/workspace` as the default working directory for coding and file IO" in GENERAL_PURPOSE_CONFIG.system_prompt
|
||||
assert "`hello.txt`, `../uploads/input.csv`, and `../outputs/result.md`" in GENERAL_PURPOSE_CONFIG.system_prompt
|
||||
Reference in New Issue
Block a user