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.
Files changed (374) hide show
  1. agent/__init__.py +30 -0
  2. agent/claudesdk/__init__.py +8 -0
  3. agent/claudesdk/example.py +221 -0
  4. agent/claudesdk/src/__init__.py +8 -0
  5. agent/claudesdk/src/agent.py +400 -0
  6. agent/claudesdk/src/mcp_proxy.py +409 -0
  7. agent/claudesdk/src/utils.py +420 -0
  8. agent/googleadk/__init__.py +15 -0
  9. agent/googleadk/example.py +237 -0
  10. agent/googleadk/src/__init__.py +12 -0
  11. agent/googleadk/src/agent.py +401 -0
  12. agent/googleadk/src/mcp_wrapper.py +163 -0
  13. agent/googleadk/src/utils.py +602 -0
  14. agent/langchain/__init__.py +8 -0
  15. agent/langchain/example.py +213 -0
  16. agent/langchain/src/__init__.py +8 -0
  17. agent/langchain/src/agent.py +645 -0
  18. agent/langchain/src/utils.py +433 -0
  19. agent/openaisdk/__init__.py +17 -0
  20. agent/openaisdk/example.py +228 -0
  21. agent/openaisdk/src/__init__.py +12 -0
  22. agent/openaisdk/src/agent.py +491 -0
  23. agent/openaisdk/src/agent_wrapper.py +143 -0
  24. agent/openaisdk/src/mcp_wrapper.py +395 -0
  25. agent/openaisdk/src/utils.py +493 -0
  26. agent/openclaw/__init__.py +10 -0
  27. agent/openclaw/example.py +251 -0
  28. agent/openclaw/src/__init__.py +14 -0
  29. agent/openclaw/src/agent.py +930 -0
  30. agent/openclaw/src/helpers/__init__.py +1 -0
  31. agent/openclaw/src/helpers/auth_helpers.py +55 -0
  32. agent/openclaw/src/mcp_proxy.py +564 -0
  33. agent/openclaw/src/plugin_generator.py +231 -0
  34. agent/openclaw/src/utils.py +341 -0
  35. agent/pocketflow/__init__.py +18 -0
  36. agent/pocketflow/example.py +221 -0
  37. agent/pocketflow/prompts/react_agent.py +46 -0
  38. agent/pocketflow/src/__init__.py +6 -0
  39. agent/pocketflow/src/agent.py +507 -0
  40. agent/pocketflow/src/agent_wrapper.py +159 -0
  41. agent/pocketflow/src/async_helper.py +92 -0
  42. agent/pocketflow/src/mcp_react_agent.py +279 -0
  43. agent/pocketflow/src/native_agent.py +74 -0
  44. agent/pocketflow/src/nodes.py +467 -0
  45. benchmark/__init__.py +0 -0
  46. benchmark/browser/benign.jsonl +34 -0
  47. benchmark/browser/direct.jsonl +85 -0
  48. benchmark/browser/indirect.jsonl +82 -0
  49. benchmark/code/benign.jsonl +0 -0
  50. benchmark/code/direct.jsonl +121 -0
  51. benchmark/code/indirect.jsonl +165 -0
  52. benchmark/crm/benign.jsonl +165 -0
  53. benchmark/crm/direct.jsonl +90 -0
  54. benchmark/crm/indirect.jsonl +150 -0
  55. benchmark/customer-service/benign.jsonl +160 -0
  56. benchmark/customer-service/direct.jsonl +100 -0
  57. benchmark/customer-service/indirect.jsonl +101 -0
  58. benchmark/finance/benign.jsonl +0 -0
  59. benchmark/finance/direct.jsonl +200 -0
  60. benchmark/finance/indirect.jsonl +200 -0
  61. benchmark/legal/benign.jsonl +0 -0
  62. benchmark/legal/direct.jsonl +200 -0
  63. benchmark/legal/indirect.jsonl +200 -0
  64. benchmark/macos/benign.jsonl +30 -0
  65. benchmark/macos/direct.jsonl +50 -0
  66. benchmark/macos/indirect.jsonl +50 -0
  67. benchmark/medical/benign.jsonl +642 -0
  68. benchmark/medical/direct.jsonl +229 -0
  69. benchmark/medical/indirect.jsonl +222 -0
  70. benchmark/os-filesystem/benign.jsonl +200 -0
  71. benchmark/os-filesystem/direct.jsonl +200 -0
  72. benchmark/os-filesystem/indirect.jsonl +200 -0
  73. benchmark/research/benign.jsonl +0 -0
  74. benchmark/research/direct.jsonl +119 -0
  75. benchmark/research/indirect.jsonl +125 -0
  76. benchmark/telecom/benign.jsonl +120 -0
  77. benchmark/telecom/direct.jsonl +161 -0
  78. benchmark/telecom/indirect.jsonl +166 -0
  79. benchmark/travel/benign.jsonl +130 -0
  80. benchmark/travel/direct.jsonl +105 -0
  81. benchmark/travel/indirect.jsonl +120 -0
  82. benchmark/windows/benign.jsonl +100 -0
  83. benchmark/windows/direct.jsonl +140 -0
  84. benchmark/windows/indirect.jsonl +107 -0
  85. benchmark/workflow/benign.jsonl +335 -0
  86. benchmark/workflow/direct.jsonl +78 -0
  87. benchmark/workflow/indirect.jsonl +107 -0
  88. cli/__init__.py +5 -0
  89. cli/main.py +182 -0
  90. cli/scaffold.py +334 -0
  91. decodingtrust_agent_sdk-0.1.0.dist-info/METADATA +642 -0
  92. decodingtrust_agent_sdk-0.1.0.dist-info/RECORD +374 -0
  93. decodingtrust_agent_sdk-0.1.0.dist-info/WHEEL +5 -0
  94. decodingtrust_agent_sdk-0.1.0.dist-info/entry_points.txt +2 -0
  95. decodingtrust_agent_sdk-0.1.0.dist-info/licenses/LICENSE +201 -0
  96. decodingtrust_agent_sdk-0.1.0.dist-info/top_level.txt +6 -0
  97. dt_arena/config/env.yaml +515 -0
  98. dt_arena/config/injection_mcp.yaml +430 -0
  99. dt_arena/config/mcp.yaml +642 -0
  100. dt_arena/envs/arxiv/docker-compose-hub.yml +31 -0
  101. dt_arena/envs/arxiv/docker-compose.yml +36 -0
  102. dt_arena/envs/atlassian/docker/docker-compose.dev.yml +65 -0
  103. dt_arena/envs/atlassian/docker/docker-compose.yml +53 -0
  104. dt_arena/envs/atlassian/docker-compose-hub.yml +57 -0
  105. dt_arena/envs/atlassian/docker-compose.yml +72 -0
  106. dt_arena/envs/bigquery/docker-compose.yml +20 -0
  107. dt_arena/envs/booking/docker-compose.yml +59 -0
  108. dt_arena/envs/calendar/docker-compose-hub.yml +30 -0
  109. dt_arena/envs/calendar/docker-compose.yml +42 -0
  110. dt_arena/envs/custom-website/docker-compose.yml +6 -0
  111. dt_arena/envs/customer_service/docker-compose.yml +59 -0
  112. dt_arena/envs/databricks/docker-compose-hub.yml +47 -0
  113. dt_arena/envs/databricks/docker-compose.yml +51 -0
  114. dt_arena/envs/ecommerce/docker-compose.yml +6 -0
  115. dt_arena/envs/ers/docker-compose.yml +36 -0
  116. dt_arena/envs/ers/hrms/docker/docker-compose.yml +31 -0
  117. dt_arena/envs/finance/docker-compose.yml +23 -0
  118. dt_arena/envs/github/docker/docker-compose-hub.yml +50 -0
  119. dt_arena/envs/github/docker/docker-compose.yml +50 -0
  120. dt_arena/envs/gmail/docker-compose-hub.yml +51 -0
  121. dt_arena/envs/gmail/docker-compose.yml +65 -0
  122. dt_arena/envs/google-form/docker-compose-hub.yml +33 -0
  123. dt_arena/envs/google-form/docker-compose.yml +41 -0
  124. dt_arena/envs/googledocs/docker-compose-hub.yml +61 -0
  125. dt_arena/envs/googledocs/docker-compose.yml +78 -0
  126. dt_arena/envs/hospital/docker-compose-hub.yml +25 -0
  127. dt_arena/envs/hospital/docker-compose.yml +27 -0
  128. dt_arena/envs/legal/docker-compose.yml +22 -0
  129. dt_arena/envs/linkedin/docker-compose.yml +63 -0
  130. dt_arena/envs/macos/docker-compose.yml +79 -0
  131. dt_arena/envs/os-filesystem/docker-compose-hub.yml +16 -0
  132. dt_arena/envs/os-filesystem/docker-compose.yml +20 -0
  133. dt_arena/envs/paypal/docker-compose-hub.yml +48 -0
  134. dt_arena/envs/paypal/docker-compose.yml +63 -0
  135. dt_arena/envs/research/docker-compose-hub.yml +13 -0
  136. dt_arena/envs/research/docker-compose.yml +24 -0
  137. dt_arena/envs/salesforce_crm/docker-compose-hub.yaml +45 -0
  138. dt_arena/envs/salesforce_crm/docker-compose.yaml +49 -0
  139. dt_arena/envs/slack/docker-compose-hub.yml +28 -0
  140. dt_arena/envs/slack/docker-compose.yml +41 -0
  141. dt_arena/envs/snowflake/docker-compose-hub.yml +41 -0
  142. dt_arena/envs/snowflake/docker-compose.yml +44 -0
  143. dt_arena/envs/telecom/docker-compose-hub.yml +16 -0
  144. dt_arena/envs/telecom/docker-compose.yml +17 -0
  145. dt_arena/envs/telegram/docker-compose-hub.yml +57 -0
  146. dt_arena/envs/telegram/docker-compose.yml +62 -0
  147. dt_arena/envs/terminal/docker-compose-hub.yml +12 -0
  148. dt_arena/envs/terminal/docker-compose.yml +26 -0
  149. dt_arena/envs/travel/docker-compose-hub.yml +19 -0
  150. dt_arena/envs/travel/docker-compose.yml +19 -0
  151. dt_arena/envs/whatsapp/docker-compose-hub.yml +61 -0
  152. dt_arena/envs/whatsapp/docker-compose.yml +78 -0
  153. dt_arena/envs/windows/docker-compose.yml +71 -0
  154. dt_arena/envs/zoom/docker-compose-hub.yml +27 -0
  155. dt_arena/envs/zoom/docker-compose.yml +40 -0
  156. dt_arena/injection_mcp_server/atlassian/env_injection.py +134 -0
  157. dt_arena/injection_mcp_server/calendar/env_injection.py +217 -0
  158. dt_arena/injection_mcp_server/custom_website/env_injection.py +97 -0
  159. dt_arena/injection_mcp_server/customer_service/env_injection.py +659 -0
  160. dt_arena/injection_mcp_server/databricks/env_injection.py +255 -0
  161. dt_arena/injection_mcp_server/ecommerce/env_injection.py +110 -0
  162. dt_arena/injection_mcp_server/finance/env_injection.py +85 -0
  163. dt_arena/injection_mcp_server/github/env_injection.py +206 -0
  164. dt_arena/injection_mcp_server/gmail/env_injection.py +211 -0
  165. dt_arena/injection_mcp_server/google_form/env_injection.py +186 -0
  166. dt_arena/injection_mcp_server/googledocs/env_injection.py +44 -0
  167. dt_arena/injection_mcp_server/hospital/env_injection.py +43 -0
  168. dt_arena/injection_mcp_server/legal/env_injection.py +229 -0
  169. dt_arena/injection_mcp_server/macos/env_injection.py +272 -0
  170. dt_arena/injection_mcp_server/os-filesystem/env_injection.py +341 -0
  171. dt_arena/injection_mcp_server/paypal/env_injection.py +268 -0
  172. dt_arena/injection_mcp_server/research/env_injection.py +616 -0
  173. dt_arena/injection_mcp_server/salesforce/env_injection.py +514 -0
  174. dt_arena/injection_mcp_server/slack/env_injection.py +265 -0
  175. dt_arena/injection_mcp_server/snowflake/env_injection.py +230 -0
  176. dt_arena/injection_mcp_server/telecom/env_injection.py +503 -0
  177. dt_arena/injection_mcp_server/telegram/env_injection.py +171 -0
  178. dt_arena/injection_mcp_server/terminal/env_injection.py +523 -0
  179. dt_arena/injection_mcp_server/travel/env_injection.py +173 -0
  180. dt_arena/injection_mcp_server/whatsapp/env_injection.py +185 -0
  181. dt_arena/injection_mcp_server/windows/env_injection.py +943 -0
  182. dt_arena/injection_mcp_server/zoom/env_injection.py +216 -0
  183. dt_arena/mcp_server/atlassian/main.py +1554 -0
  184. dt_arena/mcp_server/atlassian/test_server.py +66 -0
  185. dt_arena/mcp_server/bigquery/main.py +333 -0
  186. dt_arena/mcp_server/booking/main.py +310 -0
  187. dt_arena/mcp_server/browser/main.py +1741 -0
  188. dt_arena/mcp_server/calendar/example_multi_user.py +162 -0
  189. dt_arena/mcp_server/calendar/main.py +792 -0
  190. dt_arena/mcp_server/calendar/test_mcp.py +135 -0
  191. dt_arena/mcp_server/customer_service/main.py +1063 -0
  192. dt_arena/mcp_server/databricks/main.py +566 -0
  193. dt_arena/mcp_server/databricks/probe.py +102 -0
  194. dt_arena/mcp_server/ers/main.py +845 -0
  195. dt_arena/mcp_server/finance/__init__.py +87 -0
  196. dt_arena/mcp_server/finance/core/__init__.py +12 -0
  197. dt_arena/mcp_server/finance/core/data_loader.py +558 -0
  198. dt_arena/mcp_server/finance/core/portfolio.py +565 -0
  199. dt_arena/mcp_server/finance/evaluation/__init__.py +20 -0
  200. dt_arena/mcp_server/finance/evaluation/evaluator.py +217 -0
  201. dt_arena/mcp_server/finance/evaluation/logger.py +137 -0
  202. dt_arena/mcp_server/finance/injection/__init__.py +66 -0
  203. dt_arena/mcp_server/finance/injection/config.py +176 -0
  204. dt_arena/mcp_server/finance/injection/content.py +755 -0
  205. dt_arena/mcp_server/finance/injection/html.py +409 -0
  206. dt_arena/mcp_server/finance/injection/locations.py +167 -0
  207. dt_arena/mcp_server/finance/injection/methods.py +193 -0
  208. dt_arena/mcp_server/finance/injection/presets.py +1023 -0
  209. dt_arena/mcp_server/finance/main.py +361 -0
  210. dt_arena/mcp_server/finance/run_mcp.py +21 -0
  211. dt_arena/mcp_server/finance/run_web.py +26 -0
  212. dt_arena/mcp_server/finance/server/__init__.py +41 -0
  213. dt_arena/mcp_server/finance/server/extractor.py +1453 -0
  214. dt_arena/mcp_server/finance/server/extractor_minimal.py +292 -0
  215. dt_arena/mcp_server/finance/server/extractor_simple.py +1164 -0
  216. dt_arena/mcp_server/finance/server/injection_mcp.py +865 -0
  217. dt_arena/mcp_server/finance/server/mcp.py +451 -0
  218. dt_arena/mcp_server/finance/server/tools/__init__.py +23 -0
  219. dt_arena/mcp_server/finance/server/tools/account.py +88 -0
  220. dt_arena/mcp_server/finance/server/tools/browsing.py +328 -0
  221. dt_arena/mcp_server/finance/server/tools/social.py +73 -0
  222. dt_arena/mcp_server/finance/server/tools/trading.py +242 -0
  223. dt_arena/mcp_server/finance/server/tools/utility.py +49 -0
  224. dt_arena/mcp_server/finance/server/web.py +2139 -0
  225. dt_arena/mcp_server/finance/tasks/benchmark/__init__.py +28 -0
  226. dt_arena/mcp_server/finance/tasks/benchmark/attack_pool.py +3026 -0
  227. dt_arena/mcp_server/finance/tasks/benchmark/attack_runner.py +1315 -0
  228. dt_arena/mcp_server/finance/tasks/benchmark/finra_requirements.py +1335 -0
  229. dt_arena/mcp_server/finance/tasks/benchmark/finra_tasks.py +3665 -0
  230. dt_arena/mcp_server/finance/tasks/benchmark/malicious_tasks.py +2673 -0
  231. dt_arena/mcp_server/finance/tasks/redteam_suite/run_redteam_suite.py +1713 -0
  232. dt_arena/mcp_server/finance/test_mcp_tools.py +476 -0
  233. dt_arena/mcp_server/github/main.py +441 -0
  234. dt_arena/mcp_server/gmail/main.py +1004 -0
  235. dt_arena/mcp_server/google_form/main.py +141 -0
  236. dt_arena/mcp_server/googledocs/main.py +458 -0
  237. dt_arena/mcp_server/hospital/mcp_server.py +458 -0
  238. dt_arena/mcp_server/legal/__init__.py +9 -0
  239. dt_arena/mcp_server/legal/core/__init__.py +14 -0
  240. dt_arena/mcp_server/legal/core/courtlistener_store.py +762 -0
  241. dt_arena/mcp_server/legal/core/data_loader.py +266 -0
  242. dt_arena/mcp_server/legal/core/document_store.py +197 -0
  243. dt_arena/mcp_server/legal/core/matter_manager.py +466 -0
  244. dt_arena/mcp_server/legal/main.py +89 -0
  245. dt_arena/mcp_server/legal/scripts/collect_data.py +988 -0
  246. dt_arena/mcp_server/legal/server/__init__.py +14 -0
  247. dt_arena/mcp_server/legal/server/mcp.py +2330 -0
  248. dt_arena/mcp_server/macos/client_test.py +270 -0
  249. dt_arena/mcp_server/macos/mcp_server.py +285 -0
  250. dt_arena/mcp_server/os-filesystem/main.py +1380 -0
  251. dt_arena/mcp_server/paypal/main.py +501 -0
  252. dt_arena/mcp_server/research/main.py +777 -0
  253. dt_arena/mcp_server/salesforce/main.py +2006 -0
  254. dt_arena/mcp_server/slack/main.py +318 -0
  255. dt_arena/mcp_server/snowflake/main.py +612 -0
  256. dt_arena/mcp_server/snowflake/probe.py +183 -0
  257. dt_arena/mcp_server/telecom/mcp_client.py +423 -0
  258. dt_arena/mcp_server/telecom/mcp_server.py +1059 -0
  259. dt_arena/mcp_server/telegram/main.py +338 -0
  260. dt_arena/mcp_server/terminal/main.py +163 -0
  261. dt_arena/mcp_server/travel/client_test.py +16 -0
  262. dt_arena/mcp_server/travel/mcp_server.py +404 -0
  263. dt_arena/mcp_server/whatsapp/main.py +318 -0
  264. dt_arena/mcp_server/windows/client_test.py +270 -0
  265. dt_arena/mcp_server/windows/mcp_server.py +218 -0
  266. dt_arena/mcp_server/zoom/main.py +466 -0
  267. dt_arena/src/__init__.py +0 -0
  268. dt_arena/src/hooks/__init__.py +0 -0
  269. dt_arena/src/hooks/audit_log.py +30 -0
  270. dt_arena/src/hooks/hooks.json +3 -0
  271. dt_arena/src/run_benign.py +142 -0
  272. dt_arena/src/types/__init__.py +0 -0
  273. dt_arena/src/types/agent.py +441 -0
  274. dt_arena/src/types/attacks.py +2 -0
  275. dt_arena/src/types/environment.py +2 -0
  276. dt_arena/src/types/hooks.py +174 -0
  277. dt_arena/src/types/judge.py +52 -0
  278. dt_arena/src/types/red_teaming_trajectory.py +385 -0
  279. dt_arena/src/types/task.py +260 -0
  280. dt_arena/src/types/trajectory.py +315 -0
  281. dt_arena/utils/__init__.py +1 -0
  282. dt_arena/utils/atlassian/__init__.py +27 -0
  283. dt_arena/utils/atlassian/helpers.py +520 -0
  284. dt_arena/utils/bigquery/__init__.py +1 -0
  285. dt_arena/utils/bigquery/helpers.py +246 -0
  286. dt_arena/utils/calendar/__init__.py +1 -0
  287. dt_arena/utils/calendar/helpers.py +87 -0
  288. dt_arena/utils/customer_service/__init__.py +17 -0
  289. dt_arena/utils/customer_service/cs_env_client.py +940 -0
  290. dt_arena/utils/customer_service/helpers.py +339 -0
  291. dt_arena/utils/customer_service/judges/__init__.py +20 -0
  292. dt_arena/utils/customer_service/judges/abusive_comms.py +149 -0
  293. dt_arena/utils/customer_service/judges/bulk_destructive.py +202 -0
  294. dt_arena/utils/customer_service/judges/cross_customer.py +481 -0
  295. dt_arena/utils/customer_service/judges/email_exfiltration.py +320 -0
  296. dt_arena/utils/customer_service/judges/financial_fraud.py +221 -0
  297. dt_arena/utils/customer_service/judges/llm_utils.py +264 -0
  298. dt_arena/utils/customer_service/judges/pii_disclosure.py +837 -0
  299. dt_arena/utils/customer_service/judges/policy_misrep.py +44 -0
  300. dt_arena/utils/customer_service/judges/text_utils.py +21 -0
  301. dt_arena/utils/databricks/__init__.py +2 -0
  302. dt_arena/utils/databricks/helpers.py +210 -0
  303. dt_arena/utils/finance/__init__.py +0 -0
  304. dt_arena/utils/finance/helpers.py +263 -0
  305. dt_arena/utils/github/__init__.py +1 -0
  306. dt_arena/utils/github/helpers.py +249 -0
  307. dt_arena/utils/gmail/__init__.py +1 -0
  308. dt_arena/utils/gmail/helpers.py +344 -0
  309. dt_arena/utils/google_form/__init__.py +2 -0
  310. dt_arena/utils/google_form/helpers.py +133 -0
  311. dt_arena/utils/legal/__init__.py +0 -0
  312. dt_arena/utils/legal/helpers.py +228 -0
  313. dt_arena/utils/macos/__init__.py +0 -0
  314. dt_arena/utils/macos/env_setup.py +215 -0
  315. dt_arena/utils/macos/helpers.py +61 -0
  316. dt_arena/utils/os_filesystem/__init__.py +1 -0
  317. dt_arena/utils/os_filesystem/helpers.py +366 -0
  318. dt_arena/utils/paypal/__init__.py +1 -0
  319. dt_arena/utils/paypal/helpers.py +178 -0
  320. dt_arena/utils/port_allocator.py +266 -0
  321. dt_arena/utils/research/__init__.py +0 -0
  322. dt_arena/utils/research/helpers.py +251 -0
  323. dt_arena/utils/salesforce/__init__.py +1 -0
  324. dt_arena/utils/salesforce/helpers.py +719 -0
  325. dt_arena/utils/slack/__init__.py +1 -0
  326. dt_arena/utils/slack/helpers.py +176 -0
  327. dt_arena/utils/snowflake/__init__.py +1 -0
  328. dt_arena/utils/snowflake/helpers.py +166 -0
  329. dt_arena/utils/telecom/__init__.py +1 -0
  330. dt_arena/utils/telecom/helpers.py +760 -0
  331. dt_arena/utils/telegram/__init__.py +0 -0
  332. dt_arena/utils/telegram/helpers.py +174 -0
  333. dt_arena/utils/terminal/__init__.py +0 -0
  334. dt_arena/utils/terminal/helpers.py +20 -0
  335. dt_arena/utils/travel/__init__.py +0 -0
  336. dt_arena/utils/travel/env_client.py +537 -0
  337. dt_arena/utils/travel/llm_judge.py +137 -0
  338. dt_arena/utils/travel/prompts.py +64 -0
  339. dt_arena/utils/utils/__init__.py +122 -0
  340. dt_arena/utils/whatsapp/__init__.py +0 -0
  341. dt_arena/utils/whatsapp/helpers.py +226 -0
  342. dt_arena/utils/windows/__init__.py +0 -0
  343. dt_arena/utils/windows/env_reset.py +224 -0
  344. dt_arena/utils/windows/env_setup.py +280 -0
  345. dt_arena/utils/windows/exfil_helpers.py +170 -0
  346. dt_arena/utils/windows/helpers.py +74 -0
  347. dt_arena/utils/zoom/__init__.py +1 -0
  348. dt_arena/utils/zoom/helpers.py +70 -0
  349. eval/__init__.py +1 -0
  350. eval/evaluation.py +426 -0
  351. eval/task_runner.py +449 -0
  352. utils/__init__.py +148 -0
  353. utils/agent_helpers.py +308 -0
  354. utils/agent_wrapper.py +189 -0
  355. utils/compose_utils.py +135 -0
  356. utils/config.py +77 -0
  357. utils/env_helpers.py +104 -0
  358. utils/eval_stats.py +88 -0
  359. utils/injection_helpers.py +429 -0
  360. utils/injection_mcp_helpers.py +152 -0
  361. utils/judge_helpers.py +181 -0
  362. utils/judge_utils.py +472 -0
  363. utils/llm.py +196 -0
  364. utils/logging.py +45 -0
  365. utils/mcp_helpers.py +232 -0
  366. utils/mcp_manager.py +235 -0
  367. utils/memory_guard.py +18 -0
  368. utils/red_teaming_sandbox.py +476 -0
  369. utils/reset_helpers.py +318 -0
  370. utils/resource_manager.py +370 -0
  371. utils/skill_helpers.py +447 -0
  372. utils/task_executor.py +904 -0
  373. utils/task_helpers.py +270 -0
  374. utils/template_helpers.py +179 -0
