agent-learning-kit 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 (642) hide show
  1. agent_learning_kit-0.1.0.dist-info/METADATA +381 -0
  2. agent_learning_kit-0.1.0.dist-info/RECORD +642 -0
  3. agent_learning_kit-0.1.0.dist-info/WHEEL +4 -0
  4. agent_learning_kit-0.1.0.dist-info/entry_points.txt +5 -0
  5. agent_learning_kit-0.1.0.dist-info/licenses/LICENSE +173 -0
  6. agent_learning_kit-0.1.0.dist-info/licenses/NOTICE +7 -0
  7. fi/__init__.py +5 -0
  8. fi/alk/__init__.py +57 -0
  9. fi/alk/_facade.py +31 -0
  10. fi/alk/_module_alias.py +68 -0
  11. fi/alk/_paths.py +14 -0
  12. fi/alk/_schema.py +522 -0
  13. fi/alk/actions.py +727 -0
  14. fi/alk/bench/__init__.py +517 -0
  15. fi/alk/bench/_codeexec.py +213 -0
  16. fi/alk/bench/_coding.py +215 -0
  17. fi/alk/bench/_docker.py +237 -0
  18. fi/alk/bench/_grader.py +286 -0
  19. fi/alk/bench/_pull.py +212 -0
  20. fi/alk/bench/_voice.py +147 -0
  21. fi/alk/capabilities.py +627 -0
  22. fi/alk/cli.py +6396 -0
  23. fi/alk/config.py +130 -0
  24. fi/alk/cua_loop.py +562 -0
  25. fi/alk/evals.py +2351 -0
  26. fi/alk/extensions.py +163 -0
  27. fi/alk/harness/ARCHITECTURE.md +231 -0
  28. fi/alk/harness/DESIGN.md +246 -0
  29. fi/alk/harness/ENVIRONMENT_CONFORMANCE.md +127 -0
  30. fi/alk/harness/HOW-IT-WORKS.md +297 -0
  31. fi/alk/harness/IMPLEMENTATION_AND_VALIDATION_STATUS.md +229 -0
  32. fi/alk/harness/README.md +417 -0
  33. fi/alk/harness/__init__.py +77 -0
  34. fi/alk/harness/__main__.py +3 -0
  35. fi/alk/harness/amend.py +312 -0
  36. fi/alk/harness/artifacts.py +319 -0
  37. fi/alk/harness/authoring_entrypoint.py +189 -0
  38. fi/alk/harness/authoring_runtime_validation.py +267 -0
  39. fi/alk/harness/backends/README.md +43 -0
  40. fi/alk/harness/backends/__init__.py +122 -0
  41. fi/alk/harness/backends/base.py +241 -0
  42. fi/alk/harness/backends/claude.py +211 -0
  43. fi/alk/harness/backends/files.py +182 -0
  44. fi/alk/harness/backends/vertex_gemini.py +457 -0
  45. fi/alk/harness/background_noise.py +95 -0
  46. fi/alk/harness/build.py +385 -0
  47. fi/alk/harness/bundle.py +593 -0
  48. fi/alk/harness/bundle_author_v2.py +1831 -0
  49. fi/alk/harness/bundle_v2.py +719 -0
  50. fi/alk/harness/call_runner.py +1440 -0
  51. fi/alk/harness/callback_http_adapter.py +111 -0
  52. fi/alk/harness/catalogue.py +287 -0
  53. fi/alk/harness/chat.py +428 -0
  54. fi/alk/harness/chat_call_runner.py +506 -0
  55. fi/alk/harness/checks.py +136 -0
  56. fi/alk/harness/cli.py +1354 -0
  57. fi/alk/harness/config.py +338 -0
  58. fi/alk/harness/contract.py +718 -0
  59. fi/alk/harness/credentials.py +674 -0
  60. fi/alk/harness/data/persona_vocabulary.json +111 -0
  61. fi/alk/harness/environment.py +99 -0
  62. fi/alk/harness/environment_plan.py +168 -0
  63. fi/alk/harness/events.py +125 -0
  64. fi/alk/harness/executor.py +304 -0
  65. fi/alk/harness/folder.py +234 -0
  66. fi/alk/harness/generated_runtime.py +815 -0
  67. fi/alk/harness/github.py +72 -0
  68. fi/alk/harness/hosted_authoring_entrypoint.py +183 -0
  69. fi/alk/harness/hosted_entrypoint.py +2402 -0
  70. fi/alk/harness/hosted_scheduler.py +2218 -0
  71. fi/alk/harness/job.py +426 -0
  72. fi/alk/harness/judge.py +184 -0
  73. fi/alk/harness/livekit_source.py +50 -0
  74. fi/alk/harness/livekit_tool_trace_bootstrap.py +71 -0
  75. fi/alk/harness/observability.py +208 -0
  76. fi/alk/harness/outbound.py +3252 -0
  77. fi/alk/harness/packaging.py +515 -0
  78. fi/alk/harness/persona_guides.py +157 -0
  79. fi/alk/harness/platform.py +692 -0
  80. fi/alk/harness/process_preflight.py +764 -0
  81. fi/alk/harness/process_runtime.py +5670 -0
  82. fi/alk/harness/prove.py +425 -0
  83. fi/alk/harness/provider_import.py +703 -0
  84. fi/alk/harness/provider_lifecycle.py +392 -0
  85. fi/alk/harness/provision.py +2896 -0
  86. fi/alk/harness/reception.py +147 -0
  87. fi/alk/harness/retell_chat_call_runner.py +373 -0
  88. fi/alk/harness/run/__init__.py +296 -0
  89. fi/alk/harness/run/alk.py +184 -0
  90. fi/alk/harness/run/call.py +162 -0
  91. fi/alk/harness/run/conversation.py +264 -0
  92. fi/alk/harness/run/data/voices_by_language_and_gender.json +693 -0
  93. fi/alk/harness/run/evidence.py +195 -0
  94. fi/alk/harness/run/grade.py +598 -0
  95. fi/alk/harness/run/live.py +297 -0
  96. fi/alk/harness/run/models.py +56 -0
  97. fi/alk/harness/run/platform_evals.py +227 -0
  98. fi/alk/harness/run/sdk_voice.py +130 -0
  99. fi/alk/harness/run/simulation.py +1209 -0
  100. fi/alk/harness/run/stage.py +91 -0
  101. fi/alk/harness/run/targets.py +508 -0
  102. fi/alk/harness/run/tools.py +601 -0
  103. fi/alk/harness/run/voice.py +340 -0
  104. fi/alk/harness/runtime.py +172 -0
  105. fi/alk/harness/sandbox_server.py +2011 -0
  106. fi/alk/harness/sandbox_worker.py +44 -0
  107. fi/alk/harness/scenario.py +1048 -0
  108. fi/alk/harness/scenario_source.py +879 -0
  109. fi/alk/harness/scenario_tools.py +1143 -0
  110. fi/alk/harness/scenarios.py +915 -0
  111. fi/alk/harness/secrets.py +168 -0
  112. fi/alk/harness/service_catalog.py +97 -0
  113. fi/alk/harness/session.py +391 -0
  114. fi/alk/harness/sessions.py +372 -0
  115. fi/alk/harness/simulator.py +76 -0
  116. fi/alk/harness/simulator_voice.py +928 -0
  117. fi/alk/harness/skills/build-environment/SKILL.md +538 -0
  118. fi/alk/harness/skills/harness.md +131 -0
  119. fi/alk/harness/skills/kinds/chat.md +48 -0
  120. fi/alk/harness/skills/kinds/voice-voicemail.md +63 -0
  121. fi/alk/harness/skills/kinds/voice.md +59 -0
  122. fi/alk/harness/skills/plan-suite/SKILL.md +103 -0
  123. fi/alk/harness/skills/provision-environment/SKILL.md +136 -0
  124. fi/alk/harness/skills/run-scenarios/SKILL.md +112 -0
  125. fi/alk/harness/skills/understand-agent/SKILL.md +251 -0
  126. fi/alk/harness/skills/write-scenarios/SKILL.md +606 -0
  127. fi/alk/harness/skills/write-scenarios/references/refusals.md +28 -0
  128. fi/alk/harness/skills/write-scenarios/references/world-api.md +92 -0
  129. fi/alk/harness/source_data_invariants.py +444 -0
  130. fi/alk/harness/source_tool_evidence.py +79 -0
  131. fi/alk/harness/sources.py +253 -0
  132. fi/alk/harness/spend.py +140 -0
  133. fi/alk/harness/tool_trace_proxy.py +104 -0
  134. fi/alk/harness/tools.py +1018 -0
  135. fi/alk/harness/understand.py +169 -0
  136. fi/alk/harness/voicemail_audio.py +74 -0
  137. fi/alk/harness/world/__init__.py +33 -0
  138. fi/alk/harness/world/errors.py +68 -0
  139. fi/alk/harness/world/expectations.py +91 -0
  140. fi/alk/harness/world/handle.py +538 -0
  141. fi/alk/harness/world/kinds.py +196 -0
  142. fi/alk/harness/world/mutate.py +186 -0
  143. fi/alk/harness/world/probe.py +413 -0
  144. fi/alk/harness/world/provision.py +511 -0
  145. fi/alk/harness/world/provisioned.py +191 -0
  146. fi/alk/harness/world/runtime.py +616 -0
  147. fi/alk/harness/world/snapshot.py +288 -0
  148. fi/alk/harness/world/stores/__init__.py +305 -0
  149. fi/alk/harness/world/stores/container.py +215 -0
  150. fi/alk/harness/world/stores/inprocess.py +346 -0
  151. fi/alk/harness/world/stores/postgres.py +481 -0
  152. fi/alk/harness/world/stores/prove.py +202 -0
  153. fi/alk/harness/world/stores/sqlite.py +245 -0
  154. fi/alk/harness/world/stores/written.py +182 -0
  155. fi/alk/harness/world/tools.py +1516 -0
  156. fi/alk/harness/world/workspace.py +144 -0
  157. fi/alk/image_loop.py +453 -0
  158. fi/alk/image_perturb.py +241 -0
  159. fi/alk/improve.py +274 -0
  160. fi/alk/live/__init__.py +154 -0
  161. fi/alk/live/_attribution.py +184 -0
  162. fi/alk/live/_capture.py +264 -0
  163. fi/alk/live/_codec.py +391 -0
  164. fi/alk/live/_contract.py +134 -0
  165. fi/alk/live/_loopback.py +316 -0
  166. fi/alk/live/_perturb.py +449 -0
  167. fi/alk/live/_runner.py +386 -0
  168. fi/alk/live/_stats.py +561 -0
  169. fi/alk/live/_transcript.py +240 -0
  170. fi/alk/live/_workers/__init__.py +9 -0
  171. fi/alk/live/_workers/a2a_worker.py +316 -0
  172. fi/alk/live/_workers/langgraph_worker.py +217 -0
  173. fi/alk/live/_workers/livekit_worker.py +207 -0
  174. fi/alk/live/_workers/mcp_loopback_server.py +46 -0
  175. fi/alk/live/_workers/mcp_worker.py +158 -0
  176. fi/alk/live/_workers/pipecat_worker.py +189 -0
  177. fi/alk/live/a2a_lane.py +138 -0
  178. fi/alk/live/langgraph_lane.py +339 -0
  179. fi/alk/live/livekit_lane.py +376 -0
  180. fi/alk/live/mcp_lane.py +172 -0
  181. fi/alk/live/pipecat_lane.py +341 -0
  182. fi/alk/live/voice_redteam.py +494 -0
  183. fi/alk/loss.py +306 -0
  184. fi/alk/optimize.py +36260 -0
  185. fi/alk/practice/__init__.py +51 -0
  186. fi/alk/practice/_assess.py +103 -0
  187. fi/alk/practice/_budget.py +81 -0
  188. fi/alk/practice/_calibrate.py +69 -0
  189. fi/alk/practice/_capstone.py +86 -0
  190. fi/alk/practice/_contract.py +91 -0
  191. fi/alk/practice/_diagnose.py +79 -0
  192. fi/alk/practice/_drill.py +196 -0
  193. fi/alk/practice/_experiment.py +720 -0
  194. fi/alk/practice/_schedule.py +102 -0
  195. fi/alk/practice/_store.py +194 -0
  196. fi/alk/practice/_trainer.py +245 -0
  197. fi/alk/practice/_update.py +125 -0
  198. fi/alk/redteam.py +2621 -0
  199. fi/alk/rewardhack.py +237 -0
  200. fi/alk/simulate.py +10351 -0
  201. fi/alk/studio/__init__.py +82 -0
  202. fi/alk/studio/_bias.py +314 -0
  203. fi/alk/studio/_calibration.py +522 -0
  204. fi/alk/studio/_coverage.py +262 -0
  205. fi/alk/studio/_download.py +665 -0
  206. fi/alk/studio/_fidelity_attack.py +114 -0
  207. fi/alk/studio/_generate.py +652 -0
  208. fi/alk/studio/_library.py +370 -0
  209. fi/alk/studio/_scan.py +134 -0
  210. fi/alk/studio/_upgrade.py +42 -0
  211. fi/alk/studio/_vendor.py +172 -0
  212. fi/alk/suite.py +4200 -0
  213. fi/alk/tasks.py +828 -0
  214. fi/alk/telemetry/__init__.py +149 -0
  215. fi/alk/telemetry/_contract.py +141 -0
  216. fi/alk/telemetry/_emit.py +182 -0
  217. fi/alk/telemetry/_ledger.py +296 -0
  218. fi/alk/telemetry/_queue.py +127 -0
  219. fi/alk/telemetry/_row.py +294 -0
  220. fi/alk/telemetry/_run.py +233 -0
  221. fi/alk/telemetry/_sync.py +193 -0
  222. fi/alk/telemetry/_url.py +119 -0
  223. fi/alk/trinity.py +49397 -0
  224. fi/alk/voice_loop.py +174 -0
  225. fi/api/__init__.py +1 -0
  226. fi/api/auth.py +137 -0
  227. fi/api/types.py +29 -0
  228. fi/cli/__init__.py +9 -0
  229. fi/cli/assertions/__init__.py +25 -0
  230. fi/cli/assertions/conditions.py +76 -0
  231. fi/cli/assertions/evaluator.py +286 -0
  232. fi/cli/assertions/exit_codes.py +20 -0
  233. fi/cli/assertions/parser.py +131 -0
  234. fi/cli/assertions/reporter.py +194 -0
  235. fi/cli/commands/__init__.py +9 -0
  236. fi/cli/commands/config.py +165 -0
  237. fi/cli/commands/export.py +208 -0
  238. fi/cli/commands/init.py +112 -0
  239. fi/cli/commands/list_cmd.py +213 -0
  240. fi/cli/commands/run.py +486 -0
  241. fi/cli/commands/validate.py +173 -0
  242. fi/cli/commands/view.py +424 -0
  243. fi/cli/config/__init__.py +6 -0
  244. fi/cli/config/defaults.py +206 -0
  245. fi/cli/config/loader.py +155 -0
  246. fi/cli/config/schema.py +174 -0
  247. fi/cli/main.py +78 -0
  248. fi/cli/output/__init__.py +6 -0
  249. fi/cli/output/formatters.py +106 -0
  250. fi/cli/output/reporters.py +46 -0
  251. fi/cli/storage/__init__.py +5 -0
  252. fi/cli/storage/run_history.py +249 -0
  253. fi/cli/utils/__init__.py +5 -0
  254. fi/cli/utils/console.py +44 -0
  255. fi/evals/__init__.py +131 -0
  256. fi/evals/autoeval/__init__.py +137 -0
  257. fi/evals/autoeval/analyzer.py +211 -0
  258. fi/evals/autoeval/config.py +244 -0
  259. fi/evals/autoeval/export.py +213 -0
  260. fi/evals/autoeval/interactive.py +283 -0
  261. fi/evals/autoeval/pipeline.py +625 -0
  262. fi/evals/autoeval/prompts.py +139 -0
  263. fi/evals/autoeval/recommender.py +242 -0
  264. fi/evals/autoeval/rules.py +589 -0
  265. fi/evals/autoeval/templates.py +299 -0
  266. fi/evals/autoeval/types.py +232 -0
  267. fi/evals/core/__init__.py +16 -0
  268. fi/evals/core/cloud_registry.py +184 -0
  269. fi/evals/core/engines.py +368 -0
  270. fi/evals/core/evaluate.py +319 -0
  271. fi/evals/core/judge_prompt.py +90 -0
  272. fi/evals/core/prompt_generator.py +83 -0
  273. fi/evals/core/registry.py +57 -0
  274. fi/evals/core/result.py +55 -0
  275. fi/evals/evaluator.py +721 -0
  276. fi/evals/execution.py +168 -0
  277. fi/evals/feedback/__init__.py +32 -0
  278. fi/evals/feedback/calibrator.py +160 -0
  279. fi/evals/feedback/collector.py +214 -0
  280. fi/evals/feedback/hooks.py +81 -0
  281. fi/evals/feedback/retriever.py +128 -0
  282. fi/evals/feedback/store.py +272 -0
  283. fi/evals/feedback/types.py +99 -0
  284. fi/evals/framework/README.md +79 -0
  285. fi/evals/framework/__init__.py +267 -0
  286. fi/evals/framework/backends/Dockerfile.eval-runner +33 -0
  287. fi/evals/framework/backends/__init__.py +99 -0
  288. fi/evals/framework/backends/_container.py +141 -0
  289. fi/evals/framework/backends/_utils.py +145 -0
  290. fi/evals/framework/backends/base.py +223 -0
  291. fi/evals/framework/backends/celery_backend.py +417 -0
  292. fi/evals/framework/backends/celery_worker.py +78 -0
  293. fi/evals/framework/backends/kubernetes_backend.py +665 -0
  294. fi/evals/framework/backends/ray_backend.py +521 -0
  295. fi/evals/framework/backends/temporal.py +350 -0
  296. fi/evals/framework/backends/temporal_worker.py +126 -0
  297. fi/evals/framework/backends/thread_pool.py +286 -0
  298. fi/evals/framework/context.py +258 -0
  299. fi/evals/framework/enrichment.py +306 -0
  300. fi/evals/framework/evals/__init__.py +68 -0
  301. fi/evals/framework/evals/agentic.py +399 -0
  302. fi/evals/framework/evals/builder.py +609 -0
  303. fi/evals/framework/evals/semantic.py +142 -0
  304. fi/evals/framework/evaluator.py +647 -0
  305. fi/evals/framework/evaluators/__init__.py +22 -0
  306. fi/evals/framework/evaluators/blocking.py +347 -0
  307. fi/evals/framework/evaluators/non_blocking.py +577 -0
  308. fi/evals/framework/propagation.py +421 -0
  309. fi/evals/framework/protocols.py +385 -0
  310. fi/evals/framework/registry.py +370 -0
  311. fi/evals/framework/resilience/__init__.py +150 -0
  312. fi/evals/framework/resilience/circuit_breaker.py +309 -0
  313. fi/evals/framework/resilience/degradation.py +355 -0
  314. fi/evals/framework/resilience/health.py +505 -0
  315. fi/evals/framework/resilience/rate_limiter.py +228 -0
  316. fi/evals/framework/resilience/retry.py +274 -0
  317. fi/evals/framework/resilience/types.py +288 -0
  318. fi/evals/framework/resilience/wrapper.py +433 -0
  319. fi/evals/framework/types.py +218 -0
  320. fi/evals/guardrails/README.md +915 -0
  321. fi/evals/guardrails/__init__.py +96 -0
  322. fi/evals/guardrails/backends/__init__.py +43 -0
  323. fi/evals/guardrails/backends/azure.py +361 -0
  324. fi/evals/guardrails/backends/base.py +88 -0
  325. fi/evals/guardrails/backends/generic_llm.py +163 -0
  326. fi/evals/guardrails/backends/granite.py +216 -0
  327. fi/evals/guardrails/backends/llamaguard.py +221 -0
  328. fi/evals/guardrails/backends/local_base.py +479 -0
  329. fi/evals/guardrails/backends/openai.py +365 -0
  330. fi/evals/guardrails/backends/qwen.py +170 -0
  331. fi/evals/guardrails/backends/shieldgemma.py +154 -0
  332. fi/evals/guardrails/backends/turing.py +235 -0
  333. fi/evals/guardrails/backends/vllm_client.py +321 -0
  334. fi/evals/guardrails/backends/wildguard.py +188 -0
  335. fi/evals/guardrails/base.py +888 -0
  336. fi/evals/guardrails/config.py +221 -0
  337. fi/evals/guardrails/discovery.py +243 -0
  338. fi/evals/guardrails/gateway.py +437 -0
  339. fi/evals/guardrails/registry.py +231 -0
  340. fi/evals/guardrails/scanners/__init__.py +127 -0
  341. fi/evals/guardrails/scanners/base.py +191 -0
  342. fi/evals/guardrails/scanners/code_injection.py +243 -0
  343. fi/evals/guardrails/scanners/eval_delegate.py +574 -0
  344. fi/evals/guardrails/scanners/invisible_chars.py +351 -0
  345. fi/evals/guardrails/scanners/jailbreak.py +412 -0
  346. fi/evals/guardrails/scanners/language.py +288 -0
  347. fi/evals/guardrails/scanners/pipeline.py +260 -0
  348. fi/evals/guardrails/scanners/regex.py +311 -0
  349. fi/evals/guardrails/scanners/secrets.py +274 -0
  350. fi/evals/guardrails/scanners/topics.py +649 -0
  351. fi/evals/guardrails/scanners/urls.py +341 -0
  352. fi/evals/guardrails/types.py +96 -0
  353. fi/evals/llm/__init__.py +3 -0
  354. fi/evals/llm/base_llm_provider.py +35 -0
  355. fi/evals/llm/providers/litellm.py +70 -0
  356. fi/evals/local/__init__.py +90 -0
  357. fi/evals/local/evaluator.py +690 -0
  358. fi/evals/local/execution_mode.py +121 -0
  359. fi/evals/local/llm.py +489 -0
  360. fi/evals/local/metrics/__init__.py +19 -0
  361. fi/evals/local/registry.py +360 -0
  362. fi/evals/manager.py +1018 -0
  363. fi/evals/manager_types.py +362 -0
  364. fi/evals/metrics/__init__.py +185 -0
  365. fi/evals/metrics/agents/__init__.py +74 -0
  366. fi/evals/metrics/agents/metrics.py +693 -0
  367. fi/evals/metrics/agents/report.py +36463 -0
  368. fi/evals/metrics/agents/types.py +160 -0
  369. fi/evals/metrics/base_llm_metric.py +111 -0
  370. fi/evals/metrics/base_metric.py +138 -0
  371. fi/evals/metrics/code_security/__init__.py +305 -0
  372. fi/evals/metrics/code_security/analyzer.py +985 -0
  373. fi/evals/metrics/code_security/benchmarks/__init__.py +73 -0
  374. fi/evals/metrics/code_security/benchmarks/builtin.py +750 -0
  375. fi/evals/metrics/code_security/benchmarks/loader.py +580 -0
  376. fi/evals/metrics/code_security/benchmarks/types.py +308 -0
  377. fi/evals/metrics/code_security/detectors/__init__.py +186 -0
  378. fi/evals/metrics/code_security/detectors/base.py +394 -0
  379. fi/evals/metrics/code_security/detectors/cryptography.py +345 -0
  380. fi/evals/metrics/code_security/detectors/injection.py +744 -0
  381. fi/evals/metrics/code_security/detectors/secrets.py +287 -0
  382. fi/evals/metrics/code_security/detectors/serialization.py +192 -0
  383. fi/evals/metrics/code_security/joint_metrics.py +588 -0
  384. fi/evals/metrics/code_security/judges/__init__.py +83 -0
  385. fi/evals/metrics/code_security/judges/base.py +238 -0
  386. fi/evals/metrics/code_security/judges/dual_judge.py +534 -0
  387. fi/evals/metrics/code_security/judges/llm_judge.py +301 -0
  388. fi/evals/metrics/code_security/judges/pattern_judge.py +515 -0
  389. fi/evals/metrics/code_security/metrics.py +388 -0
  390. fi/evals/metrics/code_security/modes/__init__.py +63 -0
  391. fi/evals/metrics/code_security/modes/adversarial.py +284 -0
  392. fi/evals/metrics/code_security/modes/autocomplete.py +198 -0
  393. fi/evals/metrics/code_security/modes/base.py +283 -0
  394. fi/evals/metrics/code_security/modes/instruct.py +253 -0
  395. fi/evals/metrics/code_security/modes/repair.py +230 -0
  396. fi/evals/metrics/code_security/reports/__init__.py +57 -0
  397. fi/evals/metrics/code_security/reports/generator.py +404 -0
  398. fi/evals/metrics/code_security/reports/leaderboard.py +509 -0
  399. fi/evals/metrics/code_security/types.py +534 -0
  400. fi/evals/metrics/function_calling/__init__.py +34 -0
  401. fi/evals/metrics/function_calling/metrics.py +573 -0
  402. fi/evals/metrics/function_calling/types.py +87 -0
  403. fi/evals/metrics/hallucination/__init__.py +54 -0
  404. fi/evals/metrics/hallucination/detector.py +149 -0
  405. fi/evals/metrics/hallucination/metrics.py +390 -0
  406. fi/evals/metrics/hallucination/nli.py +253 -0
  407. fi/evals/metrics/hallucination/sentinel.py +106 -0
  408. fi/evals/metrics/hallucination/types.py +132 -0
  409. fi/evals/metrics/heuristics/aggregation_metrics.py +85 -0
  410. fi/evals/metrics/heuristics/json_metrics.py +87 -0
  411. fi/evals/metrics/heuristics/similarity_metrics.py +375 -0
  412. fi/evals/metrics/heuristics/string_metrics.py +391 -0
  413. fi/evals/metrics/llm_as_judges/__init__.py +17 -0
  414. fi/evals/metrics/llm_as_judges/custom_judge/metric.py +112 -0
  415. fi/evals/metrics/llm_as_judges/custom_judge/prompts.py +26 -0
  416. fi/evals/metrics/llm_as_judges/types.py +48 -0
  417. fi/evals/metrics/rag/__init__.py +111 -0
  418. fi/evals/metrics/rag/advanced/__init__.py +14 -0
  419. fi/evals/metrics/rag/advanced/multi_hop.py +283 -0
  420. fi/evals/metrics/rag/advanced/source_attribution.py +344 -0
  421. fi/evals/metrics/rag/generation/__init__.py +17 -0
  422. fi/evals/metrics/rag/generation/answer_relevancy.py +176 -0
  423. fi/evals/metrics/rag/generation/context_utilization.py +245 -0
  424. fi/evals/metrics/rag/generation/faithfulness.py +241 -0
  425. fi/evals/metrics/rag/generation/groundedness.py +131 -0
  426. fi/evals/metrics/rag/rag_score.py +277 -0
  427. fi/evals/metrics/rag/retrieval/__init__.py +20 -0
  428. fi/evals/metrics/rag/retrieval/context_entity_recall.py +124 -0
  429. fi/evals/metrics/rag/retrieval/context_precision.py +158 -0
  430. fi/evals/metrics/rag/retrieval/context_recall.py +106 -0
  431. fi/evals/metrics/rag/retrieval/noise_sensitivity.py +163 -0
  432. fi/evals/metrics/rag/retrieval/ranking.py +261 -0
  433. fi/evals/metrics/rag/types.py +100 -0
  434. fi/evals/metrics/rag/utils/__init__.py +62 -0
  435. fi/evals/metrics/rag/utils/claims.py +189 -0
  436. fi/evals/metrics/rag/utils/entities.py +244 -0
  437. fi/evals/metrics/rag/utils/nli.py +92 -0
  438. fi/evals/metrics/rag/utils/similarity.py +345 -0
  439. fi/evals/metrics/structured/__init__.py +114 -0
  440. fi/evals/metrics/structured/field_completeness.py +313 -0
  441. fi/evals/metrics/structured/hierarchy_score.py +366 -0
  442. fi/evals/metrics/structured/json_validation.py +190 -0
  443. fi/evals/metrics/structured/schema_compliance.py +280 -0
  444. fi/evals/metrics/structured/structured_output_score.py +298 -0
  445. fi/evals/metrics/structured/types.py +108 -0
  446. fi/evals/metrics/structured/validators/__init__.py +30 -0
  447. fi/evals/metrics/structured/validators/base.py +189 -0
  448. fi/evals/metrics/structured/validators/json_validator.py +196 -0
  449. fi/evals/metrics/structured/validators/pydantic_validator.py +178 -0
  450. fi/evals/metrics/structured/validators/yaml_validator.py +248 -0
  451. fi/evals/otel/__init__.py +266 -0
  452. fi/evals/otel/config.py +400 -0
  453. fi/evals/otel/conventions.py +463 -0
  454. fi/evals/otel/enrichment.py +371 -0
  455. fi/evals/otel/instrumentors/__init__.py +140 -0
  456. fi/evals/otel/instrumentors/anthropic.py +517 -0
  457. fi/evals/otel/instrumentors/base.py +382 -0
  458. fi/evals/otel/instrumentors/openai.py +673 -0
  459. fi/evals/otel/processors/__init__.py +36 -0
  460. fi/evals/otel/processors/base.py +473 -0
  461. fi/evals/otel/processors/cost.py +445 -0
  462. fi/evals/otel/processors/evaluation.py +559 -0
  463. fi/evals/otel/processors/llm.py +462 -0
  464. fi/evals/otel/tracer.py +506 -0
  465. fi/evals/otel/types.py +232 -0
  466. fi/evals/otel_utils.py +23 -0
  467. fi/evals/protect.py +671 -0
  468. fi/evals/protect_input_adapter.py +154 -0
  469. fi/evals/streaming/__init__.py +88 -0
  470. fi/evals/streaming/buffer.py +213 -0
  471. fi/evals/streaming/evaluator.py +551 -0
  472. fi/evals/streaming/policy.py +307 -0
  473. fi/evals/streaming/scorers.py +368 -0
  474. fi/evals/streaming/types.py +238 -0
  475. fi/evals/templates.py +472 -0
  476. fi/evals/types.py +156 -0
  477. fi/opt/__init__.py +221 -0
  478. fi/opt/_objective_scoring.py +85 -0
  479. fi/opt/base/__init__.py +11 -0
  480. fi/opt/base/base_generator.py +33 -0
  481. fi/opt/base/base_mapper.py +26 -0
  482. fi/opt/base/base_optimizer.py +45 -0
  483. fi/opt/base/evaluator.py +211 -0
  484. fi/opt/components.py +3095 -0
  485. fi/opt/datamappers/__init__.py +3 -0
  486. fi/opt/datamappers/basic_mapper.py +40 -0
  487. fi/opt/deployment.py +1021 -0
  488. fi/opt/evidence.py +4332 -0
  489. fi/opt/generators/__init__.py +3 -0
  490. fi/opt/generators/litellm.py +66 -0
  491. fi/opt/integrations/__init__.py +23 -0
  492. fi/opt/integrations/generative_suite.py +410 -0
  493. fi/opt/integrations/simulate.py +1313 -0
  494. fi/opt/mutations.py +771 -0
  495. fi/opt/observability.py +4639 -0
  496. fi/opt/optimizer_trace.py +889 -0
  497. fi/opt/optimizers/__init__.py +80 -0
  498. fi/opt/optimizers/agent.py +331 -0
  499. fi/opt/optimizers/agent_bandit.py +392 -0
  500. fi/opt/optimizers/agent_curriculum.py +635 -0
  501. fi/opt/optimizers/agent_evolution.py +894 -0
  502. fi/opt/optimizers/agent_feedback.py +1863 -0
  503. fi/opt/optimizers/agent_pareto.py +547 -0
  504. fi/opt/optimizers/agent_social_memory.py +1113 -0
  505. fi/opt/optimizers/agent_tpe.py +321 -0
  506. fi/opt/optimizers/bayesian_search.py +449 -0
  507. fi/opt/optimizers/council.py +2075 -0
  508. fi/opt/optimizers/futureagi_replay.py +799 -0
  509. fi/opt/optimizers/gepa.py +322 -0
  510. fi/opt/optimizers/metaprompt.py +243 -0
  511. fi/opt/optimizers/promptwizard.py +417 -0
  512. fi/opt/optimizers/protegi.py +329 -0
  513. fi/opt/optimizers/random_search.py +224 -0
  514. fi/opt/research.py +518 -0
  515. fi/opt/simulation.py +260 -0
  516. fi/opt/targets.py +232 -0
  517. fi/opt/types.py +66 -0
  518. fi/opt/utils/__init__.py +4 -0
  519. fi/opt/utils/early_stopping.py +266 -0
  520. fi/opt/utils/setup_logging.py +82 -0
  521. fi/simulate/__init__.py +540 -0
  522. fi/simulate/_hashing.py +35 -0
  523. fi/simulate/_logging.py +10 -0
  524. fi/simulate/adapters.py +87 -0
  525. fi/simulate/agent/__init__.py +120 -0
  526. fi/simulate/agent/browser.py +658 -0
  527. fi/simulate/agent/definition.py +587 -0
  528. fi/simulate/agent/frameworks.py +3528 -0
  529. fi/simulate/agent/generic.py +8286 -0
  530. fi/simulate/agent/import_probe.py +227 -0
  531. fi/simulate/agent/memory.py +905 -0
  532. fi/simulate/agent/mocks.py +101 -0
  533. fi/simulate/agent/multi_agent.py +361 -0
  534. fi/simulate/agent/orchestration.py +903 -0
  535. fi/simulate/agent/realtime.py +665 -0
  536. fi/simulate/agent/wrapper.py +99 -0
  537. fi/simulate/agent/wrappers/__init__.py +18 -0
  538. fi/simulate/agent/wrappers/anthropic.py +62 -0
  539. fi/simulate/agent/wrappers/gemini.py +65 -0
  540. fi/simulate/agent/wrappers/http.py +404 -0
  541. fi/simulate/agent/wrappers/langchain.py +80 -0
  542. fi/simulate/agent/wrappers/openai.py +75 -0
  543. fi/simulate/agent/wrappers/websocket.py +326 -0
  544. fi/simulate/artifacts/__init__.py +11 -0
  545. fi/simulate/artifacts/manifest.py +62 -0
  546. fi/simulate/cli.py +20560 -0
  547. fi/simulate/endpoints/__init__.py +45 -0
  548. fi/simulate/endpoints/_http_actor.py +73 -0
  549. fi/simulate/endpoints/actor_sources.py +243 -0
  550. fi/simulate/endpoints/base.py +107 -0
  551. fi/simulate/endpoints/builtins.py +10 -0
  552. fi/simulate/endpoints/callable.py +95 -0
  553. fi/simulate/endpoints/http.py +76 -0
  554. fi/simulate/endpoints/livekit.py +138 -0
  555. fi/simulate/endpoints/originators.py +132 -0
  556. fi/simulate/endpoints/profiles.py +348 -0
  557. fi/simulate/endpoints/retell.py +633 -0
  558. fi/simulate/endpoints/vapi.py +205 -0
  559. fi/simulate/endpoints/websocket.py +76 -0
  560. fi/simulate/environment.py +33026 -0
  561. fi/simulate/environments/__init__.py +11 -0
  562. fi/simulate/environments/base.py +73 -0
  563. fi/simulate/environments/chat.py +697 -0
  564. fi/simulate/environments/voice.py +212 -0
  565. fi/simulate/evaluation/__init__.py +4 -0
  566. fi/simulate/evaluation/ai_eval.py +227 -0
  567. fi/simulate/evidence/__init__.py +35 -0
  568. fi/simulate/evidence/base.py +59 -0
  569. fi/simulate/evidence/caller_observed.py +50 -0
  570. fi/simulate/evidence/livekit_instrumentation.py +51 -0
  571. fi/simulate/evidence/livekit_room.py +50 -0
  572. fi/simulate/evidence/otel.py +49 -0
  573. fi/simulate/evidence/providers/__init__.py +24 -0
  574. fi/simulate/evidence/providers/base.py +61 -0
  575. fi/simulate/evidence/providers/retell.py +376 -0
  576. fi/simulate/evidence/providers/vapi.py +426 -0
  577. fi/simulate/hosted/__init__.py +32 -0
  578. fi/simulate/hosted/child_entrypoint.py +306 -0
  579. fi/simulate/hosted/job.py +150 -0
  580. fi/simulate/hosted/targets.py +53 -0
  581. fi/simulate/instrumentation/__init__.py +5 -0
  582. fi/simulate/instrumentation/livekit/__init__.py +122 -0
  583. fi/simulate/manifest.py +1033 -0
  584. fi/simulate/matrix_cli.py +165 -0
  585. fi/simulate/realtime/__init__.py +40 -0
  586. fi/simulate/realtime/events.py +107 -0
  587. fi/simulate/realtime/media.py +61 -0
  588. fi/simulate/realtime/session.py +91 -0
  589. fi/simulate/recording/__init__.py +5 -0
  590. fi/simulate/recording/room_recorder.py +326 -0
  591. fi/simulate/registry.py +185 -0
  592. fi/simulate/results/__init__.py +9 -0
  593. fi/simulate/results/base.py +18 -0
  594. fi/simulate/results/filesystem.py +71 -0
  595. fi/simulate/results/futureagi.py +1340 -0
  596. fi/simulate/runtime/__init__.py +85 -0
  597. fi/simulate/runtime/capabilities.py +40 -0
  598. fi/simulate/runtime/events.py +63 -0
  599. fi/simulate/runtime/failures.py +25 -0
  600. fi/simulate/runtime/ids.py +34 -0
  601. fi/simulate/runtime/plan.py +70 -0
  602. fi/simulate/runtime/planner.py +102 -0
  603. fi/simulate/runtime/report.py +174 -0
  604. fi/simulate/runtime/run.py +75 -0
  605. fi/simulate/runtime/runner.py +333 -0
  606. fi/simulate/runtime/spec.py +186 -0
  607. fi/simulate/simulation/__init__.py +30 -0
  608. fi/simulate/simulation/behavior_policy.py +425 -0
  609. fi/simulate/simulation/bridge/__init__.py +9 -0
  610. fi/simulate/simulation/bridge/audio.py +29 -0
  611. fi/simulate/simulation/bridge/connector.py +46 -0
  612. fi/simulate/simulation/bridge/livekit.py +252 -0
  613. fi/simulate/simulation/bridge/retell.py +188 -0
  614. fi/simulate/simulation/bridge/vapi.py +177 -0
  615. fi/simulate/simulation/contract.py +419 -0
  616. fi/simulate/simulation/engines/__init__.py +12 -0
  617. fi/simulate/simulation/engines/base.py +21 -0
  618. fi/simulate/simulation/engines/cloud.py +517 -0
  619. fi/simulate/simulation/engines/livekit.py +4167 -0
  620. fi/simulate/simulation/engines/local_text.py +89 -0
  621. fi/simulate/simulation/fidelity.py +374 -0
  622. fi/simulate/simulation/gemini_tts_stream.py +110 -0
  623. fi/simulate/simulation/generator.py +91 -0
  624. fi/simulate/simulation/goal_machine.py +185 -0
  625. fi/simulate/simulation/livekit_models.py +467 -0
  626. fi/simulate/simulation/matrix.py +170 -0
  627. fi/simulate/simulation/models.py +279 -0
  628. fi/simulate/simulation/runner.py +153 -0
  629. fi/simulate/simulation/synthetic.py +880 -0
  630. fi/simulate/simulation/voice_prompt.py +502 -0
  631. fi/simulate/simulator/__init__.py +55 -0
  632. fi/simulate/simulator/builtins.py +53 -0
  633. fi/simulate/suite.py +1288 -0
  634. fi/simulate/utils/routes.py +164 -0
  635. fi/simulate/voice.py +225 -0
  636. fi/simulate/voice_cli.py +182 -0
  637. fi/utils/__init__.py +1 -0
  638. fi/utils/constants.py +14 -0
  639. fi/utils/errors.py +200 -0
  640. fi/utils/executor.py +26 -0
  641. fi/utils/routes.py +119 -0
  642. fi/utils/utils.py +17 -0
