actshield 0.9.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 (366) hide show
  1. actshield/__init__.py +439 -0
  2. actshield/__main__.py +46 -0
  3. actshield/agents/__init__.py +12 -0
  4. actshield/agents/agent.py +200 -0
  5. actshield/agents/identity.py +114 -0
  6. actshield/api/__init__.py +34 -0
  7. actshield/api/models.py +198 -0
  8. actshield/api/server.py +669 -0
  9. actshield/api/service.py +599 -0
  10. actshield/approval/__init__.py +15 -0
  11. actshield/approval/approval.py +164 -0
  12. actshield/cli/__init__.py +8 -0
  13. actshield/cli/graph.py +49 -0
  14. actshield/cli/main.py +802 -0
  15. actshield/cli/shell.py +406 -0
  16. actshield/cli/theme.py +110 -0
  17. actshield/client.py +757 -0
  18. actshield/config.py +88 -0
  19. actshield/context/__init__.py +14 -0
  20. actshield/context/context.py +161 -0
  21. actshield/context/provenance.py +108 -0
  22. actshield/context/taint.py +48 -0
  23. actshield/decisions/decision.py +74 -0
  24. actshield/delegation/__init__.py +11 -0
  25. actshield/delegation/authority.py +63 -0
  26. actshield/delegation/delegation.py +180 -0
  27. actshield/demo.py +139 -0
  28. actshield/doctor.py +94 -0
  29. actshield/drift/__init__.py +27 -0
  30. actshield/drift/drift_engine.py +149 -0
  31. actshield/drift/drift_models.py +63 -0
  32. actshield/evaluation/__init__.py +1 -0
  33. actshield/evaluation/cases/__init__.py +1 -0
  34. actshield/evaluation/eval_suite.py +254 -0
  35. actshield/forensics/__init__.py +53 -0
  36. actshield/forensics/access_graph.py +216 -0
  37. actshield/forensics/authority_graph.py +186 -0
  38. actshield/forensics/delegation_graph.py +119 -0
  39. actshield/forensics/explanation.py +254 -0
  40. actshield/forensics/models.py +488 -0
  41. actshield/forensics/queries.py +367 -0
  42. actshield/forensics/serializers.py +68 -0
  43. actshield/forensics/service.py +310 -0
  44. actshield/forensics/snapshots.py +174 -0
  45. actshield/gates/__init__.py +13 -0
  46. actshield/gates/gate_models.py +46 -0
  47. actshield/gates/security_gate.py +191 -0
  48. actshield/gateway/__init__.py +13 -0
  49. actshield/gateway/http.py +191 -0
  50. actshield/gateway/mcp.py +292 -0
  51. actshield/incidents/__init__.py +25 -0
  52. actshield/incidents/incident.py +94 -0
  53. actshield/incidents/incident_engine.py +163 -0
  54. actshield/incidents/incident_rules.py +116 -0
  55. actshield/incidents/incident_state.py +58 -0
  56. actshield/integrations/__init__.py +24 -0
  57. actshield/integrations/ai_secura.py +169 -0
  58. actshield/integrations/ai_secura_analysis.py +236 -0
  59. actshield/integrations/apiris.py +122 -0
  60. actshield/integrations/few_shot.py +104 -0
  61. actshield/integrations/ollama_adapter.py +538 -0
  62. actshield/integrations/prompts/__init__.py +1 -0
  63. actshield/integrations/prompts/examples/__init__.py +1 -0
  64. actshield/integrations/security_packet.py +82 -0
  65. actshield/llm_config.py +89 -0
  66. actshield/offensive/__init__.py +95 -0
  67. actshield/offensive/adaptive/__init__.py +22 -0
  68. actshield/offensive/adaptive/adaptive_engine.py +165 -0
  69. actshield/offensive/adaptive/attack_selector.py +51 -0
  70. actshield/offensive/adaptive/boundary_search.py +99 -0
  71. actshield/offensive/adaptive/campaign_memory.py +123 -0
  72. actshield/offensive/adaptive/feedback.py +84 -0
  73. actshield/offensive/adaptive/mutation_planner.py +57 -0
  74. actshield/offensive/attack.py +78 -0
  75. actshield/offensive/campaign.py +219 -0
  76. actshield/offensive/corpus.py +155 -0
  77. actshield/offensive/engine.py +466 -0
  78. actshield/offensive/evaluator.py +116 -0
  79. actshield/offensive/evidence.py +63 -0
  80. actshield/offensive/generator.py +128 -0
  81. actshield/offensive/mutation.py +101 -0
  82. actshield/offensive/results.py +77 -0
  83. actshield/offensive/safety.py +80 -0
  84. actshield/offensive/strategies/__init__.py +22 -0
  85. actshield/offensive/strategies/authority_escalation.py +100 -0
  86. actshield/offensive/strategies/base.py +34 -0
  87. actshield/offensive/strategies/context_manipulation.py +100 -0
  88. actshield/offensive/strategies/data_exfiltration.py +100 -0
  89. actshield/offensive/strategies/delegation_attacks.py +100 -0
  90. actshield/offensive/strategies/mcp_attacks.py +100 -0
  91. actshield/offensive/strategies/prompt_injection.py +100 -0
  92. actshield/offensive/strategies/tool_poisoning.py +100 -0
  93. actshield/offensive/target.py +113 -0
  94. actshield/offensive/vulnerable_target.py +121 -0
  95. actshield/persistence/__init__.py +18 -0
  96. actshield/persistence/siem.py +102 -0
  97. actshield/persistence/storage.py +240 -0
  98. actshield/policy/__init__.py +12 -0
  99. actshield/policy/evaluator.py +294 -0
  100. actshield/policy/intent.py +113 -0
  101. actshield/policy/policy.py +48 -0
  102. actshield/posture/__init__.py +26 -0
  103. actshield/posture/posture_engine.py +186 -0
  104. actshield/posture/posture_models.py +152 -0
  105. actshield/posture/posture_rules.py +137 -0
  106. actshield/providers/__init__.py +32 -0
  107. actshield/providers/anthropic_provider.py +146 -0
  108. actshield/providers/base.py +160 -0
  109. actshield/providers/gemini_provider.py +133 -0
  110. actshield/providers/null_provider.py +40 -0
  111. actshield/providers/ollama_provider.py +135 -0
  112. actshield/providers/openai_provider.py +142 -0
  113. actshield/providers/registry.py +244 -0
  114. actshield/py.typed +0 -0
  115. actshield/response/__init__.py +14 -0
  116. actshield/response/response_actions.py +39 -0
  117. actshield/response/response_audit.py +32 -0
  118. actshield/response/response_engine.py +139 -0
  119. actshield/risk/models.py +104 -0
  120. actshield/serve.py +117 -0
  121. actshield/static/404.html +1 -0
  122. actshield/static/__next.__PAGE__.txt +24 -0
  123. actshield/static/__next._full.txt +20 -0
  124. actshield/static/__next._tree.txt +4 -0
  125. actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_buildManifest.js +11 -0
  126. actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_clientMiddlewareManifest.js +1 -0
  127. actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_ssgManifest.js +1 -0
  128. actshield/static/_next/static/chunks/09kny2eqjc2or.js +1 -0
  129. actshield/static/_next/static/chunks/0c1zba1u9whdp.js +1 -0
  130. actshield/static/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
  131. actshield/static/_next/static/chunks/0dbjjeg01x25o.js +1 -0
  132. actshield/static/_next/static/chunks/0duobs55ne238.js +1 -0
  133. actshield/static/_next/static/chunks/0iaz41l6068e4.js +1 -0
  134. actshield/static/_next/static/chunks/0mjhyv72x2idp.js +1 -0
  135. actshield/static/_next/static/chunks/0nelpqfu_ciq6.js +1 -0
  136. actshield/static/_next/static/chunks/0p1bci9ch797v.js +1 -0
  137. actshield/static/_next/static/chunks/0tld_ygho5tgm.js +1 -0
  138. actshield/static/_next/static/chunks/0w1-y7oni66j9.js +1 -0
  139. actshield/static/_next/static/chunks/10537zyl427zj.js +1 -0
  140. actshield/static/_next/static/chunks/11pc_jkl3aggn.js +1 -0
  141. actshield/static/_next/static/chunks/16k7nw0b3t8ys.js +1 -0
  142. actshield/static/_next/static/chunks/19mx3mg6lkumu.js +1 -0
  143. actshield/static/_next/static/chunks/1_8p47b-kxg2a.js +1 -0
  144. actshield/static/_next/static/chunks/1dszjozwfqegx.js +1 -0
  145. actshield/static/_next/static/chunks/1h43jcb90-m2r.js +22 -0
  146. actshield/static/_next/static/chunks/1ly04cvt_wh_j.js +1 -0
  147. actshield/static/_next/static/chunks/1odxrypuwuwp_.js +1 -0
  148. actshield/static/_next/static/chunks/1oes4c35qz5ku.js +1 -0
  149. actshield/static/_next/static/chunks/1ow883jl4ln-r.js +16 -0
  150. actshield/static/_next/static/chunks/1po7bna1as8tc.js +1 -0
  151. actshield/static/_next/static/chunks/1rsh0og8ifkzx.js +1 -0
  152. actshield/static/_next/static/chunks/1v0lwzv-859z_.js +1 -0
  153. actshield/static/_next/static/chunks/25iat2epwx25a.js +1 -0
  154. actshield/static/_next/static/chunks/25uvt4s2f39a4.js +1 -0
  155. actshield/static/_next/static/chunks/27t_qfc-3_lzs.js +1 -0
  156. actshield/static/_next/static/chunks/28bkmy8mez7gm.js +1 -0
  157. actshield/static/_next/static/chunks/2b6brmw_drw1p.js +1 -0
  158. actshield/static/_next/static/chunks/2fnhtxi4j6vge.js +1 -0
  159. actshield/static/_next/static/chunks/2p087eftxemg4.js +6 -0
  160. actshield/static/_next/static/chunks/2s8pao_z8pgtq.js +1 -0
  161. actshield/static/_next/static/chunks/2yj7ooc2c-zpg.js +1 -0
  162. actshield/static/_next/static/chunks/3-mrrr8udt5tk.js +1 -0
  163. actshield/static/_next/static/chunks/310vm2bl3xxpt.js +31 -0
  164. actshield/static/_next/static/chunks/35mvsv251jx1r.css +3 -0
  165. actshield/static/_next/static/chunks/370vf0oetlsx9.js +1 -0
  166. actshield/static/_next/static/chunks/3e-2m72tyo556.js +1 -0
  167. actshield/static/_next/static/chunks/3fntmmi971322.js +1 -0
  168. actshield/static/_next/static/chunks/3fzw-g0hycl2c.js +1 -0
  169. actshield/static/_next/static/chunks/3lopq3lhmcjxg.js +129 -0
  170. actshield/static/_next/static/chunks/3mpe2jejel0v2.css +1 -0
  171. actshield/static/_next/static/chunks/3t8o4f2lzr2sf.js +1 -0
  172. actshield/static/_next/static/chunks/3y-v1neyllne5.js +1 -0
  173. actshield/static/_next/static/chunks/43oiwy8mx6cs1.js +1 -0
  174. actshield/static/_next/static/chunks/turbopack-23wzuebcy_lxm.js +1 -0
  175. actshield/static/_next/static/media/1bffadaabf893a1e-s.3-6t-g6q0vh0a.woff2 +0 -0
  176. actshield/static/_next/static/media/2bbe8d2671613f1f-s.0k62hbripvv8p.woff2 +0 -0
  177. actshield/static/_next/static/media/2c55a0e60120577a-s.0-dom-5bn10r2.woff2 +0 -0
  178. actshield/static/_next/static/media/5476f68d60460930-s.2uwcyprjm3xu3.woff2 +0 -0
  179. actshield/static/_next/static/media/83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2 +0 -0
  180. actshield/static/_next/static/media/9c72aa0f40e4eef8-s.1y4-pdgsjb-pw.woff2 +0 -0
  181. actshield/static/_next/static/media/ad66f9afd8947f86-s.3lvt2whj97whp.woff2 +0 -0
  182. actshield/static/_next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  183. actshield/static/_not-found/__next._full.txt +17 -0
  184. actshield/static/_not-found/__next._not-found/__PAGE__.txt +23 -0
  185. actshield/static/_not-found/__next._tree.txt +3 -0
  186. actshield/static/_not-found.html +1 -0
  187. actshield/static/_not-found.txt +17 -0
  188. actshield/static/access/matrix/__next._full.txt +24 -0
  189. actshield/static/access/matrix/__next._tree.txt +4 -0
  190. actshield/static/access/matrix/__next.access/matrix/__PAGE__.txt +30 -0
  191. actshield/static/access/matrix.html +1 -0
  192. actshield/static/access/matrix.txt +24 -0
  193. actshield/static/activity/__next._full.txt +22 -0
  194. actshield/static/activity/__next._tree.txt +4 -0
  195. actshield/static/activity/__next.activity/__PAGE__.txt +27 -0
  196. actshield/static/activity.html +1 -0
  197. actshield/static/activity.txt +22 -0
  198. actshield/static/agents/__next._full.txt +22 -0
  199. actshield/static/agents/__next._tree.txt +4 -0
  200. actshield/static/agents/__next.agents/__PAGE__.txt +27 -0
  201. actshield/static/agents.html +1 -0
  202. actshield/static/agents.txt +22 -0
  203. actshield/static/ai-secura/__next._full.txt +22 -0
  204. actshield/static/ai-secura/__next._tree.txt +4 -0
  205. actshield/static/ai-secura/__next.ai-secura/__PAGE__.txt +27 -0
  206. actshield/static/ai-secura.html +1 -0
  207. actshield/static/ai-secura.txt +22 -0
  208. actshield/static/api/__next._full.txt +22 -0
  209. actshield/static/api/__next._tree.txt +4 -0
  210. actshield/static/api/__next.api/__PAGE__.txt +27 -0
  211. actshield/static/api.html +15 -0
  212. actshield/static/api.txt +22 -0
  213. actshield/static/apiris/__next._full.txt +22 -0
  214. actshield/static/apiris/__next._tree.txt +4 -0
  215. actshield/static/apiris/__next.apiris/__PAGE__.txt +27 -0
  216. actshield/static/apiris.html +1 -0
  217. actshield/static/apiris.txt +22 -0
  218. actshield/static/attack-graph/__next._full.txt +23 -0
  219. actshield/static/attack-graph/__next._tree.txt +5 -0
  220. actshield/static/attack-graph/__next.attack-graph/__PAGE__.txt +28 -0
  221. actshield/static/attack-graph.html +2 -0
  222. actshield/static/attack-graph.txt +23 -0
  223. actshield/static/campaigns/__next._full.txt +22 -0
  224. actshield/static/campaigns/__next._tree.txt +4 -0
  225. actshield/static/campaigns/__next.campaigns/__PAGE__.txt +27 -0
  226. actshield/static/campaigns.html +1 -0
  227. actshield/static/campaigns.txt +22 -0
  228. actshield/static/context/__next._full.txt +22 -0
  229. actshield/static/context/__next._tree.txt +4 -0
  230. actshield/static/context/__next.context/__PAGE__.txt +27 -0
  231. actshield/static/context.html +1 -0
  232. actshield/static/context.txt +22 -0
  233. actshield/static/dashboard/__next._full.txt +22 -0
  234. actshield/static/dashboard/__next._tree.txt +4 -0
  235. actshield/static/dashboard/__next.dashboard/__PAGE__.txt +27 -0
  236. actshield/static/dashboard.html +1 -0
  237. actshield/static/dashboard.txt +22 -0
  238. actshield/static/delegations/__next._full.txt +22 -0
  239. actshield/static/delegations/__next._tree.txt +4 -0
  240. actshield/static/delegations/__next.delegations/__PAGE__.txt +27 -0
  241. actshield/static/delegations.html +1 -0
  242. actshield/static/delegations.txt +22 -0
  243. actshield/static/demo/__next._full.txt +22 -0
  244. actshield/static/demo/__next._tree.txt +4 -0
  245. actshield/static/demo/__next.demo/__PAGE__.txt +27 -0
  246. actshield/static/demo.html +1 -0
  247. actshield/static/demo.txt +22 -0
  248. actshield/static/drift/__next._full.txt +22 -0
  249. actshield/static/drift/__next._tree.txt +4 -0
  250. actshield/static/drift/__next.drift/__PAGE__.txt +27 -0
  251. actshield/static/drift.html +1 -0
  252. actshield/static/drift.txt +22 -0
  253. actshield/static/favicon.ico +0 -0
  254. actshield/static/file.svg +1 -0
  255. actshield/static/forensics/__next._full.txt +22 -0
  256. actshield/static/forensics/__next._tree.txt +4 -0
  257. actshield/static/forensics/__next.forensics/__PAGE__.txt +27 -0
  258. actshield/static/forensics.html +1 -0
  259. actshield/static/forensics.txt +22 -0
  260. actshield/static/globe.svg +1 -0
  261. actshield/static/incidents/__next._full.txt +22 -0
  262. actshield/static/incidents/__next._tree.txt +4 -0
  263. actshield/static/incidents/__next.incidents/__PAGE__.txt +27 -0
  264. actshield/static/incidents.html +1 -0
  265. actshield/static/incidents.txt +22 -0
  266. actshield/static/index.html +3 -0
  267. actshield/static/index.txt +20 -0
  268. actshield/static/logo.png +0 -0
  269. actshield/static/metrics/__next._full.txt +22 -0
  270. actshield/static/metrics/__next._tree.txt +4 -0
  271. actshield/static/metrics/__next.metrics/__PAGE__.txt +27 -0
  272. actshield/static/metrics.html +1 -0
  273. actshield/static/metrics.txt +22 -0
  274. actshield/static/next.svg +1 -0
  275. actshield/static/offensive/__next._full.txt +22 -0
  276. actshield/static/offensive/__next._tree.txt +4 -0
  277. actshield/static/offensive/__next.offensive/__PAGE__.txt +27 -0
  278. actshield/static/offensive.html +1 -0
  279. actshield/static/offensive.txt +22 -0
  280. actshield/static/policies/__next._full.txt +22 -0
  281. actshield/static/policies/__next._tree.txt +4 -0
  282. actshield/static/policies/__next.policies/__PAGE__.txt +27 -0
  283. actshield/static/policies.html +1 -0
  284. actshield/static/policies.txt +22 -0
  285. actshield/static/posture/__next._full.txt +22 -0
  286. actshield/static/posture/__next._tree.txt +4 -0
  287. actshield/static/posture/__next.posture/__PAGE__.txt +27 -0
  288. actshield/static/posture.html +1 -0
  289. actshield/static/posture.txt +22 -0
  290. actshield/static/regressions/__next._full.txt +22 -0
  291. actshield/static/regressions/__next._tree.txt +4 -0
  292. actshield/static/regressions/__next.regressions/__PAGE__.txt +27 -0
  293. actshield/static/regressions.html +1 -0
  294. actshield/static/regressions.txt +22 -0
  295. actshield/static/reports/__next._full.txt +22 -0
  296. actshield/static/reports/__next._tree.txt +4 -0
  297. actshield/static/reports/__next.reports/__PAGE__.txt +27 -0
  298. actshield/static/reports.html +1 -0
  299. actshield/static/reports.txt +22 -0
  300. actshield/static/resources/__next._full.txt +22 -0
  301. actshield/static/resources/__next._tree.txt +4 -0
  302. actshield/static/resources/__next.resources/__PAGE__.txt +27 -0
  303. actshield/static/resources.html +1 -0
  304. actshield/static/resources.txt +22 -0
  305. actshield/static/security-gates/__next._full.txt +22 -0
  306. actshield/static/security-gates/__next._tree.txt +4 -0
  307. actshield/static/security-gates/__next.security-gates/__PAGE__.txt +27 -0
  308. actshield/static/security-gates.html +1 -0
  309. actshield/static/security-gates.txt +22 -0
  310. actshield/static/settings/__next._full.txt +22 -0
  311. actshield/static/settings/__next._tree.txt +4 -0
  312. actshield/static/settings/__next.settings/__PAGE__.txt +27 -0
  313. actshield/static/settings.html +1 -0
  314. actshield/static/settings.txt +22 -0
  315. actshield/static/tasks/__next._full.txt +22 -0
  316. actshield/static/tasks/__next._tree.txt +4 -0
  317. actshield/static/tasks/__next.tasks/__PAGE__.txt +27 -0
  318. actshield/static/tasks.html +1 -0
  319. actshield/static/tasks.txt +22 -0
  320. actshield/static/threats/__next._full.txt +22 -0
  321. actshield/static/threats/__next._tree.txt +4 -0
  322. actshield/static/threats/__next.threats/__PAGE__.txt +27 -0
  323. actshield/static/threats.html +1 -0
  324. actshield/static/threats.txt +22 -0
  325. actshield/static/tools/__next._full.txt +22 -0
  326. actshield/static/tools/__next._tree.txt +4 -0
  327. actshield/static/tools/__next.tools/__PAGE__.txt +27 -0
  328. actshield/static/tools.html +1 -0
  329. actshield/static/tools.txt +22 -0
  330. actshield/static/traces/__next._full.txt +22 -0
  331. actshield/static/traces/__next._tree.txt +4 -0
  332. actshield/static/traces/__next.traces/__PAGE__.txt +27 -0
  333. actshield/static/traces.html +1 -0
  334. actshield/static/traces.txt +22 -0
  335. actshield/static/vercel.svg +1 -0
  336. actshield/static/window.svg +1 -0
  337. actshield/tasks/__init__.py +6 -0
  338. actshield/tasks/task.py +143 -0
  339. actshield/threatmodel/__init__.py +70 -0
  340. actshield/threatmodel/actors.py +210 -0
  341. actshield/threatmodel/analyzer.py +131 -0
  342. actshield/threatmodel/assets.py +167 -0
  343. actshield/threatmodel/boundaries.py +165 -0
  344. actshield/threatmodel/exporters.py +49 -0
  345. actshield/threatmodel/mitigations.py +209 -0
  346. actshield/threatmodel/models.py +80 -0
  347. actshield/threatmodel/report.py +341 -0
  348. actshield/threatmodel/scenarios.py +212 -0
  349. actshield/threatmodel/scoring.py +66 -0
  350. actshield/threatmodel/threats.py +387 -0
  351. actshield/tools/__init__.py +20 -0
  352. actshield/tools/interceptor.py +256 -0
  353. actshield/tools/tool.py +71 -0
  354. actshield/tracing/__init__.py +38 -0
  355. actshield/tracing/correlation.py +173 -0
  356. actshield/tracing/events.py +75 -0
  357. actshield/tracing/tracer.py +305 -0
  358. actshield/watch.py +129 -0
  359. actshield-0.9.0.dist-info/METADATA +57 -0
  360. actshield-0.9.0.dist-info/RECORD +366 -0
  361. actshield-0.9.0.dist-info/WHEEL +5 -0
  362. actshield-0.9.0.dist-info/entry_points.txt +4 -0
  363. actshield-0.9.0.dist-info/top_level.txt +2 -0
  364. agentguard/__init__.py +39 -0
  365. agentguard/__main__.py +8 -0
  366. agentguard/py.typed +1 -0