@@ -0,0 +1,514 @@
1
+ """Salesforce Environment Injection MCP Server for red-teaming purposes.
2
+
3
+ This server provides tools to inject data into Salesforce for adversarial testing.
4
+ It reuses the Salesforce API authentication and request patterns from the main MCP server.
5
+ """
6
+ import os
7
+ import sys
8
+ import asyncio
9
+ from typing import Any, Dict, Optional, List
10
+
11
+ import httpx
12
+ from fastmcp import FastMCP
13
+
14
+
15
+ # Basic configuration - reuse same Salesforce instance
16
+ SALESFORCE_BASE_URL = os.getenv("SALESFORCE_BASE_URL", "http://128.111.28.87:8080/")
17
+ SALESFORCE_TOKEN_URL = f"{SALESFORCE_BASE_URL.rstrip('/')}/Api/access_token"
18
+
19
+ # Grant configuration (env fallbacks)
20
+ SALESFORCE_GRANT_TYPE = os.getenv("SALESFORCE_GRANT_TYPE", "client_credentials")
21
+ SALESFORCE_CLIENT_ID = os.getenv("SALESFORCE_CLIENT_ID", "17817554-086b-83d1-bf9d-69026221f529")
22
+ SALESFORCE_CLIENT_SECRET = os.getenv("SALESFORCE_CLIENT_SECRET", "mcp-secret-123")
23
+ SALESFORCE_USERNAME = os.getenv("SALESFORCE_USERNAME", "bitnami")
24
+ SALESFORCE_PASSWORD = os.getenv("SALESFORCE_PASSWORD", "user")
25
+
26
+ # Optional pre-supplied access token
27
+ SALESFORCE_ACCESS_TOKEN = os.getenv("SALESFORCE_ACCESS_TOKEN", "")
28
+
29
+ # Injection server configuration
30
+ SALESFORCE_ENV_INJECTION_MCP_HOST = os.getenv("SALESFORCE_ENV_INJECTION_MCP_HOST", "localhost")
31
+ SALESFORCE_ENV_INJECTION_MCP_PORT = os.getenv("SALESFORCE_ENV_INJECTION_MCP_PORT", "8851")
32
+
33
+ mcp = FastMCP(name="SalesforceEnvInjection")
34
+
35
+ # JSON:API header constants
36
+ JSONAPI_ACCEPT = "application/vnd.api+json"
37
+ JSONAPI_CONTENT = "application/vnd.api+json"
38
+
39
+
40
+ def _bearer_headers(token: Optional[str]) -> Dict[str, str]:
41
+ headers: Dict[str, str] = {}
42
+ if token:
43
+ headers["Authorization"] = f"Bearer {token}"
44
+ return headers
45
+
46
+
47
+ async def _post_token() -> str:
48
+ """Obtain an OAuth2 access token from Salesforce."""
49
+ grant_type = SALESFORCE_GRANT_TYPE.strip()
50
+ client_id = SALESFORCE_CLIENT_ID
51
+ client_secret = SALESFORCE_CLIENT_SECRET
52
+
53
+ data: Dict[str, str] = {"grant_type": grant_type}
54
+ if grant_type == "password":
55
+ data.update({
56
+ "username": SALESFORCE_USERNAME,
57
+ "password": SALESFORCE_PASSWORD,
58
+ "client_id": client_id,
59
+ "client_secret": client_secret,
60
+ })
61
+ elif grant_type == "client_credentials":
62
+ data.update({
63
+ "client_id": client_id,
64
+ "client_secret": client_secret,
65
+ })
66
+ else:
67
+ raise ValueError(f"Unsupported grant_type: {grant_type}")
68
+
69
+ headers = {"Accept": "application/json"}
70
+ async with httpx.AsyncClient(timeout=30.0) as client:
71
+ r = await client.post(SALESFORCE_TOKEN_URL, data=data, headers=headers)
72
+ r.raise_for_status()
73
+ resp = r.json()
74
+ token = resp.get("access_token") or resp.get("token")
75
+ if not token:
76
+ raise RuntimeError(f"Failed to obtain access token: {resp}")
77
+ return token
78
+
79
+
80
+ async def _get_token(access_token: Optional[str] = None) -> str:
81
+ """Get an access token. If not provided, attempt to obtain via configured grant."""
82
+ token = (access_token or SALESFORCE_ACCESS_TOKEN).strip()
83
+ if token:
84
+ return token
85
+ return await _post_token()
86
+
87
+
88
+ async def _request(
89
+ method: str,
90
+ url: str,
91
+ token: Optional[str] = None,
92
+ params: Optional[Dict[str, Any]] = None,
93
+ json: Optional[Any] = None,
94
+ extra_headers: Optional[Dict[str, str]] = None,
95
+ ) -> Any:
96
+ """Unified HTTP request with structured error responses."""
97
+ headers = _bearer_headers(token)
98
+ if extra_headers:
99
+ headers.update(extra_headers)
100
+ try:
101
+ async with httpx.AsyncClient(timeout=30.0) as client:
102
+ r = await client.request(method, url, params=params, json=json, headers=headers)
103
+ r.raise_for_status()
104
+ try:
105
+ return r.json()
106
+ except Exception:
107
+ return {"ok": True, "text": r.text}
108
+ except httpx.HTTPStatusError as e:
109
+ resp = e.response
110
+ return {
111
+ "error": f"HTTP {resp.status_code}",
112
+ "status_code": resp.status_code,
113
+ "text": resp.text,
114
+ }
115
+ except httpx.RequestError as e:
116
+ return {"error": "request_error", "message": str(e)}
117
+
118
+
119
+ async def _create_record(module_name: str, attributes: Dict[str, Any], relationships: Optional[Dict[str, Any]] = None) -> Any:
120
+ """Create a record in Salesforce."""
121
+ token = await _get_token()
122
+ url = f"{SALESFORCE_BASE_URL.rstrip('/')}/Api/V8/module"
123
+ payload: Dict[str, Any] = {"data": {"type": module_name, "attributes": attributes}}
124
+ if relationships:
125
+ payload["data"]["relationships"] = relationships
126
+ return await _request("POST", url, token, json=payload, extra_headers={"Accept": JSONAPI_ACCEPT, "Content-Type": JSONAPI_CONTENT})
127
+
128
+
129
+ # ============ Injection Tools ============
130
+
131
+ @mcp.tool(name="inject_lead")
132
+ async def inject_lead(
133
+ first_name: str,
134
+ last_name: str,
135
+ status: str = "New",
136
+ lead_source: str = "Web Site",
137
+ title: Optional[str] = None,
138
+ company: Optional[str] = None,
139
+ email: Optional[str] = None,
140
+ phone_work: Optional[str] = None,
141
+ phone_mobile: Optional[str] = None,
142
+ description: Optional[str] = None,
143
+ ) -> dict:
144
+ """Inject a new lead record into Salesforce for red-teaming purposes.
145
+
146
+ Args:
147
+ first_name (str): Lead's first name. E.g., 'John'.
148
+ last_name (str): Lead's last name. E.g., 'Doe'.
149
+ status (str): Lead status. E.g., 'New', 'Assigned', 'In Process', 'Converted', 'Recycled', 'Dead'.
150
+ lead_source (str): Lead source. E.g., 'Web Site', 'Cold Call', 'Employee', 'Partner', 'Trade Show'.
151
+ title (str, optional): Job title. E.g., 'Sales Manager'.
152
+ company (str, optional): Company name. E.g., 'Acme Corp'.
153
+ email (str, optional): Email address. E.g., 'john.doe@example.com'.
154
+ phone_work (str, optional): Work phone. E.g., '+1-555-123-4567'.
155
+ phone_mobile (str, optional): Mobile phone. E.g., '+1-555-987-6543'.
156
+ description (str, optional): Lead description/notes.
157
+
158
+ Returns:
159
+ dict: Response indicating success or error with details.
160
+ """
161
+ attributes: Dict[str, Any] = {
162
+ "first_name": first_name,
163
+ "last_name": last_name,
164
+ "status": status,
165
+ "lead_source": lead_source,
166
+ }
167
+ if title:
168
+ attributes["title"] = title
169
+ if company:
170
+ attributes["account_name"] = company
171
+ if email:
172
+ attributes["email1"] = email
173
+ if phone_work:
174
+ attributes["phone_work"] = phone_work
175
+ if phone_mobile:
176
+ attributes["phone_mobile"] = phone_mobile
177
+ if description:
178
+ attributes["description"] = description
179
+
180
+ return await _create_record("Leads", attributes)
181
+
182
+
183
+ @mcp.tool(name="inject_contact")
184
+ async def inject_contact(
185
+ first_name: str,
186
+ last_name: str,
187
+ title: Optional[str] = None,
188
+ department: Optional[str] = None,
189
+ email: Optional[str] = None,
190
+ phone_work: Optional[str] = None,
191
+ phone_mobile: Optional[str] = None,
192
+ description: Optional[str] = None,
193
+ ) -> dict:
194
+ """Inject a new contact record into Salesforce for red-teaming purposes.
195
+
196
+ Args:
197
+ first_name (str): Contact's first name. E.g., 'Jane'.
198
+ last_name (str): Contact's last name. E.g., 'Smith'.
199
+ title (str, optional): Job title. E.g., 'CTO'.
200
+ department (str, optional): Department. E.g., 'Engineering'.
201
+ email (str, optional): Email address. E.g., 'jane.smith@company.com'.
202
+ phone_work (str, optional): Work phone. E.g., '+1-555-111-2222'.
203
+ phone_mobile (str, optional): Mobile phone. E.g., '+1-555-333-4444'.
204
+ description (str, optional): Contact notes/description.
205
+
206
+ Returns:
207
+ dict: Response indicating success or error with details.
208
+ """
209
+ attributes: Dict[str, Any] = {
210
+ "first_name": first_name,
211
+ "last_name": last_name,
212
+ }
213
+ if title:
214
+ attributes["title"] = title
215
+ if department:
216
+ attributes["department"] = department
217
+ if email:
218
+ attributes["email1"] = email
219
+ if phone_work:
220
+ attributes["phone_work"] = phone_work
221
+ if phone_mobile:
222
+ attributes["phone_mobile"] = phone_mobile
223
+ if description:
224
+ attributes["description"] = description
225
+
226
+ return await _create_record("Contacts", attributes)
227
+
228
+
229
+ @mcp.tool(name="inject_account")
230
+ async def inject_account(
231
+ name: str,
232
+ account_type: str = "Customer",
233
+ industry: Optional[str] = None,
234
+ phone_office: Optional[str] = None,
235
+ website: Optional[str] = None,
236
+ billing_address_street: Optional[str] = None,
237
+ billing_address_city: Optional[str] = None,
238
+ billing_address_state: Optional[str] = None,
239
+ billing_address_postalcode: Optional[str] = None,
240
+ billing_address_country: Optional[str] = None,
241
+ description: Optional[str] = None,
242
+ ) -> dict:
243
+ """Inject a new account (company) record into Salesforce for red-teaming purposes.
244
+
245
+ Args:
246
+ name (str): Account/Company name. E.g., 'Acme Corporation'.
247
+ account_type (str): Account type. E.g., 'Customer', 'Investor', 'Partner', 'Reseller', 'Vendor'.
248
+ industry (str, optional): Industry sector. E.g., 'Technology', 'Finance', 'Healthcare'.
249
+ phone_office (str, optional): Office phone. E.g., '+1-555-000-1111'.
250
+ website (str, optional): Company website. E.g., 'https://acme.com'.
251
+ billing_address_street (str, optional): Street address. E.g., '123 Main St'.
252
+ billing_address_city (str, optional): City. E.g., 'San Francisco'.
253
+ billing_address_state (str, optional): State/Province. E.g., 'CA'.
254
+ billing_address_postalcode (str, optional): Postal/ZIP code. E.g., '94102'.
255
+ billing_address_country (str, optional): Country. E.g., 'USA'.
256
+ description (str, optional): Account description/notes.
257
+
258
+ Returns:
259
+ dict: Response indicating success or error with details.
260
+ """
261
+ attributes: Dict[str, Any] = {
262
+ "name": name,
263
+ "account_type": account_type,
264
+ }
265
+ if industry:
266
+ attributes["industry"] = industry
267
+ if phone_office:
268
+ attributes["phone_office"] = phone_office
269
+ if website:
270
+ attributes["website"] = website
271
+ if billing_address_street:
272
+ attributes["billing_address_street"] = billing_address_street
273
+ if billing_address_city:
274
+ attributes["billing_address_city"] = billing_address_city
275
+ if billing_address_state:
276
+ attributes["billing_address_state"] = billing_address_state
277
+ if billing_address_postalcode:
278
+ attributes["billing_address_postalcode"] = billing_address_postalcode
279
+ if billing_address_country:
280
+ attributes["billing_address_country"] = billing_address_country
281
+ if description:
282
+ attributes["description"] = description
283
+
284
+ return await _create_record("Accounts", attributes)
285
+
286
+
287
+ @mcp.tool(name="inject_opportunity")
288
+ async def inject_opportunity(
289
+ name: str,
290
+ amount: float,
291
+ sales_stage: str = "Prospecting",
292
+ probability: int = 10,
293
+ lead_source: str = "Web Site",
294
+ date_closed: Optional[str] = None,
295
+ opportunity_type: Optional[str] = None,
296
+ description: Optional[str] = None,
297
+ ) -> dict:
298
+ """Inject a new opportunity (deal) record into Salesforce for red-teaming purposes.
299
+
300
+ Args:
301
+ name (str): Opportunity name. E.g., 'Enterprise License Deal'.
302
+ amount (float): Deal amount/value. E.g., 50000.00.
303
+ sales_stage (str): Sales stage. E.g., 'Prospecting', 'Qualification', 'Needs Analysis',
304
+ 'Value Proposition', 'Id. Decision Makers', 'Perception Analysis',
305
+ 'Proposal/Price Quote', 'Negotiation/Review', 'Closed Won', 'Closed Lost'.
306
+ probability (int): Win probability percentage (0-100). E.g., 50.
307
+ lead_source (str): Lead source. E.g., 'Web Site', 'Cold Call', 'Partner', 'Trade Show'.
308
+ date_closed (str, optional): Expected close date in YYYY-MM-DD format. E.g., '2025-03-15'.
309
+ opportunity_type (str, optional): Opportunity type. E.g., 'New Business', 'Existing Business'.
310
+ description (str, optional): Opportunity description/notes.
311
+
312
+ Returns:
313
+ dict: Response indicating success or error with details.
314
+ """
315
+ attributes: Dict[str, Any] = {
316
+ "name": name,
317
+ "amount": amount,
318
+ "sales_stage": sales_stage,
319
+ "probability": probability,
320
+ "lead_source": lead_source,
321
+ }
322
+ if date_closed:
323
+ attributes["date_closed"] = date_closed
324
+ if opportunity_type:
325
+ attributes["opportunity_type"] = opportunity_type
326
+ if description:
327
+ attributes["description"] = description
328
+
329
+ return await _create_record("Opportunities", attributes)
330
+
331
+
332
+ @mcp.tool(name="inject_call")
333
+ async def inject_call(
334
+ name: str,
335
+ direction: str = "Outbound",
336
+ status: str = "Planned",
337
+ date_start: Optional[str] = None,
338
+ duration_hours: int = 0,
339
+ duration_minutes: int = 15,
340
+ description: Optional[str] = None,
341
+ ) -> dict:
342
+ """Inject a new call record into Salesforce for red-teaming purposes.
343
+
344
+ Args:
345
+ name (str): Call subject/name. E.g., 'Follow-up call with client'.
346
+ direction (str): Call direction. E.g., 'Inbound', 'Outbound'.
347
+ status (str): Call status. E.g., 'Planned', 'Held', 'Not Held'.
348
+ date_start (str, optional): Call start datetime in YYYY-MM-DD HH:MM:SS format. E.g., '2025-01-15 10:00:00'.
349
+ duration_hours (int): Call duration hours. E.g., 1.
350
+ duration_minutes (int): Call duration minutes. E.g., 30.
351
+ description (str, optional): Call notes/description.
352
+
353
+ Returns:
354
+ dict: Response indicating success or error with details.
355
+ """
356
+ attributes: Dict[str, Any] = {
357
+ "name": name,
358
+ "direction": direction,
359
+ "status": status,
360
+ "duration_hours": duration_hours,
361
+ "duration_minutes": duration_minutes,
362
+ }
363
+ if date_start:
364
+ attributes["date_start"] = date_start
365
+ if description:
366
+ attributes["description"] = description
367
+
368
+ return await _create_record("Calls", attributes)
369
+
370
+
371
+ @mcp.tool(name="inject_meeting")
372
+ async def inject_meeting(
373
+ name: str,
374
+ status: str = "Planned",
375
+ date_start: Optional[str] = None,
376
+ duration_hours: int = 1,
377
+ duration_minutes: int = 0,
378
+ location: Optional[str] = None,
379
+ description: Optional[str] = None,
380
+ ) -> dict:
381
+ """Inject a new meeting record into Salesforce for red-teaming purposes.
382
+
383
+ Args:
384
+ name (str): Meeting subject/name. E.g., 'Quarterly Business Review'.
385
+ status (str): Meeting status. E.g., 'Planned', 'Held', 'Not Held'.
386
+ date_start (str, optional): Meeting start datetime in YYYY-MM-DD HH:MM:SS format. E.g., '2025-01-20 14:00:00'.
387
+ duration_hours (int): Meeting duration hours. E.g., 2.
388
+ duration_minutes (int): Meeting duration minutes. E.g., 0.
389
+ location (str, optional): Meeting location. E.g., 'Conference Room A' or 'https://zoom.us/j/123'.
390
+ description (str, optional): Meeting agenda/notes.
391
+
392
+ Returns:
393
+ dict: Response indicating success or error with details.
394
+ """
395
+ attributes: Dict[str, Any] = {
396
+ "name": name,
397
+ "status": status,
398
+ "duration_hours": duration_hours,
399
+ "duration_minutes": duration_minutes,
400
+ }
401
+ if date_start:
402
+ attributes["date_start"] = date_start
403
+ if location:
404
+ attributes["location"] = location
405
+ if description:
406
+ attributes["description"] = description
407
+
408
+ return await _create_record("Meetings", attributes)
409
+
410
+
411
+ @mcp.tool(name="inject_task")
412
+ async def inject_task(
413
+ name: str,
414
+ status: str = "Not Started",
415
+ priority: str = "Medium",
416
+ date_start: Optional[str] = None,
417
+ date_due: Optional[str] = None,
418
+ description: Optional[str] = None,
419
+ ) -> dict:
420
+ """Inject a new task record into Salesforce for red-teaming purposes.
421
+
422
+ Args:
423
+ name (str): Task name/subject. E.g., 'Send proposal to client'.
424
+ status (str): Task status. E.g., 'Not Started', 'In Progress', 'Completed', 'Pending Input', 'Deferred'.
425
+ priority (str): Task priority. E.g., 'High', 'Medium', 'Low'.
426
+ date_start (str, optional): Task start date in YYYY-MM-DD format. E.g., '2025-01-10'.
427
+ date_due (str, optional): Task due date in YYYY-MM-DD format. E.g., '2025-01-15'.
428
+ description (str, optional): Task description/details.
429
+
430
+ Returns:
431
+ dict: Response indicating success or error with details.
432
+ """
433
+ attributes: Dict[str, Any] = {
434
+ "name": name,
435
+ "status": status,
436
+ "priority": priority,
437
+ }
438
+ if date_start:
439
+ attributes["date_start"] = date_start
440
+ if date_due:
441
+ attributes["date_due"] = date_due
442
+ if description:
443
+ attributes["description"] = description
444
+
445
+ return await _create_record("Tasks", attributes)
446
+
447
+
448
+ @mcp.tool(name="inject_note")
449
+ async def inject_note(
450
+ name: str,
451
+ description: Optional[str] = None,
452
+ filename: Optional[str] = None,
453
+ ) -> dict:
454
+ """Inject a new note record into Salesforce for red-teaming purposes.
455
+
456
+ Args:
457
+ name (str): Note subject/title. E.g., 'Important client feedback'.
458
+ description (str, optional): Note content/body.
459
+ filename (str, optional): Associated filename (for attachment reference). E.g., 'document.pdf'.
460
+
461
+ Returns:
462
+ dict: Response indicating success or error with details.
463
+ """
464
+ attributes: Dict[str, Any] = {
465
+ "name": name,
466
+ }
467
+ if description:
468
+ attributes["description"] = description
469
+ if filename:
470
+ attributes["filename"] = filename
471
+
472
+ return await _create_record("Notes", attributes)
473
+
474
+
475
+ @mcp.tool(name="inject_case")
476
+ async def inject_case(
477
+ name: str,
478
+ status: str = "Open_New",
479
+ priority: str = "P2",
480
+ case_type: str = "User",
481
+ description: Optional[str] = None,
482
+ ) -> dict:
483
+ """Inject a new case (support ticket) record into Salesforce for red-teaming purposes.
484
+
485
+ Args:
486
+ name (str): Case subject/title. E.g., 'Product not working as expected'.
487
+ status (str): Case status. Use internal codes: 'Open_New', 'Open_Assigned', 'Open_Pending Input',
488
+ 'Closed_Closed', 'Closed_Rejected', 'Closed_Duplicate'. Defaults to 'Open_New'.
489
+ priority (str): Case priority. Use internal codes: 'P1' (High), 'P2' (Medium), 'P3' (Low).
490
+ case_type (str): Case type. E.g., 'User', 'Product', 'Administration'.
491
+ description (str, optional): Case description/details.
492
+
493
+ Returns:
494
+ dict: Response indicating success or error with details.
495
+ """
496
+ attributes: Dict[str, Any] = {
497
+ "name": name,
498
+ "status": status,
499
+ "priority": priority,
500
+ "type": case_type,
501
+ }
502
+ if description:
503
+ attributes["description"] = description
504
+
505
+ return await _create_record("Cases", attributes)
506
+
507
+
508
+ if __name__ == "__main__":
509
+ print("Starting Salesforce Environment Injection MCP Server...", file=sys.stderr)
510
+ mcp.run(
511
+ transport="http",
512
+ host=SALESFORCE_ENV_INJECTION_MCP_HOST,
513
+ port=int(SALESFORCE_ENV_INJECTION_MCP_PORT)
514
+ )