@@ -0,0 +1,287 @@
1
+ """
2
+ Secrets Detection - Hardcoded Credentials.
3
+
4
+ Detects hardcoded secrets and credentials:
5
+ - CWE-798: Use of Hard-coded Credentials
6
+ - CWE-259: Use of Hard-coded Password
7
+ - CWE-321: Use of Hard-coded Cryptographic Key
8
+ - CWE-532: Insertion of Sensitive Information into Log File
9
+ """
10
+
11
+ import re
12
+ from typing import List, Optional
13
+
14
+ from .base import BaseDetector, register_detector
15
+ from ..types import (
16
+ SecurityFinding,
17
+ Severity,
18
+ VulnerabilityCategory,
19
+ )
20
+ from ..analyzer import AnalysisResult
21
+
22
+
23
+ @register_detector("hardcoded_secrets")
24
+ class HardcodedSecretsDetector(BaseDetector):
25
+ """
26
+ Detects hardcoded secrets and credentials (CWE-798, CWE-259, CWE-321).
27
+
28
+ Identifies:
29
+ - Hardcoded passwords
30
+ - API keys
31
+ - Secret tokens
32
+ - Private keys
33
+ - Database connection strings
34
+
35
+ Examples of vulnerable code:
36
+ password = "secret123"
37
+ API_KEY = "sk-1234567890abcdef"
38
+ conn_str = "postgres://user:pass@host/db"
39
+ """
40
+
41
+ name = "hardcoded_secrets"
42
+ cwe_ids = ["CWE-798", "CWE-259", "CWE-321"]
43
+ category = VulnerabilityCategory.SECRETS
44
+ description = "Hardcoded credentials and secrets"
45
+ default_severity = Severity.HIGH
46
+
47
+ # Variable names that typically contain secrets
48
+ SECRET_VAR_PATTERNS = [
49
+ r"\b(password|passwd|pwd|pass)\s*=",
50
+ r"\b(secret|token|key|api_key|apikey|auth)\s*=",
51
+ r"\b(credential|cred)\s*=",
52
+ r"\b(private_key|privatekey|priv_key)\s*=",
53
+ r"\b(access_key|secret_key)\s*=",
54
+ r"\b(db_password|database_password)\s*=",
55
+ r"\b(jwt_secret|session_secret)\s*=",
56
+ r"\b(encryption_key|signing_key)\s*=",
57
+ ]
58
+
59
+ # Patterns for specific API keys
60
+ API_KEY_PATTERNS = [
61
+ # OpenAI
62
+ (r"sk-[a-zA-Z0-9]{48}", "OpenAI API Key"),
63
+ # AWS
64
+ (r"AKIA[0-9A-Z]{16}", "AWS Access Key ID"),
65
+ (r"[a-zA-Z0-9/+=]{40}", "Potential AWS Secret Key"),
66
+ # Google
67
+ (r"AIza[0-9A-Za-z_-]{35}", "Google API Key"),
68
+ # GitHub
69
+ (r"ghp_[a-zA-Z0-9]{36}", "GitHub Personal Access Token"),
70
+ (r"gho_[a-zA-Z0-9]{36}", "GitHub OAuth Token"),
71
+ (r"ghs_[a-zA-Z0-9]{36}", "GitHub Server Token"),
72
+ # Stripe
73
+ (r"sk_live_[a-zA-Z0-9]{24}", "Stripe Live Secret Key"),
74
+ (r"sk_test_[a-zA-Z0-9]{24}", "Stripe Test Secret Key"),
75
+ # Slack
76
+ (r"xoxb-[a-zA-Z0-9-]+", "Slack Bot Token"),
77
+ (r"xoxp-[a-zA-Z0-9-]+", "Slack User Token"),
78
+ # Generic patterns
79
+ (r"Bearer\s+[a-zA-Z0-9_-]{20,}", "Bearer Token"),
80
+ (r"Basic\s+[a-zA-Z0-9+/=]{20,}", "Basic Auth Credentials"),
81
+ ]
82
+
83
+ # Connection string patterns
84
+ CONNECTION_STRING_PATTERNS = [
85
+ (r"(postgres|mysql|mongodb|redis)://[^:]+:[^@]+@", "Database Connection String with Password"),
86
+ (r"mongodb\+srv://[^:]+:[^@]+@", "MongoDB Connection String with Password"),
87
+ (r"amqp://[^:]+:[^@]+@", "RabbitMQ Connection String"),
88
+ ]
89
+
90
+ # Private key patterns
91
+ PRIVATE_KEY_PATTERNS = [
92
+ (r"-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----", "Private Key"),
93
+ (r"-----BEGIN\s+EC\s+PRIVATE\s+KEY-----", "EC Private Key"),
94
+ (r"-----BEGIN\s+DSA\s+PRIVATE\s+KEY-----", "DSA Private Key"),
95
+ (r"-----BEGIN\s+OPENSSH\s+PRIVATE\s+KEY-----", "OpenSSH Private Key"),
96
+ (r"-----BEGIN\s+PGP\s+PRIVATE\s+KEY\s+BLOCK-----", "PGP Private Key"),
97
+ ]
98
+
99
+ # Values to exclude (not secrets)
100
+ SAFE_VALUE_PATTERNS = [
101
+ r"^[\"']?$", # Empty string
102
+ r"^[\"']?(None|null|undefined|placeholder|TODO|FIXME)[\"']?$",
103
+ r"^[\"']?<.*>[\"']?$", # Placeholder like <password>
104
+ r"^[\"']?\$\{.*\}[\"']?$", # Environment variable
105
+ r"^[\"']?%.*%[\"']?$", # Windows env var
106
+ r"os\.environ", # Environment lookup
107
+ r"getenv\(", # Environment lookup
108
+ r"process\.env", # Node.js env
109
+ r"config\[", # Config lookup
110
+ r"settings\.", # Settings lookup
111
+ ]
112
+
113
+ def detect(
114
+ self,
115
+ code: str,
116
+ language: str,
117
+ analysis: Optional[AnalysisResult] = None,
118
+ ) -> List[SecurityFinding]:
119
+ """Detect hardcoded secrets."""
120
+ if not self.enabled:
121
+ return []
122
+
123
+ findings = []
124
+ lines = code.split("\n")
125
+
126
+ for i, line in enumerate(lines, 1):
127
+ # Skip comments
128
+ stripped = line.strip()
129
+ if stripped.startswith(("#", "//", "*", "/*")):
130
+ continue
131
+
132
+ # Check for secret variable assignments
133
+ for pattern in self.SECRET_VAR_PATTERNS:
134
+ if re.search(pattern, line, re.IGNORECASE):
135
+ if not self._is_safe_value(line):
136
+ # Extract the value being assigned
137
+ value_match = re.search(r'=\s*["\']([^"\']+)["\']', line)
138
+ if value_match and len(value_match.group(1)) >= 4:
139
+ findings.append(self.create_finding(
140
+ vulnerability_type="Hardcoded Credentials",
141
+ description="Potential hardcoded secret in variable assignment",
142
+ line=i,
143
+ snippet=self._redact_secret(line.strip()[:100]),
144
+ confidence=0.85,
145
+ cwe_id="CWE-798",
146
+ suggested_fix="Use environment variables or a secrets manager instead of hardcoding.",
147
+ ))
148
+ break
149
+
150
+ # Check for API keys
151
+ for pattern, key_type in self.API_KEY_PATTERNS:
152
+ if re.search(pattern, line):
153
+ findings.append(self.create_finding(
154
+ vulnerability_type="Hardcoded API Key",
155
+ description=f"Detected {key_type}",
156
+ line=i,
157
+ snippet=self._redact_secret(line.strip()[:100]),
158
+ severity=Severity.HIGH,
159
+ confidence=0.95,
160
+ cwe_id="CWE-798",
161
+ suggested_fix="Store API keys in environment variables or a secrets manager.",
162
+ ))
163
+ break
164
+
165
+ # Check for connection strings
166
+ for pattern, conn_type in self.CONNECTION_STRING_PATTERNS:
167
+ if re.search(pattern, line, re.IGNORECASE):
168
+ findings.append(self.create_finding(
169
+ vulnerability_type="Hardcoded Connection String",
170
+ description=f"Detected {conn_type}",
171
+ line=i,
172
+ snippet=self._redact_secret(line.strip()[:100]),
173
+ severity=Severity.HIGH,
174
+ confidence=0.9,
175
+ cwe_id="CWE-259",
176
+ suggested_fix="Use environment variables for database credentials.",
177
+ ))
178
+ break
179
+
180
+ # Check for private keys
181
+ for pattern, key_type in self.PRIVATE_KEY_PATTERNS:
182
+ if re.search(pattern, line):
183
+ findings.append(self.create_finding(
184
+ vulnerability_type="Embedded Private Key",
185
+ description=f"Detected {key_type} in source code",
186
+ line=i,
187
+ snippet=line.strip()[:50] + "...[REDACTED]",
188
+ severity=Severity.CRITICAL,
189
+ confidence=0.99,
190
+ cwe_id="CWE-321",
191
+ suggested_fix="Never embed private keys in source code. Use secure key management.",
192
+ ))
193
+ break
194
+
195
+ return findings
196
+
197
+ def _is_safe_value(self, line: str) -> bool:
198
+ """Check if the assigned value is a safe pattern (not a hardcoded secret)."""
199
+ return any(re.search(p, line, re.IGNORECASE) for p in self.SAFE_VALUE_PATTERNS)
200
+
201
+ def _redact_secret(self, text: str) -> str:
202
+ """Redact potential secrets from text."""
203
+ # Redact values in quotes
204
+ text = re.sub(r'(["\'])([^"\']{4})[^"\']*([^"\']{2})\1', r'\1\2****\3\1', text)
205
+ # Redact API keys
206
+ text = re.sub(r'(sk-|ghp_|gho_|sk_live_|sk_test_)[a-zA-Z0-9]{4}[a-zA-Z0-9]*', r'\1****', text)
207
+ return text
208
+
209
+
210
+ @register_detector("sensitive_logging")
211
+ class SensitiveLoggingDetector(BaseDetector):
212
+ """
213
+ Detects logging of sensitive information (CWE-532).
214
+
215
+ Identifies:
216
+ - Logging passwords or tokens
217
+ - Printing sensitive variables
218
+ - Debug output with credentials
219
+
220
+ Examples of vulnerable code:
221
+ print(f"Password: {password}")
222
+ logger.info(f"Token: {api_token}")
223
+ console.log("Secret:", secret)
224
+ """
225
+
226
+ name = "sensitive_logging"
227
+ cwe_ids = ["CWE-532"]
228
+ category = VulnerabilityCategory.INFORMATION
229
+ description = "Sensitive information in log output"
230
+ default_severity = Severity.MEDIUM
231
+
232
+ LOGGING_FUNCTIONS = {
233
+ "python": ["print", "logging", "logger", "log"],
234
+ "javascript": ["console.log", "console.info", "console.debug", "console.warn"],
235
+ "java": ["System.out.print", "logger.info", "logger.debug", "log.info"],
236
+ }
237
+
238
+ SENSITIVE_TERMS = [
239
+ "password", "passwd", "pwd", "secret", "token", "key",
240
+ "credential", "api_key", "apikey", "auth", "bearer",
241
+ "private", "ssn", "credit_card", "cvv",
242
+ ]
243
+
244
+ def detect(
245
+ self,
246
+ code: str,
247
+ language: str,
248
+ analysis: Optional[AnalysisResult] = None,
249
+ ) -> List[SecurityFinding]:
250
+ """Detect sensitive information being logged."""
251
+ if not self.enabled:
252
+ return []
253
+
254
+ findings = []
255
+ lines = code.split("\n")
256
+ lang_lower = language.lower()
257
+
258
+ log_funcs = self.LOGGING_FUNCTIONS.get(lang_lower, self.LOGGING_FUNCTIONS["python"])
259
+
260
+ for i, line in enumerate(lines, 1):
261
+ line_lower = line.lower()
262
+
263
+ # Check if this is a logging line
264
+ is_logging = any(func in line_lower for func in log_funcs)
265
+ if not is_logging:
266
+ continue
267
+
268
+ # Check for sensitive terms
269
+ for term in self.SENSITIVE_TERMS:
270
+ if term in line_lower:
271
+ findings.append(self.create_finding(
272
+ vulnerability_type="Sensitive Data Logging",
273
+ description=f"Potentially logging sensitive data: '{term}'",
274
+ line=i,
275
+ snippet=line.strip()[:100],
276
+ confidence=0.7,
277
+ suggested_fix="Remove sensitive data from log statements or mask the values.",
278
+ ))
279
+ break
280
+
281
+ return findings
282
+
283
+
284
+ __all__ = [
285
+ "HardcodedSecretsDetector",
286
+ "SensitiveLoggingDetector",
287
+ ]
@@ -0,0 +1,192 @@
1
+ """
2
+ Serialization Vulnerability Detectors.
3
+
4
+ Detects unsafe deserialization vulnerabilities:
5
+ - CWE-502: Deserialization of Untrusted Data
6
+ """
7
+
8
+ import re
9
+ from typing import List, Optional
10
+
11
+ from .base import BaseDetector, register_detector
12
+ from ..types import (
13
+ SecurityFinding,
14
+ Severity,
15
+ VulnerabilityCategory,
16
+ )
17
+ from ..analyzer import AnalysisResult
18
+
19
+
20
+ @register_detector("unsafe_deserialization")
21
+ class UnsafeDeserializationDetector(BaseDetector):
22
+ """
23
+ Detects unsafe deserialization (CWE-502).
24
+
25
+ Identifies:
26
+ - pickle.loads with untrusted data
27
+ - yaml.load without safe_load
28
+ - Unsafe JSON deserialization with code execution
29
+ - Java ObjectInputStream
30
+
31
+ Examples of vulnerable code:
32
+ pickle.loads(user_data)
33
+ yaml.load(data) # without Loader=SafeLoader
34
+ marshal.loads(data)
35
+ """
36
+
37
+ name = "unsafe_deserialization"
38
+ cwe_ids = ["CWE-502"]
39
+ category = VulnerabilityCategory.SERIALIZATION
40
+ description = "Deserialization of untrusted data"
41
+ default_severity = Severity.CRITICAL
42
+
43
+ UNSAFE_PATTERNS = {
44
+ "python": [
45
+ # Pickle
46
+ (r"pickle\.loads?\s*\(", "pickle.load(s) can execute arbitrary code", Severity.CRITICAL),
47
+ (r"cPickle\.loads?\s*\(", "cPickle.load(s) can execute arbitrary code", Severity.CRITICAL),
48
+ (r"_pickle\.loads?\s*\(", "_pickle.load(s) can execute arbitrary code", Severity.CRITICAL),
49
+ # YAML
50
+ (r"yaml\.load\s*\([^)]*\)", "yaml.load without SafeLoader can execute code", Severity.HIGH),
51
+ (r"yaml\.unsafe_load\s*\(", "yaml.unsafe_load can execute code", Severity.CRITICAL),
52
+ # Marshal
53
+ (r"marshal\.loads?\s*\(", "marshal.load(s) can execute arbitrary code", Severity.CRITICAL),
54
+ # Shelve
55
+ (r"shelve\.open\s*\(", "shelve.open can execute code on load", Severity.HIGH),
56
+ # Dill
57
+ (r"dill\.loads?\s*\(", "dill.load(s) can execute arbitrary code", Severity.CRITICAL),
58
+ ],
59
+ "javascript": [
60
+ # Node.js serialize
61
+ (r"serialize\.unserialize\s*\(", "node-serialize unserialize can execute code", Severity.CRITICAL),
62
+ # eval-based JSON
63
+ (r"eval\s*\(\s*['\"]?\s*\(", "eval used for parsing", Severity.CRITICAL),
64
+ ],
65
+ "java": [
66
+ # ObjectInputStream
67
+ (r"ObjectInputStream\s*\(", "ObjectInputStream can execute arbitrary code", Severity.CRITICAL),
68
+ (r"\.readObject\s*\(", "readObject can execute arbitrary code", Severity.CRITICAL),
69
+ # XMLDecoder
70
+ (r"XMLDecoder\s*\(", "XMLDecoder can execute arbitrary code", Severity.CRITICAL),
71
+ # XStream
72
+ (r"XStream\.fromXML\s*\(", "XStream can execute arbitrary code", Severity.CRITICAL),
73
+ # SnakeYAML
74
+ (r"new\s+Yaml\s*\(\s*\)", "SnakeYAML without SafeConstructor", Severity.HIGH),
75
+ ],
76
+ "php": [
77
+ (r"unserialize\s*\(", "unserialize can execute code via __wakeup", Severity.CRITICAL),
78
+ ],
79
+ }
80
+
81
+ # Safe patterns that indicate proper usage
82
+ SAFE_PATTERNS = {
83
+ "python": [
84
+ r"yaml\.safe_load",
85
+ r"Loader\s*=\s*SafeLoader",
86
+ r"Loader\s*=\s*yaml\.SafeLoader",
87
+ ],
88
+ "java": [
89
+ r"SafeConstructor",
90
+ r"setAllowedTypes",
91
+ ],
92
+ }
93
+
94
+ def detect(
95
+ self,
96
+ code: str,
97
+ language: str,
98
+ analysis: Optional[AnalysisResult] = None,
99
+ ) -> List[SecurityFinding]:
100
+ """Detect unsafe deserialization."""
101
+ if not self.enabled:
102
+ return []
103
+
104
+ findings = []
105
+ lines = code.split("\n")
106
+ lang_lower = language.lower()
107
+
108
+ patterns = self.UNSAFE_PATTERNS.get(lang_lower, [])
109
+ safe_patterns = self.SAFE_PATTERNS.get(lang_lower, [])
110
+
111
+ for i, line in enumerate(lines, 1):
112
+ # Skip if safe pattern is present
113
+ if any(re.search(p, line, re.IGNORECASE) for p in safe_patterns):
114
+ continue
115
+
116
+ for pattern, description, severity in patterns:
117
+ if re.search(pattern, line, re.IGNORECASE):
118
+ # Special case for yaml.load - check if SafeLoader is used
119
+ if "yaml.load" in pattern and "Loader" in line:
120
+ continue # Safe usage with Loader parameter
121
+
122
+ findings.append(self.create_finding(
123
+ vulnerability_type="Unsafe Deserialization",
124
+ description=description,
125
+ line=i,
126
+ snippet=line.strip()[:100],
127
+ severity=severity,
128
+ confidence=0.9,
129
+ suggested_fix="Use safe alternatives: json.loads, yaml.safe_load, or validate input before deserializing.",
130
+ ))
131
+
132
+ return findings
133
+
134
+
135
+ @register_detector("json_injection")
136
+ class JSONInjectionDetector(BaseDetector):
137
+ """
138
+ Detects potential JSON injection vulnerabilities.
139
+
140
+ Identifies:
141
+ - String concatenation to build JSON
142
+ - Unescaped user input in JSON strings
143
+
144
+ Examples of vulnerable code:
145
+ json_str = '{"user": "' + user_input + '"}'
146
+ """
147
+
148
+ name = "json_injection"
149
+ cwe_ids = ["CWE-94"]
150
+ category = VulnerabilityCategory.INJECTION
151
+ description = "JSON injection via string concatenation"
152
+ default_severity = Severity.MEDIUM
153
+
154
+ JSON_CONCAT_PATTERNS = [
155
+ r'["\'][{[].*["\'].*\+', # JSON string concatenation
156
+ r'\+.*["\'][}\]].*["\']', # Concatenation with JSON
157
+ ]
158
+
159
+ def detect(
160
+ self,
161
+ code: str,
162
+ language: str,
163
+ analysis: Optional[AnalysisResult] = None,
164
+ ) -> List[SecurityFinding]:
165
+ """Detect JSON injection."""
166
+ if not self.enabled:
167
+ return []
168
+
169
+ findings = []
170
+ lines = code.split("\n")
171
+
172
+ for i, line in enumerate(lines, 1):
173
+ # Look for JSON-like patterns with concatenation
174
+ if any(re.search(p, line) for p in self.JSON_CONCAT_PATTERNS):
175
+ # Check for JSON structure indicators
176
+ if any(c in line for c in ['{', '[', '}']):
177
+ findings.append(self.create_finding(
178
+ vulnerability_type="JSON Injection",
179
+ description="Building JSON via string concatenation",
180
+ line=i,
181
+ snippet=line.strip()[:100],
182
+ confidence=0.7,
183
+ suggested_fix="Use json.dumps() to properly escape values.",
184
+ ))
185
+
186
+ return findings
187
+
188
+
189
+ __all__ = [
190
+ "UnsafeDeserializationDetector",
191
+ "JSONInjectionDetector",
192
+ ]