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,25 @@
1
+ """ActShield Incidents Engine Package (Phase 9)."""
2
+
3
+ from actshield.incidents.incident import IncidentTimelineEntry, SecurityIncident
4
+ from actshield.incidents.incident_engine import IncidentEngine, IncidentTimelineBuilder
5
+ from actshield.incidents.incident_rules import IncidentCreationRule
6
+ from actshield.incidents.incident_state import (
7
+ ALLOWED_TRANSITIONS,
8
+ IncidentSeverity,
9
+ IncidentState,
10
+ IncidentStateMachine,
11
+ )
12
+
13
+ __all__ = [
14
+ "IncidentTimelineEntry",
15
+ "SecurityIncident",
16
+ "IncidentEngine",
17
+ "IncidentTimelineBuilder",
18
+ "IncidentCreationRule",
19
+ "ALLOWED_TRANSITIONS",
20
+ "IncidentSeverity",
21
+ "IncidentState",
22
+ "IncidentStateMachine",
23
+ ]
24
+
25
+
@@ -0,0 +1,94 @@
1
+ """Security Incident Model for ActShield Phase 9."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import uuid
6
+ from datetime import datetime, timezone
7
+ from typing import Any, Dict, List, Optional
8
+ from pydantic import BaseModel, Field
9
+
10
+ from actshield.incidents.incident_state import IncidentSeverity, IncidentState
11
+ from actshield.tracing.correlation import generate_id
12
+
13
+
14
+ class IncidentTimelineEntry(BaseModel):
15
+ """A chronological causal entry within an incident storyline."""
16
+ timestamp: str = Field(..., description="ISO timestamp or formatted time")
17
+ stage: str = Field(..., description="Stage e.g. '01. INTENT', '03. CONTEXT', '07. ENFORCE'")
18
+ agent_id: Optional[str] = None
19
+ agent_name: Optional[str] = None
20
+ action: str = ""
21
+ detail: str = ""
22
+ taint_state: str = "CLEAN"
23
+ decision: Optional[str] = None
24
+ event_id: Optional[str] = None
25
+ actor_name: Optional[str] = None
26
+ incident_state: Optional[IncidentState] = None
27
+
28
+ @property
29
+ def actor(self) -> str:
30
+ return self.actor_name or self.agent_name or self.agent_id or "system"
31
+
32
+ @property
33
+ def reason(self) -> str:
34
+ return self.detail or self.action
35
+
36
+ @property
37
+ def state(self) -> IncidentState:
38
+ return self.incident_state or IncidentState.DETECTED
39
+
40
+
41
+ class SecurityIncident(BaseModel):
42
+ """Complete causal security incident record."""
43
+ incident_id: str = Field(default_factory=lambda: generate_id("inc"))
44
+ title: str = Field(..., description="Summary title of the incident")
45
+ severity: IncidentSeverity = Field(default=IncidentSeverity.MEDIUM)
46
+ state: IncidentState = Field(default=IncidentState.DETECTED)
47
+ attack_type: str = Field(default="policy_violation", description="Classification e.g. 'indirect_prompt_injection', 'authority_escape'")
48
+ root_event_id: Optional[str] = None
49
+ trace_id: str = Field(default_factory=lambda: generate_id("trc"), description="Causal trace ID linking all events")
50
+
51
+ # Affected security entities
52
+ affected_agents: List[str] = Field(default_factory=list)
53
+ affected_tasks: List[str] = Field(default_factory=list)
54
+ affected_resources: List[str] = Field(default_factory=list)
55
+
56
+ # Causal context & taint state
57
+ context_source: Optional[str] = None
58
+ trust_state: str = "UNKNOWN"
59
+ taint_state: str = "CLEAN"
60
+ authority_violated: bool = False
61
+
62
+ # Decisions & runtime evidence
63
+ policy_verdict: str = "BLOCK"
64
+ sensitive_operations_attempted: int = 0
65
+ sensitive_operations_executed: int = 0 # CRITICAL: 0 proves prevention held
66
+
67
+ # Intelligence enrichments
68
+ ai_secura_summary: Optional[str] = None
69
+ apiris_signals: List[str] = Field(default_factory=list)
70
+
71
+ # Lifecycle & timeline
72
+ timeline: List[IncidentTimelineEntry] = Field(default_factory=list)
73
+ remediation_notes: Optional[str] = None
74
+ regression_id: Optional[str] = None
75
+ secured_replay_verified: bool = False
76
+
77
+ created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
78
+ updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
79
+ metadata: Dict[str, Any] = Field(default_factory=dict)
80
+
81
+ @property
82
+ def target_agent_id(self) -> str:
83
+ return self.affected_agents[0] if self.affected_agents else ""
84
+
85
+ @property
86
+ def tool_name(self) -> str:
87
+ return self.affected_resources[0] if self.affected_resources else ""
88
+
89
+ @property
90
+ def root_cause(self) -> str:
91
+ return self.ai_secura_summary or self.remediation_notes or "Security boundary violation"
92
+
93
+
94
+
@@ -0,0 +1,163 @@
1
+ """Incident timeline builder and incident engine orchestrator for ActShield Phase 9."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime, timezone
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from actshield.incidents.incident import IncidentTimelineEntry, SecurityIncident
9
+ from actshield.incidents.incident_rules import IncidentCreationRule
10
+ from actshield.incidents.incident_state import (
11
+ IncidentSeverity,
12
+ IncidentState,
13
+ IncidentStateMachine,
14
+ )
15
+ from actshield.tracing.correlation import generate_id
16
+
17
+
18
+ class IncidentTimelineBuilder:
19
+ """Builds a structured causal storyline from correlated events."""
20
+
21
+ @staticmethod
22
+ def from_events(events: List[Dict[str, Any]]) -> List[IncidentTimelineEntry]:
23
+ timeline: List[IncidentTimelineEntry] = []
24
+ for i, evt in enumerate(events):
25
+ stage = f"0{i+1}. {evt.get('stage_name', evt.get('event_type', 'EVENT'))}"
26
+ timeline.append(IncidentTimelineEntry(
27
+ timestamp=str(evt.get("timestamp", datetime.now(timezone.utc).isoformat())),
28
+ stage=stage,
29
+ agent_id=evt.get("agent_id"),
30
+ agent_name=evt.get("agent_name"),
31
+ action=evt.get("action") or f"Called {evt.get('tool', 'tool')}",
32
+ detail=evt.get("detail") or evt.get("reason") or "Event executed in trace",
33
+ taint_state=evt.get("taint", "CLEAN"),
34
+ decision=evt.get("decision"),
35
+ event_id=evt.get("event_id"),
36
+ ))
37
+ return timeline
38
+
39
+
40
+ class IncidentEngine:
41
+ """Manages continuous security incident generation, correlation, and lifecycle state."""
42
+
43
+ def __init__(self, guard: Optional[Any] = None) -> None:
44
+ self.guard = guard
45
+ self.incidents: Dict[str, SecurityIncident] = {}
46
+
47
+ def record_incident(self, incident: SecurityIncident) -> SecurityIncident:
48
+ """Explicitly register a SecurityIncident."""
49
+ self.incidents[incident.incident_id] = incident
50
+ return incident
51
+
52
+ def process_event(self, event: Dict[str, Any], related_events: Optional[List[Dict[str, Any]]] = None) -> Optional[SecurityIncident]:
53
+ """Evaluate an event for incident creation and causal linking."""
54
+ should_create, title, severity, attack_type = IncidentCreationRule.evaluate(event)
55
+ if not should_create:
56
+ return None
57
+
58
+ trace_id = event.get("trace_id") or generate_id("trc")
59
+
60
+ # Check if active incident already exists for this trace
61
+ for existing in self.incidents.values():
62
+ if existing.trace_id == trace_id and existing.state not in (IncidentState.CLOSED, IncidentState.VALIDATED):
63
+ # Update existing incident
64
+ if event.get("agent_id") and event["agent_id"] not in existing.affected_agents:
65
+ existing.affected_agents.append(event["agent_id"])
66
+ if event.get("resource") and event["resource"] not in existing.affected_resources:
67
+ existing.affected_resources.append(event["resource"])
68
+ existing.updated_at = datetime.now(timezone.utc)
69
+ return existing
70
+
71
+ timeline_events = related_events or [event]
72
+ timeline = IncidentTimelineBuilder.from_events(timeline_events)
73
+
74
+ incident = SecurityIncident(
75
+ title=title or "Security Boundary Incident",
76
+ severity=severity,
77
+ state=IncidentState.DETECTED,
78
+ attack_type=attack_type or "unknown_threat",
79
+ root_event_id=event.get("event_id"),
80
+ trace_id=trace_id,
81
+ affected_agents=[event["agent_id"]] if event.get("agent_id") else [],
82
+ affected_tasks=[event["task_id"]] if event.get("task_id") else [],
83
+ affected_resources=[event["resource"]] if event.get("resource") else ([event["tool"]] if event.get("tool") else []),
84
+ context_source=event.get("context_source"),
85
+ trust_state=event.get("trust_level", "UNKNOWN"),
86
+ taint_state=event.get("taint", "CLEAN"),
87
+ authority_violated=bool(event.get("authority_violation", False)),
88
+ policy_verdict=event.get("decision", "BLOCK"),
89
+ sensitive_operations_attempted=1,
90
+ sensitive_operations_executed=1 if event.get("decision") == "ALLOW" and event.get("taint") == "TAINTED" else 0,
91
+ ai_secura_summary=event.get("ai_secura_summary") or event.get("threat_reason"),
92
+ timeline=timeline,
93
+ )
94
+
95
+ self.incidents[incident.incident_id] = incident
96
+ return incident
97
+
98
+ def transition_state(self, incident_id: str, target_state: IncidentState, remediation_notes: Optional[str] = None) -> SecurityIncident:
99
+ """Deterministically transition an incident's lifecycle state."""
100
+ if incident_id not in self.incidents:
101
+ raise KeyError(f"Incident with ID '{incident_id}' not found.")
102
+
103
+ incident = self.incidents[incident_id]
104
+ IncidentStateMachine.validate_transition(incident.state, target_state)
105
+ incident.state = target_state
106
+ if remediation_notes:
107
+ incident.remediation_notes = remediation_notes
108
+ incident.updated_at = datetime.now(timezone.utc)
109
+ return incident
110
+
111
+ def transition_incident_state(
112
+ self,
113
+ incident_id: str,
114
+ to_state: IncidentState,
115
+ actor: str = "system",
116
+ reason: str = "",
117
+ ) -> Optional[SecurityIncident]:
118
+ """Transition incident state and append a timeline entry."""
119
+ if incident_id not in self.incidents:
120
+ return None
121
+
122
+ incident = self.incidents[incident_id]
123
+ IncidentStateMachine.validate_transition(incident.state, to_state)
124
+ incident.state = to_state
125
+ if reason:
126
+ incident.remediation_notes = reason
127
+
128
+ entry = IncidentTimelineEntry(
129
+ timestamp=datetime.now(timezone.utc).isoformat(),
130
+ stage=f"Stage {to_state.value}",
131
+ agent_id=incident.target_agent_id,
132
+ action=f"Transitioned to {to_state.value}",
133
+ detail=reason or f"State changed to {to_state.value}",
134
+ actor_name=actor,
135
+ incident_state=to_state,
136
+ )
137
+ incident.timeline.append(entry)
138
+ incident.updated_at = datetime.now(timezone.utc)
139
+ return incident
140
+
141
+ def link_regression(self, incident_id: str, regression_id: str, secured_replay_passed: bool = True) -> SecurityIncident:
142
+ """Attach verified regression fixture to incident and advance state."""
143
+ if incident_id not in self.incidents:
144
+ raise KeyError(f"Incident with ID '{incident_id}' not found.")
145
+
146
+ incident = self.incidents[incident_id]
147
+ incident.regression_id = regression_id
148
+ incident.secured_replay_verified = secured_replay_passed
149
+ if secured_replay_passed:
150
+ incident.state = IncidentState.VALIDATED
151
+ incident.updated_at = datetime.now(timezone.utc)
152
+ return incident
153
+
154
+ def get_incident(self, incident_id: str) -> Optional[SecurityIncident]:
155
+ return self.incidents.get(incident_id)
156
+
157
+ def list_incidents(self, state: Optional[IncidentState] = None) -> List[SecurityIncident]:
158
+ if state:
159
+ return [inc for inc in self.incidents.values() if inc.state == state]
160
+ return list(self.incidents.values())
161
+
162
+
163
+
@@ -0,0 +1,116 @@
1
+ """Deterministic rules for automatic incident creation in ActShield Phase 9."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict, Optional, Tuple
6
+ from actshield.incidents.incident_state import IncidentSeverity
7
+
8
+
9
+ class IncidentCreationRule:
10
+ """Evaluates runtime security event signals to determine if an incident must be generated."""
11
+
12
+ @staticmethod
13
+ def evaluate(event: Dict[str, Any]) -> Tuple[bool, Optional[str], IncidentSeverity, Optional[str]]:
14
+ """
15
+ Evaluate an event dictionary or security payload.
16
+ Returns: (should_create_incident, title, severity, attack_type)
17
+ """
18
+ decision = str(event.get("decision", "")).upper()
19
+ taint = str(event.get("taint", "")).upper()
20
+ res_sens = str(event.get("resource_sensitivity", "")).upper()
21
+ auth_violation = bool(event.get("authority_violation", False))
22
+ bypass_detected = bool(event.get("bypass_detected", False))
23
+ attack_type = event.get("attack_type") or event.get("threat_type") or "policy_violation"
24
+
25
+ # Rule 1: CRITICAL INVARIANT — Actual unauthorized execution
26
+ if decision == "ALLOW" and (taint == "TAINTED" or auth_violation) and res_sens in ("HIGH", "CRITICAL"):
27
+ return (
28
+ True,
29
+ f"CRITICAL: Actual Unauthorized Execution on {event.get('resource', event.get('tool', 'Sensitive Resource'))}",
30
+ IncidentSeverity.CRITICAL,
31
+ "unauthorized_execution_bypass",
32
+ )
33
+
34
+ # Rule 2: Offensive Bypass Discovered
35
+ if bypass_detected:
36
+ return (
37
+ True,
38
+ f"Offensive Validation Bypass Detected: {event.get('variant_name', attack_type)}",
39
+ IncidentSeverity.HIGH,
40
+ "offensive_validation_bypass",
41
+ )
42
+
43
+ # Rule 3: Tainted context attempting high/critical resource
44
+ if taint in ("TAINTED", "UNTRUSTED") and (res_sens in ("HIGH", "CRITICAL") or decision == "BLOCK"):
45
+ return (
46
+ True,
47
+ f"Tainted Context Propagation to Sensitive Target: {event.get('tool', 'tool')}",
48
+ IncidentSeverity.HIGH,
49
+ "indirect_prompt_injection" if "injection" in attack_type.lower() else "tainted_data_propagation",
50
+ )
51
+
52
+ # Rule 4: Authority Boundary Escape Attempt
53
+ if auth_violation or "authority" in str(event.get("reason", "")).lower():
54
+ return (
55
+ True,
56
+ f"Delegated Authority Boundary Violation: {event.get('agent_id', 'Agent')} attempted {event.get('tool', 'action')}",
57
+ IncidentSeverity.MEDIUM,
58
+ "authority_escalation",
59
+ )
60
+
61
+ # Rule 5: Blocked Privileged Tool Execution
62
+ if decision == "BLOCK" and res_sens in ("HIGH", "CRITICAL"):
63
+ return (
64
+ True,
65
+ f"Blocked High-Risk Tool Request on {event.get('tool', 'tool')}",
66
+ IncidentSeverity.MEDIUM,
67
+ attack_type,
68
+ )
69
+
70
+ return (False, None, IncidentSeverity.LOW, None)
71
+
72
+ @staticmethod
73
+ def evaluate_threat_event(
74
+ threat_type: str,
75
+ severity: IncidentSeverity,
76
+ title: str,
77
+ description: str,
78
+ source_context_id: Optional[str] = None,
79
+ target_agent_id: Optional[str] = None,
80
+ tool_name: Optional[str] = None,
81
+ root_cause: Optional[str] = None,
82
+ evidence_event_ids: Optional[List[str]] = None,
83
+ ) -> Any:
84
+ """Construct a SecurityIncident directly from threat analysis signals."""
85
+ from actshield.incidents.incident import IncidentTimelineEntry, SecurityIncident
86
+ from actshield.incidents.incident_state import IncidentState
87
+ from datetime import datetime, timezone
88
+
89
+ timeline = [
90
+ IncidentTimelineEntry(
91
+ timestamp=datetime.now(timezone.utc).isoformat(),
92
+ stage="01. DETECTED",
93
+ agent_id=target_agent_id,
94
+ action=f"Detected {threat_type} on {tool_name or 'resource'}",
95
+ detail=description,
96
+ taint_state="UNTRUSTED",
97
+ decision="BLOCK",
98
+ actor_name="detection_engine",
99
+ incident_state=IncidentState.DETECTED,
100
+ )
101
+ ]
102
+
103
+ return SecurityIncident(
104
+ title=title,
105
+ severity=severity,
106
+ state=IncidentState.DETECTED,
107
+ attack_type=threat_type,
108
+ affected_agents=[target_agent_id] if target_agent_id else [],
109
+ affected_resources=[tool_name] if tool_name else [],
110
+ ai_secura_summary=root_cause or description,
111
+ timeline=timeline,
112
+ remediation_notes=root_cause,
113
+ )
114
+
115
+
116
+
@@ -0,0 +1,58 @@
1
+ """Incident Lifecycle States and Deterministic State Transition Machine (Phase 9).
2
+
3
+ Lifecycle:
4
+ DETECTED -> TRIAGED -> INVESTIGATING -> CONTAINED -> REMEDIATED -> VALIDATED -> CLOSED
5
+
6
+ Note:
7
+ AI may provide analytical enrichment. Deterministic logic strictly governs state transitions.
8
+ """
9
+
10
+ from enum import Enum
11
+ from typing import List, Set
12
+
13
+
14
+ class IncidentState(str, Enum):
15
+ """Deterministic security incident states."""
16
+ DETECTED = "DETECTED"
17
+ TRIAGED = "TRIAGED"
18
+ INVESTIGATING = "INVESTIGATING"
19
+ CONTAINED = "CONTAINED"
20
+ REMEDIATED = "REMEDIATED"
21
+ VALIDATED = "VALIDATED"
22
+ CLOSED = "CLOSED"
23
+
24
+
25
+ class IncidentSeverity(str, Enum):
26
+ """Incident severity classification."""
27
+ LOW = "LOW"
28
+ MEDIUM = "MEDIUM"
29
+ HIGH = "HIGH"
30
+ CRITICAL = "CRITICAL"
31
+
32
+
33
+ # Valid deterministic state transitions
34
+ ALLOWED_TRANSITIONS: dict[IncidentState, Set[IncidentState]] = {
35
+ IncidentState.DETECTED: {IncidentState.TRIAGED, IncidentState.INVESTIGATING, IncidentState.CONTAINED, IncidentState.CLOSED},
36
+ IncidentState.TRIAGED: {IncidentState.INVESTIGATING, IncidentState.CONTAINED, IncidentState.CLOSED},
37
+ IncidentState.INVESTIGATING: {IncidentState.CONTAINED, IncidentState.REMEDIATED, IncidentState.CLOSED},
38
+ IncidentState.CONTAINED: {IncidentState.REMEDIATED, IncidentState.VALIDATED, IncidentState.CLOSED},
39
+ IncidentState.REMEDIATED: {IncidentState.VALIDATED, IncidentState.CLOSED, IncidentState.INVESTIGATING},
40
+ IncidentState.VALIDATED: {IncidentState.CLOSED, IncidentState.INVESTIGATING},
41
+ IncidentState.CLOSED: {IncidentState.INVESTIGATING}, # Reopen if needed
42
+ }
43
+
44
+
45
+ class IncidentStateMachine:
46
+ """Validates and enforces deterministic incident lifecycle transitions."""
47
+
48
+ @staticmethod
49
+ def can_transition(current: IncidentState, target: IncidentState) -> bool:
50
+ return target in ALLOWED_TRANSITIONS.get(current, set())
51
+
52
+ @staticmethod
53
+ def validate_transition(current: IncidentState, target: IncidentState) -> None:
54
+ if not IncidentStateMachine.can_transition(current, target):
55
+ raise ValueError(
56
+ f"Invalid incident state transition from '{current.value}' to '{target.value}'. "
57
+ f"Allowed transitions: {[s.value for s in ALLOWED_TRANSITIONS.get(current, set())]}"
58
+ )
@@ -0,0 +1,24 @@
1
+ """Integrations package for AI Secura and APIRIS."""
2
+
3
+ from actshield.integrations.ai_secura import (
4
+ LocalAISecuraAdapter,
5
+ SecurityAnalysis,
6
+ SecurityContext,
7
+ SecurityReasoner,
8
+ )
9
+ from actshield.integrations.apiris import (
10
+ APIAnalysis,
11
+ APIIntelligence,
12
+ LocalAPIRISAdapter,
13
+ )
14
+
15
+ __all__ = [
16
+ "SecurityContext",
17
+ "SecurityAnalysis",
18
+ "SecurityReasoner",
19
+ "LocalAISecuraAdapter",
20
+ "APIAnalysis",
21
+ "APIIntelligence",
22
+ "LocalAPIRISAdapter",
23
+ ]
24
+
@@ -0,0 +1,169 @@
1
+ """AI Secura security reasoning adapter interface (Dependency Inversion).
2
+
3
+ AI Secura evaluates structured security context, detects intent drift, indirect
4
+ prompt injections, and attack indicators. AI Secura reasons and explains;
5
+ ActShield's deterministic policy enforces.
6
+ """
7
+
8
+ from typing import Any, Callable, Dict, List, Optional, Protocol, runtime_checkable
9
+ import uuid
10
+ from pydantic import BaseModel, Field
11
+
12
+ from actshield.risk.models import RiskLevel, RiskSignal
13
+
14
+
15
+ class SecurityContext(BaseModel):
16
+ """Structured security context payload passed to AI Secura for cybersecurity reasoning."""
17
+ trace_id: str
18
+ task_intent: str
19
+ initiating_user: Optional[str] = None
20
+ acting_agent_id: Optional[str] = None
21
+ acting_agent_name: Optional[str] = None
22
+ acting_agent_trust: Optional[str] = None
23
+ delegation_chain: List[Dict[str, Any]] = Field(default_factory=list)
24
+ context_provenance: List[Dict[str, Any]] = Field(default_factory=list)
25
+ taint_states: List[str] = Field(default_factory=list)
26
+ tool_name: Optional[str] = None
27
+ tool_arguments: Dict[str, Any] = Field(default_factory=dict)
28
+ target_resource_sensitivity: Optional[str] = None
29
+ metadata: Dict[str, Any] = Field(default_factory=dict)
30
+
31
+
32
+ class SecurityAnalysis(BaseModel):
33
+ """Structured reasoning output returned by AI Secura."""
34
+ analysis_id: str
35
+ summary: str
36
+ risk_level: RiskLevel = RiskLevel.LOW
37
+ risk_score: float = Field(default=0.0, ge=0.0, le=1.0)
38
+ attack_indicators: List[str] = Field(default_factory=list)
39
+ intent_drift_detected: bool = False
40
+ authority_violation_detected: bool = False
41
+ prompt_injection_indicators: List[str] = Field(default_factory=list)
42
+ reasoning: str = ""
43
+ signals: List[RiskSignal] = Field(default_factory=list)
44
+
45
+
46
+ @runtime_checkable
47
+ class SecurityReasoner(Protocol):
48
+ """Protocol for AI Secura cybersecurity reasoning implementations."""
49
+
50
+ def analyze(self, context: SecurityContext) -> SecurityAnalysis:
51
+ """Analyze structured security context and produce reasoning insights without direct enforcement."""
52
+ ...
53
+
54
+
55
+ class AISecuraClient(SecurityReasoner):
56
+ """AI Secura Security Intelligence Reasoner.
57
+
58
+ Provides deep semantic analysis across multi-agent delegation chains,
59
+ untrusted MCP prompt injections, and intent divergence.
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ api_endpoint: Optional[str] = None,
65
+ api_key: Optional[str] = None,
66
+ custom_engine: Optional[Callable[[SecurityContext], SecurityAnalysis]] = None,
67
+ ) -> None:
68
+ self.api_endpoint = api_endpoint or "https://ai-secura.internal/v1/reason"
69
+ self.api_key = api_key or "ai-secura-live-token"
70
+ self.custom_engine = custom_engine
71
+
72
+ def analyze(self, context: SecurityContext) -> SecurityAnalysis:
73
+ """Perform AI Secura security reasoning over the provided multi-agent context."""
74
+ if self.custom_engine:
75
+ return self.custom_engine(context)
76
+
77
+ analysis_id = f"aisec_{uuid.uuid4().hex[:12]}"
78
+ signals: List[RiskSignal] = []
79
+ attack_indicators: List[str] = []
80
+ prompt_injections: List[str] = []
81
+ drift = False
82
+ auth_violation = False
83
+
84
+ # 1. Evaluate context taint and prompt injection heuristics
85
+ args_str = str(context.tool_arguments).lower()
86
+ context_str = json_str = str(context.context_provenance).lower()
87
+
88
+ if any(kw in context_str or kw in args_str for kw in (
89
+ "system directive", "override", "ignore previous", "exfiltrate",
90
+ "admin exemption", "ciso security team has granted", "emergency exemption"
91
+ )):
92
+ prompt_injections.append("ADVERSARIAL_INDIRECT_PROMPT_INJECTION_DIRECTIVE")
93
+ attack_indicators.append("Adversarial payload instruction detected in causal lineage")
94
+ signals.append(
95
+ RiskSignal(
96
+ source="ai_secura",
97
+ risk_level=RiskLevel.CRITICAL,
98
+ score=0.95,
99
+ indicator="AI_SECURA_PROMPT_INJECTION_DETECTED",
100
+ details={"matched_keywords": ["system directive", "override", "exfiltrate"]},
101
+ )
102
+ )
103
+
104
+ # 2. Check for untrusted taint targeting critical sinks
105
+ if any(t in ("TAINTED", "UNTRUSTED") for t in context.taint_states):
106
+ if context.target_resource_sensitivity in ("HIGH", "CRITICAL"):
107
+ signals.append(
108
+ RiskSignal(
109
+ source="ai_secura",
110
+ risk_level=RiskLevel.HIGH,
111
+ score=0.85,
112
+ indicator="AI_SECURA_TAINTED_CONTEXT_TO_SENSITIVE_SINK",
113
+ details={"taint_states": context.taint_states, "target_sensitivity": context.target_resource_sensitivity},
114
+ )
115
+ )
116
+ attack_indicators.append("Untrusted context attempting to influence sensitive data sink")
117
+
118
+ # 3. Check intent drift
119
+ intent_lower = (context.task_intent or "").lower()
120
+ tool_lower = (context.tool_name or "").lower()
121
+ if "public" in intent_lower or "research" in intent_lower:
122
+ if any(p in tool_lower for p in ("customer_db", "pii", "users", "delete", "admin")):
123
+ drift = True
124
+ signals.append(
125
+ RiskSignal(
126
+ source="ai_secura",
127
+ risk_level=RiskLevel.CRITICAL,
128
+ score=0.90,
129
+ indicator="AI_SECURA_INTENT_DRIFT_PUBLIC_VS_SENSITIVE_SINK",
130
+ details={"intent": context.task_intent, "tool": context.tool_name},
131
+ )
132
+ )
133
+ attack_indicators.append(f"Intent drift: Public research intent diverted to sensitive tool '{context.tool_name}'")
134
+
135
+ overall_score = max([s.score for s in signals], default=0.05)
136
+ if overall_score >= 0.8:
137
+ overall_level = RiskLevel.CRITICAL
138
+ elif overall_score >= 0.5:
139
+ overall_level = RiskLevel.HIGH
140
+ elif overall_score >= 0.25:
141
+ overall_level = RiskLevel.MEDIUM
142
+ else:
143
+ overall_level = RiskLevel.LOW
144
+
145
+ reasoning = (
146
+ f"AI Secura Reasoning: Evaluated delegation chain depth {len(context.delegation_chain)}, "
147
+ f"{len(context.taint_states)} context states. "
148
+ f"Prompt Injections: {len(prompt_injections)}, Intent Drift: {drift}."
149
+ )
150
+
151
+ return SecurityAnalysis(
152
+ analysis_id=analysis_id,
153
+ summary="AI Secura cybersecurity analysis completed.",
154
+ risk_level=overall_level,
155
+ risk_score=overall_score,
156
+ attack_indicators=attack_indicators,
157
+ intent_drift_detected=drift,
158
+ authority_violation_detected=auth_violation,
159
+ prompt_injection_indicators=prompt_injections,
160
+ reasoning=reasoning,
161
+ signals=signals,
162
+ )
163
+
164
+
165
+ class LocalAISecuraAdapter(AISecuraClient):
166
+ """Backward-compatible alias for local execution."""
167
+ pass
168
+
169
+