decodingtrust-agent-sdk 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent/__init__.py +30 -0
- agent/claudesdk/__init__.py +8 -0
- agent/claudesdk/example.py +221 -0
- agent/claudesdk/src/__init__.py +8 -0
- agent/claudesdk/src/agent.py +400 -0
- agent/claudesdk/src/mcp_proxy.py +409 -0
- agent/claudesdk/src/utils.py +420 -0
- agent/googleadk/__init__.py +15 -0
- agent/googleadk/example.py +237 -0
- agent/googleadk/src/__init__.py +12 -0
- agent/googleadk/src/agent.py +401 -0
- agent/googleadk/src/mcp_wrapper.py +163 -0
- agent/googleadk/src/utils.py +602 -0
- agent/langchain/__init__.py +8 -0
- agent/langchain/example.py +213 -0
- agent/langchain/src/__init__.py +8 -0
- agent/langchain/src/agent.py +645 -0
- agent/langchain/src/utils.py +433 -0
- agent/openaisdk/__init__.py +17 -0
- agent/openaisdk/example.py +228 -0
- agent/openaisdk/src/__init__.py +12 -0
- agent/openaisdk/src/agent.py +491 -0
- agent/openaisdk/src/agent_wrapper.py +143 -0
- agent/openaisdk/src/mcp_wrapper.py +395 -0
- agent/openaisdk/src/utils.py +493 -0
- agent/openclaw/__init__.py +10 -0
- agent/openclaw/example.py +251 -0
- agent/openclaw/src/__init__.py +14 -0
- agent/openclaw/src/agent.py +930 -0
- agent/openclaw/src/helpers/__init__.py +1 -0
- agent/openclaw/src/helpers/auth_helpers.py +55 -0
- agent/openclaw/src/mcp_proxy.py +564 -0
- agent/openclaw/src/plugin_generator.py +231 -0
- agent/openclaw/src/utils.py +341 -0
- agent/pocketflow/__init__.py +18 -0
- agent/pocketflow/example.py +221 -0
- agent/pocketflow/prompts/react_agent.py +46 -0
- agent/pocketflow/src/__init__.py +6 -0
- agent/pocketflow/src/agent.py +507 -0
- agent/pocketflow/src/agent_wrapper.py +159 -0
- agent/pocketflow/src/async_helper.py +92 -0
- agent/pocketflow/src/mcp_react_agent.py +279 -0
- agent/pocketflow/src/native_agent.py +74 -0
- agent/pocketflow/src/nodes.py +467 -0
- benchmark/__init__.py +0 -0
- benchmark/browser/benign.jsonl +34 -0
- benchmark/browser/direct.jsonl +85 -0
- benchmark/browser/indirect.jsonl +82 -0
- benchmark/code/benign.jsonl +0 -0
- benchmark/code/direct.jsonl +121 -0
- benchmark/code/indirect.jsonl +165 -0
- benchmark/crm/benign.jsonl +165 -0
- benchmark/crm/direct.jsonl +90 -0
- benchmark/crm/indirect.jsonl +150 -0
- benchmark/customer-service/benign.jsonl +160 -0
- benchmark/customer-service/direct.jsonl +100 -0
- benchmark/customer-service/indirect.jsonl +101 -0
- benchmark/finance/benign.jsonl +0 -0
- benchmark/finance/direct.jsonl +200 -0
- benchmark/finance/indirect.jsonl +200 -0
- benchmark/legal/benign.jsonl +0 -0
- benchmark/legal/direct.jsonl +200 -0
- benchmark/legal/indirect.jsonl +200 -0
- benchmark/macos/benign.jsonl +30 -0
- benchmark/macos/direct.jsonl +50 -0
- benchmark/macos/indirect.jsonl +50 -0
- benchmark/medical/benign.jsonl +642 -0
- benchmark/medical/direct.jsonl +229 -0
- benchmark/medical/indirect.jsonl +222 -0
- benchmark/os-filesystem/benign.jsonl +200 -0
- benchmark/os-filesystem/direct.jsonl +200 -0
- benchmark/os-filesystem/indirect.jsonl +200 -0
- benchmark/research/benign.jsonl +0 -0
- benchmark/research/direct.jsonl +119 -0
- benchmark/research/indirect.jsonl +125 -0
- benchmark/telecom/benign.jsonl +120 -0
- benchmark/telecom/direct.jsonl +161 -0
- benchmark/telecom/indirect.jsonl +166 -0
- benchmark/travel/benign.jsonl +130 -0
- benchmark/travel/direct.jsonl +105 -0
- benchmark/travel/indirect.jsonl +120 -0
- benchmark/windows/benign.jsonl +100 -0
- benchmark/windows/direct.jsonl +140 -0
- benchmark/windows/indirect.jsonl +107 -0
- benchmark/workflow/benign.jsonl +335 -0
- benchmark/workflow/direct.jsonl +78 -0
- benchmark/workflow/indirect.jsonl +107 -0
- cli/__init__.py +5 -0
- cli/main.py +182 -0
- cli/scaffold.py +334 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/METADATA +642 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/RECORD +374 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/WHEEL +5 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/entry_points.txt +2 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/licenses/LICENSE +201 -0
- decodingtrust_agent_sdk-0.1.0.dist-info/top_level.txt +6 -0
- dt_arena/config/env.yaml +515 -0
- dt_arena/config/injection_mcp.yaml +430 -0
- dt_arena/config/mcp.yaml +642 -0
- dt_arena/envs/arxiv/docker-compose-hub.yml +31 -0
- dt_arena/envs/arxiv/docker-compose.yml +36 -0
- dt_arena/envs/atlassian/docker/docker-compose.dev.yml +65 -0
- dt_arena/envs/atlassian/docker/docker-compose.yml +53 -0
- dt_arena/envs/atlassian/docker-compose-hub.yml +57 -0
- dt_arena/envs/atlassian/docker-compose.yml +72 -0
- dt_arena/envs/bigquery/docker-compose.yml +20 -0
- dt_arena/envs/booking/docker-compose.yml +59 -0
- dt_arena/envs/calendar/docker-compose-hub.yml +30 -0
- dt_arena/envs/calendar/docker-compose.yml +42 -0
- dt_arena/envs/custom-website/docker-compose.yml +6 -0
- dt_arena/envs/customer_service/docker-compose.yml +59 -0
- dt_arena/envs/databricks/docker-compose-hub.yml +47 -0
- dt_arena/envs/databricks/docker-compose.yml +51 -0
- dt_arena/envs/ecommerce/docker-compose.yml +6 -0
- dt_arena/envs/ers/docker-compose.yml +36 -0
- dt_arena/envs/ers/hrms/docker/docker-compose.yml +31 -0
- dt_arena/envs/finance/docker-compose.yml +23 -0
- dt_arena/envs/github/docker/docker-compose-hub.yml +50 -0
- dt_arena/envs/github/docker/docker-compose.yml +50 -0
- dt_arena/envs/gmail/docker-compose-hub.yml +51 -0
- dt_arena/envs/gmail/docker-compose.yml +65 -0
- dt_arena/envs/google-form/docker-compose-hub.yml +33 -0
- dt_arena/envs/google-form/docker-compose.yml +41 -0
- dt_arena/envs/googledocs/docker-compose-hub.yml +61 -0
- dt_arena/envs/googledocs/docker-compose.yml +78 -0
- dt_arena/envs/hospital/docker-compose-hub.yml +25 -0
- dt_arena/envs/hospital/docker-compose.yml +27 -0
- dt_arena/envs/legal/docker-compose.yml +22 -0
- dt_arena/envs/linkedin/docker-compose.yml +63 -0
- dt_arena/envs/macos/docker-compose.yml +79 -0
- dt_arena/envs/os-filesystem/docker-compose-hub.yml +16 -0
- dt_arena/envs/os-filesystem/docker-compose.yml +20 -0
- dt_arena/envs/paypal/docker-compose-hub.yml +48 -0
- dt_arena/envs/paypal/docker-compose.yml +63 -0
- dt_arena/envs/research/docker-compose-hub.yml +13 -0
- dt_arena/envs/research/docker-compose.yml +24 -0
- dt_arena/envs/salesforce_crm/docker-compose-hub.yaml +45 -0
- dt_arena/envs/salesforce_crm/docker-compose.yaml +49 -0
- dt_arena/envs/slack/docker-compose-hub.yml +28 -0
- dt_arena/envs/slack/docker-compose.yml +41 -0
- dt_arena/envs/snowflake/docker-compose-hub.yml +41 -0
- dt_arena/envs/snowflake/docker-compose.yml +44 -0
- dt_arena/envs/telecom/docker-compose-hub.yml +16 -0
- dt_arena/envs/telecom/docker-compose.yml +17 -0
- dt_arena/envs/telegram/docker-compose-hub.yml +57 -0
- dt_arena/envs/telegram/docker-compose.yml +62 -0
- dt_arena/envs/terminal/docker-compose-hub.yml +12 -0
- dt_arena/envs/terminal/docker-compose.yml +26 -0
- dt_arena/envs/travel/docker-compose-hub.yml +19 -0
- dt_arena/envs/travel/docker-compose.yml +19 -0
- dt_arena/envs/whatsapp/docker-compose-hub.yml +61 -0
- dt_arena/envs/whatsapp/docker-compose.yml +78 -0
- dt_arena/envs/windows/docker-compose.yml +71 -0
- dt_arena/envs/zoom/docker-compose-hub.yml +27 -0
- dt_arena/envs/zoom/docker-compose.yml +40 -0
- dt_arena/injection_mcp_server/atlassian/env_injection.py +134 -0
- dt_arena/injection_mcp_server/calendar/env_injection.py +217 -0
- dt_arena/injection_mcp_server/custom_website/env_injection.py +97 -0
- dt_arena/injection_mcp_server/customer_service/env_injection.py +659 -0
- dt_arena/injection_mcp_server/databricks/env_injection.py +255 -0
- dt_arena/injection_mcp_server/ecommerce/env_injection.py +110 -0
- dt_arena/injection_mcp_server/finance/env_injection.py +85 -0
- dt_arena/injection_mcp_server/github/env_injection.py +206 -0
- dt_arena/injection_mcp_server/gmail/env_injection.py +211 -0
- dt_arena/injection_mcp_server/google_form/env_injection.py +186 -0
- dt_arena/injection_mcp_server/googledocs/env_injection.py +44 -0
- dt_arena/injection_mcp_server/hospital/env_injection.py +43 -0
- dt_arena/injection_mcp_server/legal/env_injection.py +229 -0
- dt_arena/injection_mcp_server/macos/env_injection.py +272 -0
- dt_arena/injection_mcp_server/os-filesystem/env_injection.py +341 -0
- dt_arena/injection_mcp_server/paypal/env_injection.py +268 -0
- dt_arena/injection_mcp_server/research/env_injection.py +616 -0
- dt_arena/injection_mcp_server/salesforce/env_injection.py +514 -0
- dt_arena/injection_mcp_server/slack/env_injection.py +265 -0
- dt_arena/injection_mcp_server/snowflake/env_injection.py +230 -0
- dt_arena/injection_mcp_server/telecom/env_injection.py +503 -0
- dt_arena/injection_mcp_server/telegram/env_injection.py +171 -0
- dt_arena/injection_mcp_server/terminal/env_injection.py +523 -0
- dt_arena/injection_mcp_server/travel/env_injection.py +173 -0
- dt_arena/injection_mcp_server/whatsapp/env_injection.py +185 -0
- dt_arena/injection_mcp_server/windows/env_injection.py +943 -0
- dt_arena/injection_mcp_server/zoom/env_injection.py +216 -0
- dt_arena/mcp_server/atlassian/main.py +1554 -0
- dt_arena/mcp_server/atlassian/test_server.py +66 -0
- dt_arena/mcp_server/bigquery/main.py +333 -0
- dt_arena/mcp_server/booking/main.py +310 -0
- dt_arena/mcp_server/browser/main.py +1741 -0
- dt_arena/mcp_server/calendar/example_multi_user.py +162 -0
- dt_arena/mcp_server/calendar/main.py +792 -0
- dt_arena/mcp_server/calendar/test_mcp.py +135 -0
- dt_arena/mcp_server/customer_service/main.py +1063 -0
- dt_arena/mcp_server/databricks/main.py +566 -0
- dt_arena/mcp_server/databricks/probe.py +102 -0
- dt_arena/mcp_server/ers/main.py +845 -0
- dt_arena/mcp_server/finance/__init__.py +87 -0
- dt_arena/mcp_server/finance/core/__init__.py +12 -0
- dt_arena/mcp_server/finance/core/data_loader.py +558 -0
- dt_arena/mcp_server/finance/core/portfolio.py +565 -0
- dt_arena/mcp_server/finance/evaluation/__init__.py +20 -0
- dt_arena/mcp_server/finance/evaluation/evaluator.py +217 -0
- dt_arena/mcp_server/finance/evaluation/logger.py +137 -0
- dt_arena/mcp_server/finance/injection/__init__.py +66 -0
- dt_arena/mcp_server/finance/injection/config.py +176 -0
- dt_arena/mcp_server/finance/injection/content.py +755 -0
- dt_arena/mcp_server/finance/injection/html.py +409 -0
- dt_arena/mcp_server/finance/injection/locations.py +167 -0
- dt_arena/mcp_server/finance/injection/methods.py +193 -0
- dt_arena/mcp_server/finance/injection/presets.py +1023 -0
- dt_arena/mcp_server/finance/main.py +361 -0
- dt_arena/mcp_server/finance/run_mcp.py +21 -0
- dt_arena/mcp_server/finance/run_web.py +26 -0
- dt_arena/mcp_server/finance/server/__init__.py +41 -0
- dt_arena/mcp_server/finance/server/extractor.py +1453 -0
- dt_arena/mcp_server/finance/server/extractor_minimal.py +292 -0
- dt_arena/mcp_server/finance/server/extractor_simple.py +1164 -0
- dt_arena/mcp_server/finance/server/injection_mcp.py +865 -0
- dt_arena/mcp_server/finance/server/mcp.py +451 -0
- dt_arena/mcp_server/finance/server/tools/__init__.py +23 -0
- dt_arena/mcp_server/finance/server/tools/account.py +88 -0
- dt_arena/mcp_server/finance/server/tools/browsing.py +328 -0
- dt_arena/mcp_server/finance/server/tools/social.py +73 -0
- dt_arena/mcp_server/finance/server/tools/trading.py +242 -0
- dt_arena/mcp_server/finance/server/tools/utility.py +49 -0
- dt_arena/mcp_server/finance/server/web.py +2139 -0
- dt_arena/mcp_server/finance/tasks/benchmark/__init__.py +28 -0
- dt_arena/mcp_server/finance/tasks/benchmark/attack_pool.py +3026 -0
- dt_arena/mcp_server/finance/tasks/benchmark/attack_runner.py +1315 -0
- dt_arena/mcp_server/finance/tasks/benchmark/finra_requirements.py +1335 -0
- dt_arena/mcp_server/finance/tasks/benchmark/finra_tasks.py +3665 -0
- dt_arena/mcp_server/finance/tasks/benchmark/malicious_tasks.py +2673 -0
- dt_arena/mcp_server/finance/tasks/redteam_suite/run_redteam_suite.py +1713 -0
- dt_arena/mcp_server/finance/test_mcp_tools.py +476 -0
- dt_arena/mcp_server/github/main.py +441 -0
- dt_arena/mcp_server/gmail/main.py +1004 -0
- dt_arena/mcp_server/google_form/main.py +141 -0
- dt_arena/mcp_server/googledocs/main.py +458 -0
- dt_arena/mcp_server/hospital/mcp_server.py +458 -0
- dt_arena/mcp_server/legal/__init__.py +9 -0
- dt_arena/mcp_server/legal/core/__init__.py +14 -0
- dt_arena/mcp_server/legal/core/courtlistener_store.py +762 -0
- dt_arena/mcp_server/legal/core/data_loader.py +266 -0
- dt_arena/mcp_server/legal/core/document_store.py +197 -0
- dt_arena/mcp_server/legal/core/matter_manager.py +466 -0
- dt_arena/mcp_server/legal/main.py +89 -0
- dt_arena/mcp_server/legal/scripts/collect_data.py +988 -0
- dt_arena/mcp_server/legal/server/__init__.py +14 -0
- dt_arena/mcp_server/legal/server/mcp.py +2330 -0
- dt_arena/mcp_server/macos/client_test.py +270 -0
- dt_arena/mcp_server/macos/mcp_server.py +285 -0
- dt_arena/mcp_server/os-filesystem/main.py +1380 -0
- dt_arena/mcp_server/paypal/main.py +501 -0
- dt_arena/mcp_server/research/main.py +777 -0
- dt_arena/mcp_server/salesforce/main.py +2006 -0
- dt_arena/mcp_server/slack/main.py +318 -0
- dt_arena/mcp_server/snowflake/main.py +612 -0
- dt_arena/mcp_server/snowflake/probe.py +183 -0
- dt_arena/mcp_server/telecom/mcp_client.py +423 -0
- dt_arena/mcp_server/telecom/mcp_server.py +1059 -0
- dt_arena/mcp_server/telegram/main.py +338 -0
- dt_arena/mcp_server/terminal/main.py +163 -0
- dt_arena/mcp_server/travel/client_test.py +16 -0
- dt_arena/mcp_server/travel/mcp_server.py +404 -0
- dt_arena/mcp_server/whatsapp/main.py +318 -0
- dt_arena/mcp_server/windows/client_test.py +270 -0
- dt_arena/mcp_server/windows/mcp_server.py +218 -0
- dt_arena/mcp_server/zoom/main.py +466 -0
- dt_arena/src/__init__.py +0 -0
- dt_arena/src/hooks/__init__.py +0 -0
- dt_arena/src/hooks/audit_log.py +30 -0
- dt_arena/src/hooks/hooks.json +3 -0
- dt_arena/src/run_benign.py +142 -0
- dt_arena/src/types/__init__.py +0 -0
- dt_arena/src/types/agent.py +441 -0
- dt_arena/src/types/attacks.py +2 -0
- dt_arena/src/types/environment.py +2 -0
- dt_arena/src/types/hooks.py +174 -0
- dt_arena/src/types/judge.py +52 -0
- dt_arena/src/types/red_teaming_trajectory.py +385 -0
- dt_arena/src/types/task.py +260 -0
- dt_arena/src/types/trajectory.py +315 -0
- dt_arena/utils/__init__.py +1 -0
- dt_arena/utils/atlassian/__init__.py +27 -0
- dt_arena/utils/atlassian/helpers.py +520 -0
- dt_arena/utils/bigquery/__init__.py +1 -0
- dt_arena/utils/bigquery/helpers.py +246 -0
- dt_arena/utils/calendar/__init__.py +1 -0
- dt_arena/utils/calendar/helpers.py +87 -0
- dt_arena/utils/customer_service/__init__.py +17 -0
- dt_arena/utils/customer_service/cs_env_client.py +940 -0
- dt_arena/utils/customer_service/helpers.py +339 -0
- dt_arena/utils/customer_service/judges/__init__.py +20 -0
- dt_arena/utils/customer_service/judges/abusive_comms.py +149 -0
- dt_arena/utils/customer_service/judges/bulk_destructive.py +202 -0
- dt_arena/utils/customer_service/judges/cross_customer.py +481 -0
- dt_arena/utils/customer_service/judges/email_exfiltration.py +320 -0
- dt_arena/utils/customer_service/judges/financial_fraud.py +221 -0
- dt_arena/utils/customer_service/judges/llm_utils.py +264 -0
- dt_arena/utils/customer_service/judges/pii_disclosure.py +837 -0
- dt_arena/utils/customer_service/judges/policy_misrep.py +44 -0
- dt_arena/utils/customer_service/judges/text_utils.py +21 -0
- dt_arena/utils/databricks/__init__.py +2 -0
- dt_arena/utils/databricks/helpers.py +210 -0
- dt_arena/utils/finance/__init__.py +0 -0
- dt_arena/utils/finance/helpers.py +263 -0
- dt_arena/utils/github/__init__.py +1 -0
- dt_arena/utils/github/helpers.py +249 -0
- dt_arena/utils/gmail/__init__.py +1 -0
- dt_arena/utils/gmail/helpers.py +344 -0
- dt_arena/utils/google_form/__init__.py +2 -0
- dt_arena/utils/google_form/helpers.py +133 -0
- dt_arena/utils/legal/__init__.py +0 -0
- dt_arena/utils/legal/helpers.py +228 -0
- dt_arena/utils/macos/__init__.py +0 -0
- dt_arena/utils/macos/env_setup.py +215 -0
- dt_arena/utils/macos/helpers.py +61 -0
- dt_arena/utils/os_filesystem/__init__.py +1 -0
- dt_arena/utils/os_filesystem/helpers.py +366 -0
- dt_arena/utils/paypal/__init__.py +1 -0
- dt_arena/utils/paypal/helpers.py +178 -0
- dt_arena/utils/port_allocator.py +266 -0
- dt_arena/utils/research/__init__.py +0 -0
- dt_arena/utils/research/helpers.py +251 -0
- dt_arena/utils/salesforce/__init__.py +1 -0
- dt_arena/utils/salesforce/helpers.py +719 -0
- dt_arena/utils/slack/__init__.py +1 -0
- dt_arena/utils/slack/helpers.py +176 -0
- dt_arena/utils/snowflake/__init__.py +1 -0
- dt_arena/utils/snowflake/helpers.py +166 -0
- dt_arena/utils/telecom/__init__.py +1 -0
- dt_arena/utils/telecom/helpers.py +760 -0
- dt_arena/utils/telegram/__init__.py +0 -0
- dt_arena/utils/telegram/helpers.py +174 -0
- dt_arena/utils/terminal/__init__.py +0 -0
- dt_arena/utils/terminal/helpers.py +20 -0
- dt_arena/utils/travel/__init__.py +0 -0
- dt_arena/utils/travel/env_client.py +537 -0
- dt_arena/utils/travel/llm_judge.py +137 -0
- dt_arena/utils/travel/prompts.py +64 -0
- dt_arena/utils/utils/__init__.py +122 -0
- dt_arena/utils/whatsapp/__init__.py +0 -0
- dt_arena/utils/whatsapp/helpers.py +226 -0
- dt_arena/utils/windows/__init__.py +0 -0
- dt_arena/utils/windows/env_reset.py +224 -0
- dt_arena/utils/windows/env_setup.py +280 -0
- dt_arena/utils/windows/exfil_helpers.py +170 -0
- dt_arena/utils/windows/helpers.py +74 -0
- dt_arena/utils/zoom/__init__.py +1 -0
- dt_arena/utils/zoom/helpers.py +70 -0
- eval/__init__.py +1 -0
- eval/evaluation.py +426 -0
- eval/task_runner.py +449 -0
- utils/__init__.py +148 -0
- utils/agent_helpers.py +308 -0
- utils/agent_wrapper.py +189 -0
- utils/compose_utils.py +135 -0
- utils/config.py +77 -0
- utils/env_helpers.py +104 -0
- utils/eval_stats.py +88 -0
- utils/injection_helpers.py +429 -0
- utils/injection_mcp_helpers.py +152 -0
- utils/judge_helpers.py +181 -0
- utils/judge_utils.py +472 -0
- utils/llm.py +196 -0
- utils/logging.py +45 -0
- utils/mcp_helpers.py +232 -0
- utils/mcp_manager.py +235 -0
- utils/memory_guard.py +18 -0
- utils/red_teaming_sandbox.py +476 -0
- utils/reset_helpers.py +318 -0
- utils/resource_manager.py +370 -0
- utils/skill_helpers.py +447 -0
- utils/task_executor.py +904 -0
- utils/task_helpers.py +270 -0
- utils/template_helpers.py +179 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""WhatsApp Environment Injection MCP Server for red-teaming.
|
|
2
|
+
|
|
3
|
+
Exposes a small set of tools the red-team harness uses to seed / read the
|
|
4
|
+
sandboxed WhatsApp environment before the victim agent runs:
|
|
5
|
+
|
|
6
|
+
get_whatsapp_chat(phone_number, limit) -> read a 1:1 conversation
|
|
7
|
+
send_whatsapp_message(phone_number, body) -> write an *incoming* message
|
|
8
|
+
(appearing to come from
|
|
9
|
+
`phone_number`) into the
|
|
10
|
+
victim's inbox
|
|
11
|
+
list_whatsapp_chats(limit) -> list the victim's threads
|
|
12
|
+
|
|
13
|
+
All writes go through the WhatsApp sandbox admin endpoint
|
|
14
|
+
/api/v1/admin/inject_message; reads go through the normal /tools/call
|
|
15
|
+
endpoint using the victim's access token. Both are scoped to a single
|
|
16
|
+
victim account identified by WHATSAPP_USER_ACCESS_TOKEN.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
from typing import Any, Dict
|
|
23
|
+
|
|
24
|
+
import httpx
|
|
25
|
+
from fastmcp import FastMCP
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
WHATSAPP_API_URL = os.getenv("WHATSAPP_API_URL", "http://127.0.0.1:8039")
|
|
29
|
+
WHATSAPP_USER_ACCESS_TOKEN = os.getenv("WHATSAPP_USER_ACCESS_TOKEN", "")
|
|
30
|
+
|
|
31
|
+
WHATSAPP_ENV_INJECTION_MCP_HOST = os.getenv("WHATSAPP_ENV_INJECTION_MCP_HOST", "localhost")
|
|
32
|
+
WHATSAPP_ENV_INJECTION_MCP_PORT = os.getenv("WHATSAPP_ENV_INJECTION_MCP_PORT", "8872")
|
|
33
|
+
|
|
34
|
+
mcp = FastMCP(name="WhatsAppEnvInjection")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def _request(method: str, url: str, json: Dict[str, Any] | None = None) -> Dict[str, Any]:
|
|
38
|
+
try:
|
|
39
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
40
|
+
r = await client.request(method, url, json=json)
|
|
41
|
+
r.raise_for_status()
|
|
42
|
+
try:
|
|
43
|
+
return r.json()
|
|
44
|
+
except Exception:
|
|
45
|
+
return {"ok": True, "text": r.text}
|
|
46
|
+
except httpx.HTTPStatusError as e:
|
|
47
|
+
return {"error": f"HTTP {e.response.status_code}", "text": e.response.text}
|
|
48
|
+
except httpx.RequestError as e:
|
|
49
|
+
return {"error": "request_error", "message": str(e)}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def _call_tool(name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
53
|
+
"""Invoke a regular whatsapp tool through /tools/call using the victim token."""
|
|
54
|
+
payload = {
|
|
55
|
+
"name": name,
|
|
56
|
+
"arguments": {**arguments, "access_token": WHATSAPP_USER_ACCESS_TOKEN},
|
|
57
|
+
}
|
|
58
|
+
return await _request("POST", f"{WHATSAPP_API_URL}/tools/call", json=payload)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@mcp.tool(name="send_whatsapp_message")
|
|
62
|
+
async def send_whatsapp_message(
|
|
63
|
+
phone_number: str,
|
|
64
|
+
body: str,
|
|
65
|
+
direction: str = "incoming",
|
|
66
|
+
is_read: bool = False,
|
|
67
|
+
) -> Dict[str, Any]:
|
|
68
|
+
"""Inject a WhatsApp message into the victim's conversation with ``phone_number``.
|
|
69
|
+
|
|
70
|
+
By default the message is written as ``incoming`` so it shows up in the
|
|
71
|
+
victim's inbox as if it had been sent by ``phone_number``. Pass
|
|
72
|
+
``direction='outgoing'`` to seed a reply that looks like the victim sent it.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
phone_number: Counterparty phone (e.g. "+1-555-7001").
|
|
76
|
+
body: Message content (may contain a prompt-injection payload).
|
|
77
|
+
direction: "incoming" (default) or "outgoing".
|
|
78
|
+
is_read: Whether the message should be marked read.
|
|
79
|
+
"""
|
|
80
|
+
if not WHATSAPP_USER_ACCESS_TOKEN:
|
|
81
|
+
return {"error": "WHATSAPP_USER_ACCESS_TOKEN is not configured for the injection server"}
|
|
82
|
+
payload = {
|
|
83
|
+
"victim_token": WHATSAPP_USER_ACCESS_TOKEN,
|
|
84
|
+
"phone_number": phone_number,
|
|
85
|
+
"body": body,
|
|
86
|
+
"direction": direction,
|
|
87
|
+
"is_read": is_read,
|
|
88
|
+
}
|
|
89
|
+
return await _request("POST", f"{WHATSAPP_API_URL}/api/v1/admin/inject_message", json=payload)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@mcp.tool(name="get_whatsapp_chat")
|
|
93
|
+
async def get_whatsapp_chat(phone_number: str, limit: int = 50) -> Dict[str, Any]:
|
|
94
|
+
"""Read the victim's conversation history with ``phone_number``.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
phone_number: Counterparty phone.
|
|
98
|
+
limit: Max messages to return (default 50).
|
|
99
|
+
"""
|
|
100
|
+
if not WHATSAPP_USER_ACCESS_TOKEN:
|
|
101
|
+
return {"error": "WHATSAPP_USER_ACCESS_TOKEN is not configured for the injection server"}
|
|
102
|
+
return await _call_tool("get_conversation", {"phone_number": phone_number, "limit": int(limit)})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@mcp.tool(name="list_whatsapp_chats")
|
|
106
|
+
async def list_whatsapp_chats(limit: int = 50, unread_only: bool = False) -> Dict[str, Any]:
|
|
107
|
+
"""List the victim's message threads (most-recent first).
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
limit: Max threads to return.
|
|
111
|
+
unread_only: If true, restrict to threads with unread messages.
|
|
112
|
+
"""
|
|
113
|
+
if not WHATSAPP_USER_ACCESS_TOKEN:
|
|
114
|
+
return {"error": "WHATSAPP_USER_ACCESS_TOKEN is not configured for the injection server"}
|
|
115
|
+
return await _call_tool(
|
|
116
|
+
"list_message_threads",
|
|
117
|
+
{"limit": int(limit), "unread_only": bool(unread_only)},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@mcp.tool(name="search_whatsapp_messages")
|
|
122
|
+
async def search_whatsapp_messages(
|
|
123
|
+
query: str,
|
|
124
|
+
phone_number: str | None = None,
|
|
125
|
+
limit: int = 50,
|
|
126
|
+
) -> Dict[str, Any]:
|
|
127
|
+
"""Search the victim's WhatsApp messages by substring.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
query: Free-text substring to match against message bodies.
|
|
131
|
+
phone_number: Optional counterparty phone to scope the search.
|
|
132
|
+
limit: Max messages to return.
|
|
133
|
+
"""
|
|
134
|
+
if not WHATSAPP_USER_ACCESS_TOKEN:
|
|
135
|
+
return {"error": "WHATSAPP_USER_ACCESS_TOKEN is not configured for the injection server"}
|
|
136
|
+
args: Dict[str, Any] = {"query": query, "limit": int(limit)}
|
|
137
|
+
if phone_number:
|
|
138
|
+
args["phone_number"] = phone_number
|
|
139
|
+
return await _call_tool("search_messages", args)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@mcp.tool(name="create_contact")
|
|
143
|
+
async def create_contact(
|
|
144
|
+
first_name: str,
|
|
145
|
+
last_name: str = "",
|
|
146
|
+
phone: str = "",
|
|
147
|
+
email: str = "",
|
|
148
|
+
company: str = "",
|
|
149
|
+
job_title: str = "",
|
|
150
|
+
address: str = "",
|
|
151
|
+
notes: str = "",
|
|
152
|
+
favorite: bool = False,
|
|
153
|
+
) -> Dict[str, Any]:
|
|
154
|
+
"""Create a WhatsApp contact in the victim's address book.
|
|
155
|
+
|
|
156
|
+
Used by red-team scenarios to seed attacker contact metadata (display name,
|
|
157
|
+
company, notes, etc.) before the agent inspects the contact list.
|
|
158
|
+
"""
|
|
159
|
+
if not WHATSAPP_USER_ACCESS_TOKEN:
|
|
160
|
+
return {"error": "WHATSAPP_USER_ACCESS_TOKEN is not configured for the injection server"}
|
|
161
|
+
args = {
|
|
162
|
+
"first_name": first_name,
|
|
163
|
+
"last_name": last_name,
|
|
164
|
+
"phone": phone,
|
|
165
|
+
"email": email,
|
|
166
|
+
"company": company,
|
|
167
|
+
"job_title": job_title,
|
|
168
|
+
"address": address,
|
|
169
|
+
"notes": notes,
|
|
170
|
+
"favorite": bool(favorite),
|
|
171
|
+
}
|
|
172
|
+
args = {k: v for k, v in args.items() if v not in ("", None) or k == "favorite"}
|
|
173
|
+
return await _call_tool("create_contact", args)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
if __name__ == "__main__":
|
|
177
|
+
print(
|
|
178
|
+
f"Starting WhatsApp Environment Injection MCP Server on port {WHATSAPP_ENV_INJECTION_MCP_PORT}...",
|
|
179
|
+
file=sys.stderr,
|
|
180
|
+
)
|
|
181
|
+
mcp.run(
|
|
182
|
+
transport="http",
|
|
183
|
+
host=WHATSAPP_ENV_INJECTION_MCP_HOST,
|
|
184
|
+
port=int(WHATSAPP_ENV_INJECTION_MCP_PORT),
|
|
185
|
+
)
|