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.
- agent_learning_kit-0.1.0.dist-info/METADATA +381 -0
- agent_learning_kit-0.1.0.dist-info/RECORD +642 -0
- agent_learning_kit-0.1.0.dist-info/WHEEL +4 -0
- agent_learning_kit-0.1.0.dist-info/entry_points.txt +5 -0
- agent_learning_kit-0.1.0.dist-info/licenses/LICENSE +173 -0
- agent_learning_kit-0.1.0.dist-info/licenses/NOTICE +7 -0
- fi/__init__.py +5 -0
- fi/alk/__init__.py +57 -0
- fi/alk/_facade.py +31 -0
- fi/alk/_module_alias.py +68 -0
- fi/alk/_paths.py +14 -0
- fi/alk/_schema.py +522 -0
- fi/alk/actions.py +727 -0
- fi/alk/bench/__init__.py +517 -0
- fi/alk/bench/_codeexec.py +213 -0
- fi/alk/bench/_coding.py +215 -0
- fi/alk/bench/_docker.py +237 -0
- fi/alk/bench/_grader.py +286 -0
- fi/alk/bench/_pull.py +212 -0
- fi/alk/bench/_voice.py +147 -0
- fi/alk/capabilities.py +627 -0
- fi/alk/cli.py +6396 -0
- fi/alk/config.py +130 -0
- fi/alk/cua_loop.py +562 -0
- fi/alk/evals.py +2351 -0
- fi/alk/extensions.py +163 -0
- fi/alk/harness/ARCHITECTURE.md +231 -0
- fi/alk/harness/DESIGN.md +246 -0
- fi/alk/harness/ENVIRONMENT_CONFORMANCE.md +127 -0
- fi/alk/harness/HOW-IT-WORKS.md +297 -0
- fi/alk/harness/IMPLEMENTATION_AND_VALIDATION_STATUS.md +229 -0
- fi/alk/harness/README.md +417 -0
- fi/alk/harness/__init__.py +77 -0
- fi/alk/harness/__main__.py +3 -0
- fi/alk/harness/amend.py +312 -0
- fi/alk/harness/artifacts.py +319 -0
- fi/alk/harness/authoring_entrypoint.py +189 -0
- fi/alk/harness/authoring_runtime_validation.py +267 -0
- fi/alk/harness/backends/README.md +43 -0
- fi/alk/harness/backends/__init__.py +122 -0
- fi/alk/harness/backends/base.py +241 -0
- fi/alk/harness/backends/claude.py +211 -0
- fi/alk/harness/backends/files.py +182 -0
- fi/alk/harness/backends/vertex_gemini.py +457 -0
- fi/alk/harness/background_noise.py +95 -0
- fi/alk/harness/build.py +385 -0
- fi/alk/harness/bundle.py +593 -0
- fi/alk/harness/bundle_author_v2.py +1831 -0
- fi/alk/harness/bundle_v2.py +719 -0
- fi/alk/harness/call_runner.py +1440 -0
- fi/alk/harness/callback_http_adapter.py +111 -0
- fi/alk/harness/catalogue.py +287 -0
- fi/alk/harness/chat.py +428 -0
- fi/alk/harness/chat_call_runner.py +506 -0
- fi/alk/harness/checks.py +136 -0
- fi/alk/harness/cli.py +1354 -0
- fi/alk/harness/config.py +338 -0
- fi/alk/harness/contract.py +718 -0
- fi/alk/harness/credentials.py +674 -0
- fi/alk/harness/data/persona_vocabulary.json +111 -0
- fi/alk/harness/environment.py +99 -0
- fi/alk/harness/environment_plan.py +168 -0
- fi/alk/harness/events.py +125 -0
- fi/alk/harness/executor.py +304 -0
- fi/alk/harness/folder.py +234 -0
- fi/alk/harness/generated_runtime.py +815 -0
- fi/alk/harness/github.py +72 -0
- fi/alk/harness/hosted_authoring_entrypoint.py +183 -0
- fi/alk/harness/hosted_entrypoint.py +2402 -0
- fi/alk/harness/hosted_scheduler.py +2218 -0
- fi/alk/harness/job.py +426 -0
- fi/alk/harness/judge.py +184 -0
- fi/alk/harness/livekit_source.py +50 -0
- fi/alk/harness/livekit_tool_trace_bootstrap.py +71 -0
- fi/alk/harness/observability.py +208 -0
- fi/alk/harness/outbound.py +3252 -0
- fi/alk/harness/packaging.py +515 -0
- fi/alk/harness/persona_guides.py +157 -0
- fi/alk/harness/platform.py +692 -0
- fi/alk/harness/process_preflight.py +764 -0
- fi/alk/harness/process_runtime.py +5670 -0
- fi/alk/harness/prove.py +425 -0
- fi/alk/harness/provider_import.py +703 -0
- fi/alk/harness/provider_lifecycle.py +392 -0
- fi/alk/harness/provision.py +2896 -0
- fi/alk/harness/reception.py +147 -0
- fi/alk/harness/retell_chat_call_runner.py +373 -0
- fi/alk/harness/run/__init__.py +296 -0
- fi/alk/harness/run/alk.py +184 -0
- fi/alk/harness/run/call.py +162 -0
- fi/alk/harness/run/conversation.py +264 -0
- fi/alk/harness/run/data/voices_by_language_and_gender.json +693 -0
- fi/alk/harness/run/evidence.py +195 -0
- fi/alk/harness/run/grade.py +598 -0
- fi/alk/harness/run/live.py +297 -0
- fi/alk/harness/run/models.py +56 -0
- fi/alk/harness/run/platform_evals.py +227 -0
- fi/alk/harness/run/sdk_voice.py +130 -0
- fi/alk/harness/run/simulation.py +1209 -0
- fi/alk/harness/run/stage.py +91 -0
- fi/alk/harness/run/targets.py +508 -0
- fi/alk/harness/run/tools.py +601 -0
- fi/alk/harness/run/voice.py +340 -0
- fi/alk/harness/runtime.py +172 -0
- fi/alk/harness/sandbox_server.py +2011 -0
- fi/alk/harness/sandbox_worker.py +44 -0
- fi/alk/harness/scenario.py +1048 -0
- fi/alk/harness/scenario_source.py +879 -0
- fi/alk/harness/scenario_tools.py +1143 -0
- fi/alk/harness/scenarios.py +915 -0
- fi/alk/harness/secrets.py +168 -0
- fi/alk/harness/service_catalog.py +97 -0
- fi/alk/harness/session.py +391 -0
- fi/alk/harness/sessions.py +372 -0
- fi/alk/harness/simulator.py +76 -0
- fi/alk/harness/simulator_voice.py +928 -0
- fi/alk/harness/skills/build-environment/SKILL.md +538 -0
- fi/alk/harness/skills/harness.md +131 -0
- fi/alk/harness/skills/kinds/chat.md +48 -0
- fi/alk/harness/skills/kinds/voice-voicemail.md +63 -0
- fi/alk/harness/skills/kinds/voice.md +59 -0
- fi/alk/harness/skills/plan-suite/SKILL.md +103 -0
- fi/alk/harness/skills/provision-environment/SKILL.md +136 -0
- fi/alk/harness/skills/run-scenarios/SKILL.md +112 -0
- fi/alk/harness/skills/understand-agent/SKILL.md +251 -0
- fi/alk/harness/skills/write-scenarios/SKILL.md +606 -0
- fi/alk/harness/skills/write-scenarios/references/refusals.md +28 -0
- fi/alk/harness/skills/write-scenarios/references/world-api.md +92 -0
- fi/alk/harness/source_data_invariants.py +444 -0
- fi/alk/harness/source_tool_evidence.py +79 -0
- fi/alk/harness/sources.py +253 -0
- fi/alk/harness/spend.py +140 -0
- fi/alk/harness/tool_trace_proxy.py +104 -0
- fi/alk/harness/tools.py +1018 -0
- fi/alk/harness/understand.py +169 -0
- fi/alk/harness/voicemail_audio.py +74 -0
- fi/alk/harness/world/__init__.py +33 -0
- fi/alk/harness/world/errors.py +68 -0
- fi/alk/harness/world/expectations.py +91 -0
- fi/alk/harness/world/handle.py +538 -0
- fi/alk/harness/world/kinds.py +196 -0
- fi/alk/harness/world/mutate.py +186 -0
- fi/alk/harness/world/probe.py +413 -0
- fi/alk/harness/world/provision.py +511 -0
- fi/alk/harness/world/provisioned.py +191 -0
- fi/alk/harness/world/runtime.py +616 -0
- fi/alk/harness/world/snapshot.py +288 -0
- fi/alk/harness/world/stores/__init__.py +305 -0
- fi/alk/harness/world/stores/container.py +215 -0
- fi/alk/harness/world/stores/inprocess.py +346 -0
- fi/alk/harness/world/stores/postgres.py +481 -0
- fi/alk/harness/world/stores/prove.py +202 -0
- fi/alk/harness/world/stores/sqlite.py +245 -0
- fi/alk/harness/world/stores/written.py +182 -0
- fi/alk/harness/world/tools.py +1516 -0
- fi/alk/harness/world/workspace.py +144 -0
- fi/alk/image_loop.py +453 -0
- fi/alk/image_perturb.py +241 -0
- fi/alk/improve.py +274 -0
- fi/alk/live/__init__.py +154 -0
- fi/alk/live/_attribution.py +184 -0
- fi/alk/live/_capture.py +264 -0
- fi/alk/live/_codec.py +391 -0
- fi/alk/live/_contract.py +134 -0
- fi/alk/live/_loopback.py +316 -0
- fi/alk/live/_perturb.py +449 -0
- fi/alk/live/_runner.py +386 -0
- fi/alk/live/_stats.py +561 -0
- fi/alk/live/_transcript.py +240 -0
- fi/alk/live/_workers/__init__.py +9 -0
- fi/alk/live/_workers/a2a_worker.py +316 -0
- fi/alk/live/_workers/langgraph_worker.py +217 -0
- fi/alk/live/_workers/livekit_worker.py +207 -0
- fi/alk/live/_workers/mcp_loopback_server.py +46 -0
- fi/alk/live/_workers/mcp_worker.py +158 -0
- fi/alk/live/_workers/pipecat_worker.py +189 -0
- fi/alk/live/a2a_lane.py +138 -0
- fi/alk/live/langgraph_lane.py +339 -0
- fi/alk/live/livekit_lane.py +376 -0
- fi/alk/live/mcp_lane.py +172 -0
- fi/alk/live/pipecat_lane.py +341 -0
- fi/alk/live/voice_redteam.py +494 -0
- fi/alk/loss.py +306 -0
- fi/alk/optimize.py +36260 -0
- fi/alk/practice/__init__.py +51 -0
- fi/alk/practice/_assess.py +103 -0
- fi/alk/practice/_budget.py +81 -0
- fi/alk/practice/_calibrate.py +69 -0
- fi/alk/practice/_capstone.py +86 -0
- fi/alk/practice/_contract.py +91 -0
- fi/alk/practice/_diagnose.py +79 -0
- fi/alk/practice/_drill.py +196 -0
- fi/alk/practice/_experiment.py +720 -0
- fi/alk/practice/_schedule.py +102 -0
- fi/alk/practice/_store.py +194 -0
- fi/alk/practice/_trainer.py +245 -0
- fi/alk/practice/_update.py +125 -0
- fi/alk/redteam.py +2621 -0
- fi/alk/rewardhack.py +237 -0
- fi/alk/simulate.py +10351 -0
- fi/alk/studio/__init__.py +82 -0
- fi/alk/studio/_bias.py +314 -0
- fi/alk/studio/_calibration.py +522 -0
- fi/alk/studio/_coverage.py +262 -0
- fi/alk/studio/_download.py +665 -0
- fi/alk/studio/_fidelity_attack.py +114 -0
- fi/alk/studio/_generate.py +652 -0
- fi/alk/studio/_library.py +370 -0
- fi/alk/studio/_scan.py +134 -0
- fi/alk/studio/_upgrade.py +42 -0
- fi/alk/studio/_vendor.py +172 -0
- fi/alk/suite.py +4200 -0
- fi/alk/tasks.py +828 -0
- fi/alk/telemetry/__init__.py +149 -0
- fi/alk/telemetry/_contract.py +141 -0
- fi/alk/telemetry/_emit.py +182 -0
- fi/alk/telemetry/_ledger.py +296 -0
- fi/alk/telemetry/_queue.py +127 -0
- fi/alk/telemetry/_row.py +294 -0
- fi/alk/telemetry/_run.py +233 -0
- fi/alk/telemetry/_sync.py +193 -0
- fi/alk/telemetry/_url.py +119 -0
- fi/alk/trinity.py +49397 -0
- fi/alk/voice_loop.py +174 -0
- fi/api/__init__.py +1 -0
- fi/api/auth.py +137 -0
- fi/api/types.py +29 -0
- fi/cli/__init__.py +9 -0
- fi/cli/assertions/__init__.py +25 -0
- fi/cli/assertions/conditions.py +76 -0
- fi/cli/assertions/evaluator.py +286 -0
- fi/cli/assertions/exit_codes.py +20 -0
- fi/cli/assertions/parser.py +131 -0
- fi/cli/assertions/reporter.py +194 -0
- fi/cli/commands/__init__.py +9 -0
- fi/cli/commands/config.py +165 -0
- fi/cli/commands/export.py +208 -0
- fi/cli/commands/init.py +112 -0
- fi/cli/commands/list_cmd.py +213 -0
- fi/cli/commands/run.py +486 -0
- fi/cli/commands/validate.py +173 -0
- fi/cli/commands/view.py +424 -0
- fi/cli/config/__init__.py +6 -0
- fi/cli/config/defaults.py +206 -0
- fi/cli/config/loader.py +155 -0
- fi/cli/config/schema.py +174 -0
- fi/cli/main.py +78 -0
- fi/cli/output/__init__.py +6 -0
- fi/cli/output/formatters.py +106 -0
- fi/cli/output/reporters.py +46 -0
- fi/cli/storage/__init__.py +5 -0
- fi/cli/storage/run_history.py +249 -0
- fi/cli/utils/__init__.py +5 -0
- fi/cli/utils/console.py +44 -0
- fi/evals/__init__.py +131 -0
- fi/evals/autoeval/__init__.py +137 -0
- fi/evals/autoeval/analyzer.py +211 -0
- fi/evals/autoeval/config.py +244 -0
- fi/evals/autoeval/export.py +213 -0
- fi/evals/autoeval/interactive.py +283 -0
- fi/evals/autoeval/pipeline.py +625 -0
- fi/evals/autoeval/prompts.py +139 -0
- fi/evals/autoeval/recommender.py +242 -0
- fi/evals/autoeval/rules.py +589 -0
- fi/evals/autoeval/templates.py +299 -0
- fi/evals/autoeval/types.py +232 -0
- fi/evals/core/__init__.py +16 -0
- fi/evals/core/cloud_registry.py +184 -0
- fi/evals/core/engines.py +368 -0
- fi/evals/core/evaluate.py +319 -0
- fi/evals/core/judge_prompt.py +90 -0
- fi/evals/core/prompt_generator.py +83 -0
- fi/evals/core/registry.py +57 -0
- fi/evals/core/result.py +55 -0
- fi/evals/evaluator.py +721 -0
- fi/evals/execution.py +168 -0
- fi/evals/feedback/__init__.py +32 -0
- fi/evals/feedback/calibrator.py +160 -0
- fi/evals/feedback/collector.py +214 -0
- fi/evals/feedback/hooks.py +81 -0
- fi/evals/feedback/retriever.py +128 -0
- fi/evals/feedback/store.py +272 -0
- fi/evals/feedback/types.py +99 -0
- fi/evals/framework/README.md +79 -0
- fi/evals/framework/__init__.py +267 -0
- fi/evals/framework/backends/Dockerfile.eval-runner +33 -0
- fi/evals/framework/backends/__init__.py +99 -0
- fi/evals/framework/backends/_container.py +141 -0
- fi/evals/framework/backends/_utils.py +145 -0
- fi/evals/framework/backends/base.py +223 -0
- fi/evals/framework/backends/celery_backend.py +417 -0
- fi/evals/framework/backends/celery_worker.py +78 -0
- fi/evals/framework/backends/kubernetes_backend.py +665 -0
- fi/evals/framework/backends/ray_backend.py +521 -0
- fi/evals/framework/backends/temporal.py +350 -0
- fi/evals/framework/backends/temporal_worker.py +126 -0
- fi/evals/framework/backends/thread_pool.py +286 -0
- fi/evals/framework/context.py +258 -0
- fi/evals/framework/enrichment.py +306 -0
- fi/evals/framework/evals/__init__.py +68 -0
- fi/evals/framework/evals/agentic.py +399 -0
- fi/evals/framework/evals/builder.py +609 -0
- fi/evals/framework/evals/semantic.py +142 -0
- fi/evals/framework/evaluator.py +647 -0
- fi/evals/framework/evaluators/__init__.py +22 -0
- fi/evals/framework/evaluators/blocking.py +347 -0
- fi/evals/framework/evaluators/non_blocking.py +577 -0
- fi/evals/framework/propagation.py +421 -0
- fi/evals/framework/protocols.py +385 -0
- fi/evals/framework/registry.py +370 -0
- fi/evals/framework/resilience/__init__.py +150 -0
- fi/evals/framework/resilience/circuit_breaker.py +309 -0
- fi/evals/framework/resilience/degradation.py +355 -0
- fi/evals/framework/resilience/health.py +505 -0
- fi/evals/framework/resilience/rate_limiter.py +228 -0
- fi/evals/framework/resilience/retry.py +274 -0
- fi/evals/framework/resilience/types.py +288 -0
- fi/evals/framework/resilience/wrapper.py +433 -0
- fi/evals/framework/types.py +218 -0
- fi/evals/guardrails/README.md +915 -0
- fi/evals/guardrails/__init__.py +96 -0
- fi/evals/guardrails/backends/__init__.py +43 -0
- fi/evals/guardrails/backends/azure.py +361 -0
- fi/evals/guardrails/backends/base.py +88 -0
- fi/evals/guardrails/backends/generic_llm.py +163 -0
- fi/evals/guardrails/backends/granite.py +216 -0
- fi/evals/guardrails/backends/llamaguard.py +221 -0
- fi/evals/guardrails/backends/local_base.py +479 -0
- fi/evals/guardrails/backends/openai.py +365 -0
- fi/evals/guardrails/backends/qwen.py +170 -0
- fi/evals/guardrails/backends/shieldgemma.py +154 -0
- fi/evals/guardrails/backends/turing.py +235 -0
- fi/evals/guardrails/backends/vllm_client.py +321 -0
- fi/evals/guardrails/backends/wildguard.py +188 -0
- fi/evals/guardrails/base.py +888 -0
- fi/evals/guardrails/config.py +221 -0
- fi/evals/guardrails/discovery.py +243 -0
- fi/evals/guardrails/gateway.py +437 -0
- fi/evals/guardrails/registry.py +231 -0
- fi/evals/guardrails/scanners/__init__.py +127 -0
- fi/evals/guardrails/scanners/base.py +191 -0
- fi/evals/guardrails/scanners/code_injection.py +243 -0
- fi/evals/guardrails/scanners/eval_delegate.py +574 -0
- fi/evals/guardrails/scanners/invisible_chars.py +351 -0
- fi/evals/guardrails/scanners/jailbreak.py +412 -0
- fi/evals/guardrails/scanners/language.py +288 -0
- fi/evals/guardrails/scanners/pipeline.py +260 -0
- fi/evals/guardrails/scanners/regex.py +311 -0
- fi/evals/guardrails/scanners/secrets.py +274 -0
- fi/evals/guardrails/scanners/topics.py +649 -0
- fi/evals/guardrails/scanners/urls.py +341 -0
- fi/evals/guardrails/types.py +96 -0
- fi/evals/llm/__init__.py +3 -0
- fi/evals/llm/base_llm_provider.py +35 -0
- fi/evals/llm/providers/litellm.py +70 -0
- fi/evals/local/__init__.py +90 -0
- fi/evals/local/evaluator.py +690 -0
- fi/evals/local/execution_mode.py +121 -0
- fi/evals/local/llm.py +489 -0
- fi/evals/local/metrics/__init__.py +19 -0
- fi/evals/local/registry.py +360 -0
- fi/evals/manager.py +1018 -0
- fi/evals/manager_types.py +362 -0
- fi/evals/metrics/__init__.py +185 -0
- fi/evals/metrics/agents/__init__.py +74 -0
- fi/evals/metrics/agents/metrics.py +693 -0
- fi/evals/metrics/agents/report.py +36463 -0
- fi/evals/metrics/agents/types.py +160 -0
- fi/evals/metrics/base_llm_metric.py +111 -0
- fi/evals/metrics/base_metric.py +138 -0
- fi/evals/metrics/code_security/__init__.py +305 -0
- fi/evals/metrics/code_security/analyzer.py +985 -0
- fi/evals/metrics/code_security/benchmarks/__init__.py +73 -0
- fi/evals/metrics/code_security/benchmarks/builtin.py +750 -0
- fi/evals/metrics/code_security/benchmarks/loader.py +580 -0
- fi/evals/metrics/code_security/benchmarks/types.py +308 -0
- fi/evals/metrics/code_security/detectors/__init__.py +186 -0
- fi/evals/metrics/code_security/detectors/base.py +394 -0
- fi/evals/metrics/code_security/detectors/cryptography.py +345 -0
- fi/evals/metrics/code_security/detectors/injection.py +744 -0
- fi/evals/metrics/code_security/detectors/secrets.py +287 -0
- fi/evals/metrics/code_security/detectors/serialization.py +192 -0
- fi/evals/metrics/code_security/joint_metrics.py +588 -0
- fi/evals/metrics/code_security/judges/__init__.py +83 -0
- fi/evals/metrics/code_security/judges/base.py +238 -0
- fi/evals/metrics/code_security/judges/dual_judge.py +534 -0
- fi/evals/metrics/code_security/judges/llm_judge.py +301 -0
- fi/evals/metrics/code_security/judges/pattern_judge.py +515 -0
- fi/evals/metrics/code_security/metrics.py +388 -0
- fi/evals/metrics/code_security/modes/__init__.py +63 -0
- fi/evals/metrics/code_security/modes/adversarial.py +284 -0
- fi/evals/metrics/code_security/modes/autocomplete.py +198 -0
- fi/evals/metrics/code_security/modes/base.py +283 -0
- fi/evals/metrics/code_security/modes/instruct.py +253 -0
- fi/evals/metrics/code_security/modes/repair.py +230 -0
- fi/evals/metrics/code_security/reports/__init__.py +57 -0
- fi/evals/metrics/code_security/reports/generator.py +404 -0
- fi/evals/metrics/code_security/reports/leaderboard.py +509 -0
- fi/evals/metrics/code_security/types.py +534 -0
- fi/evals/metrics/function_calling/__init__.py +34 -0
- fi/evals/metrics/function_calling/metrics.py +573 -0
- fi/evals/metrics/function_calling/types.py +87 -0
- fi/evals/metrics/hallucination/__init__.py +54 -0
- fi/evals/metrics/hallucination/detector.py +149 -0
- fi/evals/metrics/hallucination/metrics.py +390 -0
- fi/evals/metrics/hallucination/nli.py +253 -0
- fi/evals/metrics/hallucination/sentinel.py +106 -0
- fi/evals/metrics/hallucination/types.py +132 -0
- fi/evals/metrics/heuristics/aggregation_metrics.py +85 -0
- fi/evals/metrics/heuristics/json_metrics.py +87 -0
- fi/evals/metrics/heuristics/similarity_metrics.py +375 -0
- fi/evals/metrics/heuristics/string_metrics.py +391 -0
- fi/evals/metrics/llm_as_judges/__init__.py +17 -0
- fi/evals/metrics/llm_as_judges/custom_judge/metric.py +112 -0
- fi/evals/metrics/llm_as_judges/custom_judge/prompts.py +26 -0
- fi/evals/metrics/llm_as_judges/types.py +48 -0
- fi/evals/metrics/rag/__init__.py +111 -0
- fi/evals/metrics/rag/advanced/__init__.py +14 -0
- fi/evals/metrics/rag/advanced/multi_hop.py +283 -0
- fi/evals/metrics/rag/advanced/source_attribution.py +344 -0
- fi/evals/metrics/rag/generation/__init__.py +17 -0
- fi/evals/metrics/rag/generation/answer_relevancy.py +176 -0
- fi/evals/metrics/rag/generation/context_utilization.py +245 -0
- fi/evals/metrics/rag/generation/faithfulness.py +241 -0
- fi/evals/metrics/rag/generation/groundedness.py +131 -0
- fi/evals/metrics/rag/rag_score.py +277 -0
- fi/evals/metrics/rag/retrieval/__init__.py +20 -0
- fi/evals/metrics/rag/retrieval/context_entity_recall.py +124 -0
- fi/evals/metrics/rag/retrieval/context_precision.py +158 -0
- fi/evals/metrics/rag/retrieval/context_recall.py +106 -0
- fi/evals/metrics/rag/retrieval/noise_sensitivity.py +163 -0
- fi/evals/metrics/rag/retrieval/ranking.py +261 -0
- fi/evals/metrics/rag/types.py +100 -0
- fi/evals/metrics/rag/utils/__init__.py +62 -0
- fi/evals/metrics/rag/utils/claims.py +189 -0
- fi/evals/metrics/rag/utils/entities.py +244 -0
- fi/evals/metrics/rag/utils/nli.py +92 -0
- fi/evals/metrics/rag/utils/similarity.py +345 -0
- fi/evals/metrics/structured/__init__.py +114 -0
- fi/evals/metrics/structured/field_completeness.py +313 -0
- fi/evals/metrics/structured/hierarchy_score.py +366 -0
- fi/evals/metrics/structured/json_validation.py +190 -0
- fi/evals/metrics/structured/schema_compliance.py +280 -0
- fi/evals/metrics/structured/structured_output_score.py +298 -0
- fi/evals/metrics/structured/types.py +108 -0
- fi/evals/metrics/structured/validators/__init__.py +30 -0
- fi/evals/metrics/structured/validators/base.py +189 -0
- fi/evals/metrics/structured/validators/json_validator.py +196 -0
- fi/evals/metrics/structured/validators/pydantic_validator.py +178 -0
- fi/evals/metrics/structured/validators/yaml_validator.py +248 -0
- fi/evals/otel/__init__.py +266 -0
- fi/evals/otel/config.py +400 -0
- fi/evals/otel/conventions.py +463 -0
- fi/evals/otel/enrichment.py +371 -0
- fi/evals/otel/instrumentors/__init__.py +140 -0
- fi/evals/otel/instrumentors/anthropic.py +517 -0
- fi/evals/otel/instrumentors/base.py +382 -0
- fi/evals/otel/instrumentors/openai.py +673 -0
- fi/evals/otel/processors/__init__.py +36 -0
- fi/evals/otel/processors/base.py +473 -0
- fi/evals/otel/processors/cost.py +445 -0
- fi/evals/otel/processors/evaluation.py +559 -0
- fi/evals/otel/processors/llm.py +462 -0
- fi/evals/otel/tracer.py +506 -0
- fi/evals/otel/types.py +232 -0
- fi/evals/otel_utils.py +23 -0
- fi/evals/protect.py +671 -0
- fi/evals/protect_input_adapter.py +154 -0
- fi/evals/streaming/__init__.py +88 -0
- fi/evals/streaming/buffer.py +213 -0
- fi/evals/streaming/evaluator.py +551 -0
- fi/evals/streaming/policy.py +307 -0
- fi/evals/streaming/scorers.py +368 -0
- fi/evals/streaming/types.py +238 -0
- fi/evals/templates.py +472 -0
- fi/evals/types.py +156 -0
- fi/opt/__init__.py +221 -0
- fi/opt/_objective_scoring.py +85 -0
- fi/opt/base/__init__.py +11 -0
- fi/opt/base/base_generator.py +33 -0
- fi/opt/base/base_mapper.py +26 -0
- fi/opt/base/base_optimizer.py +45 -0
- fi/opt/base/evaluator.py +211 -0
- fi/opt/components.py +3095 -0
- fi/opt/datamappers/__init__.py +3 -0
- fi/opt/datamappers/basic_mapper.py +40 -0
- fi/opt/deployment.py +1021 -0
- fi/opt/evidence.py +4332 -0
- fi/opt/generators/__init__.py +3 -0
- fi/opt/generators/litellm.py +66 -0
- fi/opt/integrations/__init__.py +23 -0
- fi/opt/integrations/generative_suite.py +410 -0
- fi/opt/integrations/simulate.py +1313 -0
- fi/opt/mutations.py +771 -0
- fi/opt/observability.py +4639 -0
- fi/opt/optimizer_trace.py +889 -0
- fi/opt/optimizers/__init__.py +80 -0
- fi/opt/optimizers/agent.py +331 -0
- fi/opt/optimizers/agent_bandit.py +392 -0
- fi/opt/optimizers/agent_curriculum.py +635 -0
- fi/opt/optimizers/agent_evolution.py +894 -0
- fi/opt/optimizers/agent_feedback.py +1863 -0
- fi/opt/optimizers/agent_pareto.py +547 -0
- fi/opt/optimizers/agent_social_memory.py +1113 -0
- fi/opt/optimizers/agent_tpe.py +321 -0
- fi/opt/optimizers/bayesian_search.py +449 -0
- fi/opt/optimizers/council.py +2075 -0
- fi/opt/optimizers/futureagi_replay.py +799 -0
- fi/opt/optimizers/gepa.py +322 -0
- fi/opt/optimizers/metaprompt.py +243 -0
- fi/opt/optimizers/promptwizard.py +417 -0
- fi/opt/optimizers/protegi.py +329 -0
- fi/opt/optimizers/random_search.py +224 -0
- fi/opt/research.py +518 -0
- fi/opt/simulation.py +260 -0
- fi/opt/targets.py +232 -0
- fi/opt/types.py +66 -0
- fi/opt/utils/__init__.py +4 -0
- fi/opt/utils/early_stopping.py +266 -0
- fi/opt/utils/setup_logging.py +82 -0
- fi/simulate/__init__.py +540 -0
- fi/simulate/_hashing.py +35 -0
- fi/simulate/_logging.py +10 -0
- fi/simulate/adapters.py +87 -0
- fi/simulate/agent/__init__.py +120 -0
- fi/simulate/agent/browser.py +658 -0
- fi/simulate/agent/definition.py +587 -0
- fi/simulate/agent/frameworks.py +3528 -0
- fi/simulate/agent/generic.py +8286 -0
- fi/simulate/agent/import_probe.py +227 -0
- fi/simulate/agent/memory.py +905 -0
- fi/simulate/agent/mocks.py +101 -0
- fi/simulate/agent/multi_agent.py +361 -0
- fi/simulate/agent/orchestration.py +903 -0
- fi/simulate/agent/realtime.py +665 -0
- fi/simulate/agent/wrapper.py +99 -0
- fi/simulate/agent/wrappers/__init__.py +18 -0
- fi/simulate/agent/wrappers/anthropic.py +62 -0
- fi/simulate/agent/wrappers/gemini.py +65 -0
- fi/simulate/agent/wrappers/http.py +404 -0
- fi/simulate/agent/wrappers/langchain.py +80 -0
- fi/simulate/agent/wrappers/openai.py +75 -0
- fi/simulate/agent/wrappers/websocket.py +326 -0
- fi/simulate/artifacts/__init__.py +11 -0
- fi/simulate/artifacts/manifest.py +62 -0
- fi/simulate/cli.py +20560 -0
- fi/simulate/endpoints/__init__.py +45 -0
- fi/simulate/endpoints/_http_actor.py +73 -0
- fi/simulate/endpoints/actor_sources.py +243 -0
- fi/simulate/endpoints/base.py +107 -0
- fi/simulate/endpoints/builtins.py +10 -0
- fi/simulate/endpoints/callable.py +95 -0
- fi/simulate/endpoints/http.py +76 -0
- fi/simulate/endpoints/livekit.py +138 -0
- fi/simulate/endpoints/originators.py +132 -0
- fi/simulate/endpoints/profiles.py +348 -0
- fi/simulate/endpoints/retell.py +633 -0
- fi/simulate/endpoints/vapi.py +205 -0
- fi/simulate/endpoints/websocket.py +76 -0
- fi/simulate/environment.py +33026 -0
- fi/simulate/environments/__init__.py +11 -0
- fi/simulate/environments/base.py +73 -0
- fi/simulate/environments/chat.py +697 -0
- fi/simulate/environments/voice.py +212 -0
- fi/simulate/evaluation/__init__.py +4 -0
- fi/simulate/evaluation/ai_eval.py +227 -0
- fi/simulate/evidence/__init__.py +35 -0
- fi/simulate/evidence/base.py +59 -0
- fi/simulate/evidence/caller_observed.py +50 -0
- fi/simulate/evidence/livekit_instrumentation.py +51 -0
- fi/simulate/evidence/livekit_room.py +50 -0
- fi/simulate/evidence/otel.py +49 -0
- fi/simulate/evidence/providers/__init__.py +24 -0
- fi/simulate/evidence/providers/base.py +61 -0
- fi/simulate/evidence/providers/retell.py +376 -0
- fi/simulate/evidence/providers/vapi.py +426 -0
- fi/simulate/hosted/__init__.py +32 -0
- fi/simulate/hosted/child_entrypoint.py +306 -0
- fi/simulate/hosted/job.py +150 -0
- fi/simulate/hosted/targets.py +53 -0
- fi/simulate/instrumentation/__init__.py +5 -0
- fi/simulate/instrumentation/livekit/__init__.py +122 -0
- fi/simulate/manifest.py +1033 -0
- fi/simulate/matrix_cli.py +165 -0
- fi/simulate/realtime/__init__.py +40 -0
- fi/simulate/realtime/events.py +107 -0
- fi/simulate/realtime/media.py +61 -0
- fi/simulate/realtime/session.py +91 -0
- fi/simulate/recording/__init__.py +5 -0
- fi/simulate/recording/room_recorder.py +326 -0
- fi/simulate/registry.py +185 -0
- fi/simulate/results/__init__.py +9 -0
- fi/simulate/results/base.py +18 -0
- fi/simulate/results/filesystem.py +71 -0
- fi/simulate/results/futureagi.py +1340 -0
- fi/simulate/runtime/__init__.py +85 -0
- fi/simulate/runtime/capabilities.py +40 -0
- fi/simulate/runtime/events.py +63 -0
- fi/simulate/runtime/failures.py +25 -0
- fi/simulate/runtime/ids.py +34 -0
- fi/simulate/runtime/plan.py +70 -0
- fi/simulate/runtime/planner.py +102 -0
- fi/simulate/runtime/report.py +174 -0
- fi/simulate/runtime/run.py +75 -0
- fi/simulate/runtime/runner.py +333 -0
- fi/simulate/runtime/spec.py +186 -0
- fi/simulate/simulation/__init__.py +30 -0
- fi/simulate/simulation/behavior_policy.py +425 -0
- fi/simulate/simulation/bridge/__init__.py +9 -0
- fi/simulate/simulation/bridge/audio.py +29 -0
- fi/simulate/simulation/bridge/connector.py +46 -0
- fi/simulate/simulation/bridge/livekit.py +252 -0
- fi/simulate/simulation/bridge/retell.py +188 -0
- fi/simulate/simulation/bridge/vapi.py +177 -0
- fi/simulate/simulation/contract.py +419 -0
- fi/simulate/simulation/engines/__init__.py +12 -0
- fi/simulate/simulation/engines/base.py +21 -0
- fi/simulate/simulation/engines/cloud.py +517 -0
- fi/simulate/simulation/engines/livekit.py +4167 -0
- fi/simulate/simulation/engines/local_text.py +89 -0
- fi/simulate/simulation/fidelity.py +374 -0
- fi/simulate/simulation/gemini_tts_stream.py +110 -0
- fi/simulate/simulation/generator.py +91 -0
- fi/simulate/simulation/goal_machine.py +185 -0
- fi/simulate/simulation/livekit_models.py +467 -0
- fi/simulate/simulation/matrix.py +170 -0
- fi/simulate/simulation/models.py +279 -0
- fi/simulate/simulation/runner.py +153 -0
- fi/simulate/simulation/synthetic.py +880 -0
- fi/simulate/simulation/voice_prompt.py +502 -0
- fi/simulate/simulator/__init__.py +55 -0
- fi/simulate/simulator/builtins.py +53 -0
- fi/simulate/suite.py +1288 -0
- fi/simulate/utils/routes.py +164 -0
- fi/simulate/voice.py +225 -0
- fi/simulate/voice_cli.py +182 -0
- fi/utils/__init__.py +1 -0
- fi/utils/constants.py +14 -0
- fi/utils/errors.py +200 -0
- fi/utils/executor.py +26 -0
- fi/utils/routes.py +119 -0
- 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
|
+
]
|