@@ -0,0 +1,236 @@
1
+ """Rich AI Secura Analysis output schema (Pydantic v2).
2
+
3
+ This schema is the contract between the OllamaAISecuraAdapter and
4
+ the rest of actshield. The PolicyEvaluator reads structured fields
5
+ from this object but remains the sole enforcement authority.
6
+ """
7
+
8
+ from enum import Enum
9
+ from typing import Any, Dict, List, Optional
10
+ from pydantic import BaseModel, Field
11
+ import uuid
12
+
13
+
14
+ class ThreatSeverity(str, Enum):
15
+ """Severity classification for a detected or suspected threat."""
16
+ LOW = "LOW"
17
+ MEDIUM = "MEDIUM"
18
+ HIGH = "HIGH"
19
+ CRITICAL = "CRITICAL"
20
+ UNKNOWN = "UNKNOWN"
21
+
22
+
23
+ class IntentAlignment(str, Enum):
24
+ """Alignment of the requested action against the original user intent."""
25
+ ALIGNED = "ALIGNED"
26
+ POTENTIALLY_DRIFTING = "POTENTIALLY_DRIFTING"
27
+ VIOLATED = "VIOLATED"
28
+ UNKNOWN = "UNKNOWN"
29
+
30
+
31
+ class AIRecommendation(str, Enum):
32
+ """Non-binding recommendation from AI Secura to the PolicyEvaluator."""
33
+ ALLOW = "ALLOW"
34
+ MONITOR = "MONITOR"
35
+ HUMAN_APPROVAL = "HUMAN_APPROVAL"
36
+ BLOCK = "BLOCK"
37
+ UNKNOWN = "UNKNOWN"
38
+
39
+
40
+ class AttackTechnique(str, Enum):
41
+ """MITRE ATLAS / OWASP LLM Top-10 aligned attack technique labels."""
42
+ PROMPT_INJECTION = "prompt_injection"
43
+ INDIRECT_PROMPT_INJECTION = "indirect_prompt_injection"
44
+ JAILBREAK = "jailbreak"
45
+ SYSTEM_PROMPT_EXTRACTION = "system_prompt_extraction"
46
+ INSTRUCTION_HIJACKING = "instruction_hijacking"
47
+ SENSITIVE_INFORMATION_DISCLOSURE = "sensitive_information_disclosure"
48
+ DATA_EXFILTRATION = "data_exfiltration"
49
+ RAG_POISONING = "RAG_poisoning"
50
+ RAG_DATA_LEAKAGE = "RAG_data_leakage"
51
+ MALICIOUS_DOCUMENT = "malicious_document"
52
+ AGENT_HIJACKING = "agent_hijacking"
53
+ TOOL_ABUSE = "tool_abuse"
54
+ EXCESSIVE_AGENCY = "excessive_agency"
55
+ PRIVILEGE_ESCALATION = "privilege_escalation"
56
+ MCP_SECURITY = "MCP_security"
57
+ TOOL_POISONING = "tool_poisoning"
58
+ MALICIOUS_MCP_SERVER = "malicious_MCP_server"
59
+ AI_API_SECURITY = "AI_API_security"
60
+ AUTHENTICATION_FAILURE = "authentication_failure"
61
+ AUTHORIZATION_FAILURE = "authorization_failure"
62
+ AI_APPLICATION_VULNERABILITY = "AI_application_vulnerability"
63
+ ADVERSARIAL_ATTACK = "adversarial_attack"
64
+ CONTEXT_MANIPULATION = "context_manipulation"
65
+ AI_SUPPLY_CHAIN = "AI_supply_chain"
66
+ MODEL_DEPENDENCY_VULNERABILITY = "model_dependency_vulnerability"
67
+ AI_SECURITY_MONITORING = "AI_security_monitoring"
68
+ AI_SECURITY_EVALUATION = "AI_security_evaluation"
69
+ LLM_RELIABILITY_SECURITY = "LLM_reliability_security"
70
+ NONE = "none"
71
+ UNKNOWN = "unknown"
72
+
73
+
74
+ class EvidenceTriad(BaseModel):
75
+ """Strict separation of observed facts, inferred conclusions, and unknowns.
76
+
77
+ AI Secura MUST NOT fabricate CVEs, CWE IDs, MITRE IDs, logs, or credentials.
78
+ If evidence is absent, the field belongs in 'unknown'.
79
+ """
80
+ observed: List[str] = Field(
81
+ default_factory=list,
82
+ description="Facts directly present in the ActShield evidence packet.",
83
+ )
84
+ inferred: List[str] = Field(
85
+ default_factory=list,
86
+ description="Reasonable conclusions derived from the observed evidence.",
87
+ )
88
+ unknown: List[str] = Field(
89
+ default_factory=list,
90
+ description="Aspects that cannot be established from the available evidence.",
91
+ )
92
+
93
+
94
+ class AuthorityAnalysis(BaseModel):
95
+ """AI Secura reasoning about delegation authority — for explanation only, not enforcement."""
96
+ acting_agent: Optional[str] = None
97
+ delegated_capabilities: List[str] = Field(default_factory=list)
98
+ requested_capability: Optional[str] = None
99
+ required_capability: Optional[str] = None
100
+ delegation_chain: List[str] = Field(default_factory=list)
101
+ authority_violated: bool = False
102
+ reasoning: str = ""
103
+
104
+
105
+ class TaintAnalysis(BaseModel):
106
+ """AI Secura reasoning about context taint lineage."""
107
+ context_id: Optional[str] = None
108
+ source: Optional[str] = None
109
+ trust_level: Optional[str] = None
110
+ taint_state: Optional[str] = None
111
+ origin_agent: Optional[str] = None
112
+ propagation_chain: List[str] = Field(default_factory=list)
113
+ is_tainted: bool = False
114
+ reasoning: str = ""
115
+
116
+
117
+ class AISecuraAnalysis(BaseModel):
118
+ """Complete structured output from AI Secura reasoning engine.
119
+
120
+ IMPORTANT: This is *reasoning*, not enforcement.
121
+ The ActShield PolicyEvaluator is the sole enforcement authority.
122
+ ai_recommendation here is advisory only.
123
+ """
124
+ analysis_id: str = Field(default_factory=lambda: f"aisec35_{uuid.uuid4().hex[:12]}")
125
+
126
+ # --- Threat Classification ---
127
+ threat_type: str = Field(
128
+ default="unknown",
129
+ description="Primary threat type from the AI Secura security taxonomy.",
130
+ )
131
+ attack_category: str = Field(
132
+ default="unknown",
133
+ description="High-level attack category (e.g. 'injection', 'escalation', 'exfiltration').",
134
+ )
135
+ attack_technique: AttackTechnique = Field(
136
+ default=AttackTechnique.UNKNOWN,
137
+ description="Specific attack technique from the AI Secura taxonomy.",
138
+ )
139
+ severity: ThreatSeverity = Field(
140
+ default=ThreatSeverity.UNKNOWN,
141
+ description="Assessed threat severity.",
142
+ )
143
+ confidence: float = Field(
144
+ default=0.0,
145
+ ge=0.0,
146
+ le=1.0,
147
+ description="Confidence in the threat assessment (0.0 = uncertain, 1.0 = certain).",
148
+ )
149
+
150
+ # --- Evidence Model ---
151
+ evidence: EvidenceTriad = Field(default_factory=EvidenceTriad)
152
+ observed_indicators: List[str] = Field(
153
+ default_factory=list,
154
+ description="Specific observable indicators extracted from the security packet.",
155
+ )
156
+
157
+ # --- Alignment and Authority ---
158
+ intent_alignment: IntentAlignment = Field(
159
+ default=IntentAlignment.UNKNOWN,
160
+ description="Alignment of the requested action to original user intent.",
161
+ )
162
+ authority_analysis: AuthorityAnalysis = Field(default_factory=AuthorityAnalysis)
163
+ taint_analysis: TaintAnalysis = Field(default_factory=TaintAnalysis)
164
+
165
+ # --- MITRE References (only when directly supported by evidence) ---
166
+ mitre_attack_id: Optional[str] = Field(
167
+ default=None,
168
+ description="MITRE ATT&CK ID — only set when directly supported by observed evidence.",
169
+ )
170
+ mitre_atlas_id: Optional[str] = Field(
171
+ default=None,
172
+ description="MITRE ATLAS ID — only set when directly supported by observed evidence.",
173
+ )
174
+
175
+ # --- Analysis Narrative ---
176
+ analysis: str = Field(
177
+ default="",
178
+ description="Comprehensive reasoning narrative from AI Secura.",
179
+ )
180
+ impact: str = Field(
181
+ default="",
182
+ description="Potential impact if the threat is not mitigated.",
183
+ )
184
+ influencing_context: str = Field(
185
+ default="",
186
+ description="Which context data items most influenced this analysis.",
187
+ )
188
+
189
+ # --- Remediation ---
190
+ recommended_actions: List[str] = Field(
191
+ default_factory=list,
192
+ description="Security recommendations (advisory only).",
193
+ )
194
+ containment: List[str] = Field(
195
+ default_factory=list,
196
+ description="Immediate containment steps.",
197
+ )
198
+ remediation: List[str] = Field(
199
+ default_factory=list,
200
+ description="Longer-term remediation measures.",
201
+ )
202
+ additional_information_required: List[str] = Field(
203
+ default_factory=list,
204
+ description="Additional context or evidence needed for a definitive assessment.",
205
+ )
206
+
207
+ # --- Advisory Recommendation ---
208
+ ai_recommendation: AIRecommendation = Field(
209
+ default=AIRecommendation.UNKNOWN,
210
+ description=(
211
+ "NON-BINDING advisory recommendation to PolicyEvaluator. "
212
+ "PolicyEvaluator may override this at any time."
213
+ ),
214
+ )
215
+
216
+ # --- Provider Metadata ---
217
+ provider: str = Field(default="local", description="Provider: 'ollama' or 'local'.")
218
+ model: str = Field(default="local-heuristic")
219
+ latency_ms: float = Field(default=0.0, description="Analysis latency in milliseconds.")
220
+ ai_unavailable: bool = Field(
221
+ default=False,
222
+ description=(
223
+ "True when Ollama is unreachable, timed out, or returned irrecoverably malformed output. "
224
+ "When True, ActShield deterministic policy continues as sole enforcer."
225
+ ),
226
+ )
227
+ json_repaired: bool = Field(
228
+ default=False,
229
+ description="True if the model output required one JSON repair attempt.",
230
+ )
231
+ raw_response: Optional[str] = Field(
232
+ default=None,
233
+ description="Raw model response string (for debugging). Redacted in production events.",
234
+ )
235
+
236
+
@@ -0,0 +1,122 @@
1
+ """APIRIS API decision-intelligence and tool security interface."""
2
+
3
+ from typing import Any, Callable, Dict, List, Optional, Protocol, runtime_checkable
4
+ import uuid
5
+ from pydantic import BaseModel, Field
6
+
7
+ from actshield.risk.models import RiskLevel, RiskSignal
8
+ from actshield.tools.tool import ToolRequest
9
+
10
+
11
+ class APIAnalysis(BaseModel):
12
+ """API & tool intelligence analysis returned by APIRIS."""
13
+ analysis_id: str
14
+ tool_id: str
15
+ tool_name: str
16
+ risk_score: float = Field(default=0.0, ge=0.0, le=1.0)
17
+ anomaly_score: float = Field(default=0.0, ge=0.0, le=1.0)
18
+ cve_indicators: List[str] = Field(default_factory=list)
19
+ vendor_reputation: str = "TRUSTED"
20
+ latency_ms_estimate: float = 50.0
21
+ cost_estimate_usd: float = 0.0
22
+ recommended_action: str = "ALLOW"
23
+ signals: List[RiskSignal] = Field(default_factory=list)
24
+ metadata: Dict[str, Any] = Field(default_factory=dict)
25
+
26
+
27
+ @runtime_checkable
28
+ class APIIntelligence(Protocol):
29
+ """Protocol for APIRIS API intelligence engine."""
30
+
31
+ def analyze(self, request: ToolRequest) -> APIAnalysis:
32
+ """Analyze tool request metadata, endpoint parameters, and reputation."""
33
+ ...
34
+
35
+
36
+ class APIRISClient(APIIntelligence):
37
+ """APIRIS API decision intelligence client.
38
+
39
+ Inspects endpoint reputation, argument injection signatures, rate anomalies,
40
+ and returns recommendations (ALLOW, MONITOR, HUMAN_APPROVAL, BLOCK).
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ api_endpoint: Optional[str] = None,
46
+ api_key: Optional[str] = None,
47
+ custom_engine: Optional[Callable[[ToolRequest], APIAnalysis]] = None,
48
+ ) -> None:
49
+ self.api_endpoint = api_endpoint or "https://apiris.internal/v1/analyze"
50
+ self.api_key = api_key or "apiris-live-token"
51
+ self.custom_engine = custom_engine
52
+
53
+ def analyze(self, request: ToolRequest) -> APIAnalysis:
54
+ """Perform APIRIS decision intelligence analysis on the requested tool invocation."""
55
+ if self.custom_engine:
56
+ return self.custom_engine(request)
57
+
58
+ analysis_id = f"apiris_{uuid.uuid4().hex[:12]}"
59
+ signals: List[RiskSignal] = []
60
+ cves: List[str] = []
61
+ risk_score = 0.05
62
+ anomaly_score = 0.02
63
+ rec_action = "ALLOW"
64
+
65
+ args_str = str(request.arguments).lower()
66
+ tool_name_lower = (request.tool_name or "").lower()
67
+
68
+ # 1. Command injection pattern checks
69
+ if any(pat in args_str for pat in ("rm -rf", "drop table", "--exec", "cmd.exe", "eval(", "; cat /etc/passwd", "bash -i")):
70
+ risk_score = 0.95
71
+ anomaly_score = 0.98
72
+ rec_action = "BLOCK"
73
+ signals.append(
74
+ RiskSignal(
75
+ source="apiris",
76
+ risk_level=RiskLevel.CRITICAL,
77
+ score=0.95,
78
+ indicator="APIRIS_COMMAND_INJECTION_PATTERN",
79
+ details={"arguments": request.arguments},
80
+ )
81
+ )
82
+
83
+ # 2. SSRF / Untrusted domain check
84
+ if any(pat in args_str for pat in ("169.254.169.254", "localhost:8080", "127.0.0.1", "evil-exfil.com")):
85
+ risk_score = 0.90
86
+ rec_action = "BLOCK"
87
+ signals.append(
88
+ RiskSignal(
89
+ source="apiris",
90
+ risk_level=RiskLevel.CRITICAL,
91
+ score=0.90,
92
+ indicator="APIRIS_SSRF_OR_UNTRUSTED_DESTINATION",
93
+ details={"arguments": request.arguments},
94
+ )
95
+ )
96
+
97
+ # 3. High sensitivity / Financial tool heuristic
98
+ if "customer_db" in tool_name_lower or "pii" in tool_name_lower:
99
+ risk_score = max(risk_score, 0.40)
100
+ vendor_rep = "INTERNAL_RESTRICTED"
101
+ else:
102
+ vendor_rep = "TRUSTED"
103
+
104
+ return APIAnalysis(
105
+ analysis_id=analysis_id,
106
+ tool_id=request.tool_id,
107
+ tool_name=request.tool_name,
108
+ risk_score=risk_score,
109
+ anomaly_score=anomaly_score,
110
+ cve_indicators=cves,
111
+ vendor_reputation=vendor_rep,
112
+ latency_ms_estimate=45.0,
113
+ recommended_action=rec_action,
114
+ signals=signals,
115
+ metadata={"evaluated_by": "APIRIS-v3.0"},
116
+ )
117
+
118
+
119
+ class LocalAPIRISAdapter(APIRISClient):
120
+ """Backward-compatible alias for local execution."""
121
+ pass
122
+
@@ -0,0 +1,104 @@
1
+ """Deterministic few-shot example selector for AI Secura prompts.
2
+
3
+ Selects up to MAX_EXAMPLES relevant examples based on:
4
+ - Protocol (mcp, http, rag, tool, api)
5
+ - Taint state (TAINTED, CLEAN)
6
+ - Resource sensitivity (CRITICAL, HIGH, MEDIUM, LOW)
7
+ - Attack category hint
8
+
9
+ No vector database. Pure rule-based selection from the examples directory.
10
+ """
11
+
12
+ import json
13
+ import pathlib
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ _EXAMPLES_DIR = pathlib.Path(__file__).parent / "prompts" / "examples"
17
+ MAX_EXAMPLES = 4
18
+
19
+
20
+ def _load_example(path: pathlib.Path) -> Optional[Dict[str, Any]]:
21
+ try:
22
+ with open(path, encoding="utf-8") as f:
23
+ return json.load(f)
24
+ except Exception:
25
+ return None
26
+
27
+
28
+ def _score_example(ex: Dict[str, Any], context: Dict[str, Any]) -> int:
29
+ """Return relevance score (higher = more relevant)."""
30
+ score = 0
31
+ ex_tags = set(ex.get("tags", []))
32
+
33
+ # Protocol match
34
+ provenance = context.get("context_provenance", [])
35
+ src = " ".join(str(p) for p in provenance).lower()
36
+ tool_name = str(context.get("tool", {}).get("name", "")).lower()
37
+ if "mcp" in src and "mcp" in ex_tags:
38
+ score += 3
39
+ if "http" in src or "api" in src:
40
+ if "http" in ex_tags or "api" in ex_tags:
41
+ score += 3
42
+ if "rag" in src and "rag" in ex_tags:
43
+ score += 3
44
+
45
+ # Taint state match
46
+ taint_states = context.get("taint_states", [])
47
+ has_taint = any(t in ("TAINTED", "UNTRUSTED") for t in taint_states)
48
+ if has_taint and "tainted" in ex_tags:
49
+ score += 2
50
+ if not has_taint and "clean" in ex_tags:
51
+ score += 2
52
+
53
+ # Sensitivity match
54
+ sensitivity = str(context.get("resource", {}).get("sensitivity", "")).upper()
55
+ if sensitivity in ("CRITICAL", "HIGH") and "critical_sink" in ex_tags:
56
+ score += 2
57
+ if sensitivity in ("LOW", "MEDIUM") and "low_risk" in ex_tags:
58
+ score += 1
59
+
60
+ # Attack category match
61
+ ex_threat = ex.get("expected_output", {}).get("attack_technique", "")
62
+ det_policy = context.get("deterministic_policy", {})
63
+ reason_codes = " ".join(det_policy.get("reason_codes", []))
64
+ if "injection" in reason_codes.lower() and "injection" in ex_threat:
65
+ score += 2
66
+ if "authority" in reason_codes.lower() and "escalation" in ex_threat:
67
+ score += 2
68
+
69
+ return score
70
+
71
+
72
+ def select_few_shot_examples(context: Dict[str, Any]) -> List[Dict[str, Any]]:
73
+ """Return up to MAX_EXAMPLES ordered by relevance to context."""
74
+ if not _EXAMPLES_DIR.exists():
75
+ return []
76
+
77
+ examples = []
78
+ for path in sorted(_EXAMPLES_DIR.glob("*.json")):
79
+ ex = _load_example(path)
80
+ if ex:
81
+ ex["_score"] = _score_example(ex, context)
82
+ examples.append(ex)
83
+
84
+ examples.sort(key=lambda e: e["_score"], reverse=True)
85
+ return [
86
+ {k: v for k, v in ex.items() if k != "_score"}
87
+ for ex in examples[:MAX_EXAMPLES]
88
+ ]
89
+
90
+
91
+ def format_examples_for_prompt(examples: List[Dict[str, Any]]) -> str:
92
+ """Format selected examples as a few-shot block for the system prompt."""
93
+ if not examples:
94
+ return ""
95
+ lines = ["\n\n### FEW-SHOT EXAMPLES\n"]
96
+ for i, ex in enumerate(examples, 1):
97
+ lines.append(f"#### Example {i}: {ex.get('description', '')}\n")
98
+ lines.append("Input:\n```json")
99
+ lines.append(json.dumps(ex.get("input", {}), indent=2))
100
+ lines.append("```\n")
101
+ lines.append("Expected Output:\n```json")
102
+ lines.append(json.dumps(ex.get("expected_output", {}), indent=2))
103
+ lines.append("```\n")
104
+ return "\n".join(lines)