Matrice des injections et attaques
English: en/injection-matrix.md
Les tests sont dans services/control-plane/tests/ sauf mention contraire. Notation : fichier::test.
| Attaque | Couche | Contrôle | Réglages | Test qui le prouve | Risque résiduel |
|---|---|---|---|---|---|
| SSRF | Outils, MCP, connecteurs | eai.security.egress.EgressPolicy, check_url, address_verdict ; eai.integrations.outbound.validate_url à l'enregistrement et à l'appel | EAI_EGRESS_PRIVATE_ALLOWLIST, EAI_EGRESS_ALLOWED_PORTS, EAI_EGRESS_ALLOW_HTTP | test_security_egress.py::test_static_rejections, test_security_egress_wiring.py::test_tool_save_refused, test_security_egress_wiring.py::test_call_time_upstream_never_called | Liste blanche privée trop large ; la posture le signale |
| Rebinding DNS | Outils, MCP | GuardedTransport / GuardedAsyncTransport : connexion à l'adresse validée, toutes les réponses DNS vérifiées, redirections jamais suivies | EAI_EGRESS_DNS_TIMEOUT_SECONDS | test_security_egress.py::test_dns_rebinding_between_check_and_connect_is_blocked, test_security_egress.py::test_dns_answers_are_all_validated, test_security_egress.py::test_redirects_are_never_followed | Clients HTTP hors guarded_client (interdits par revue) |
| Tunnel DNS et exfiltration | Réseau | Cilium DNS L7 et default deny, deploy/cilium/baseline.yaml | Valeurs Cilium, network-dns-hardening | test_platform_security_manifests.py::test_default_deny_and_metadata_deny | Noms autorisés utilisables comme canal lent |
| Usurpation ARP et DNS via NET_RAW | Pods | Capacités supprimées, Kyverno deploy/policies/kyverno/pod-network-security.yaml | pod-security | test_platform_security_manifests.py::test_every_pod_spec_is_hardened, kyverno test deploy/policies/kyverno/tests (cas eai-pod-security/drop-all-capabilities et disallow-added-capabilities, ressource net-raw-pod) | Nœuds compromis |
| Métadonnées cloud | Réseau, application | address_verdict (link-local toujours refusé), politique Cilium de refus | aucun contournement possible | test_security_egress.py::test_metadata_and_link_local_stay_blocked_even_when_allowlisted, test_platform_security_manifests.py::test_kubernetes_flavour_excludes_metadata | Faible |
| Injection SQL | Données | Requêtes paramétrées, eai.db.ident, qualified, frag, set_clause, like_pattern, int_limit | aucun | test_security_sql_static.py::test_no_interpolated_sql_in_control_plane, test_security_sql_inputs.py::test_payloads_never_5xx_or_leak, test_security_sql_inputs.py::test_like_pattern_escapes, test_security_attack_suite.py::test_injection_fuzz | Nouveau code hors vérificateur statique |
| Injection ClickHouse | Observabilité | Table issue d'une liste blanche (eai_finops.usage_events, eai_telemetry.spans) passée uniquement en paramètre typé {table:Identifier}, texte de requête constant, données en JSONEachRow dans le corps, jeton insert_deduplication_token, utilisateur eai-writer limité à INSERT (prod), eai-reader en lecture seule, TLS | EAI_CLICKHOUSE_URL, EAI_CLICKHOUSE_USER, EAI_CLICKHOUSE_TABLE | test_security_clickhouse.py::test_hostile_table_names_refused, test_security_clickhouse.py::test_hostile_env_table_refused, test_security_clickhouse.py::test_invalid_table_refused_before_any_http_request, test_security_clickhouse.py::test_query_text_constant_table_only_in_param, test_security_clickhouse.py::test_hostile_row_values_stay_json_one_line_per_row, test_security_clickhouse.py::test_hostile_dedup_token_refused, test_security_clickhouse.py::test_error_text_bounded_without_credentials, test_security_clickhouse.py::test_redirect_not_followed, test_security_clickhouse.py::test_prod_clickhouse_user_is_least_privilege_writer, test_security_clickhouse.py::test_eai_reader_is_read_only | Faible |
| Injection de commande | Multimodal, red team | eai.integrations.safe_exec.run (liste d'arguments, pas de shell, minimal_env), check, media_input | aucun | test_security_commands.py::test_payloads_refused, test_security_commands.py::test_run_uses_list_no_shell_minimal_env, test_security_commands.py::test_ffmpeg_refuses_input_specs | Vulnérabilités propres à ffmpeg |
| Injection de gabarit et de chaîne de format | Agents, prompts | eai.domains.agents.kit.safe_format (variables déclarées seulement, pas de récursion) | aucun | test_security_inputs.py::test_safe_format_never_evaluates, test_security_inputs.py::test_prompt_render_does_not_expand_attributes, test_security_inputs.py::test_safe_format_linear_time | Faible |
| Traversée de chemin | API (contrats, manifestes, catalogue), médias | Validation des noms dans les routes (400, 404 ou 422), safe_exec.media_input pour les médias | aucun | test_security_inputs.py::test_path_traversal_rejected | Faible |
| YAML et désérialisation (billion laughs) | Import système | eai.domains.system.safe_yaml (refuse ancres, alias, documents trop gros) | EAI_MAX_BODY_BYTES | test_security_inputs.py::test_yaml_refuses_aliases_anchors_and_big_documents | Faible |
| XSS (stocké, réfléchi, DOM) et CSP | Portail | buildCsp avec makeNonce dans portal/src/middleware.ts, safeHref, rendu React échappé | aucun | portal/tests/security.test.ts::buildCsp > carries the nonce and strict-dynamic, portal/tests/security.test.ts::buildCsp > never allows eval or inline scripts, portal/tests/security.test.ts::safeHref > refuses %s, portal/tests/zod-csp.test.ts::zod under a no-eval CSP > parses objects without calling the Function constructor | Bibliothèques tierces dans le portail |
| CSRF | API | Authentification par jeton Bearer ou clé API, pas de cookie d'API | EAI_CORS_ORIGINS | test_deploy_ci_evidence.py::test_api_ignores_cookies_no_csrf_surface | Nul tant qu'aucun cookie n'authentifie l'API |
| Clickjacking | Portail, API | En-têtes frame-ancestors / X-Frame-Options (security_headers, SECURITY_HEADERS) | EAI_SECURITY_HEADERS_ENABLED | test_security_http.py::test_headers_on_json_and_error_responses | Faible |
| Redirection ouverte | Portail | safeReturnTo | aucun | portal/tests/security.test.ts::safeReturnTo > falls back for %s, portal/tests/security.test.ts::safeReturnTo > keeps internal paths | Faible |
| Injection CRLF et d'en-têtes | API | Serveur ASGI refusant CR/LF, plafonds d'en-têtes (LimitsMiddleware), TrustedHostMiddleware (eai.main) | EAI_ALLOWED_HOSTS | test_security_http.py::test_header_and_query_caps, test_security_http.py::test_trusted_host | Faible |
| Injection dans les journaux | API | Journal d'accès en une ligne JSON échappée, security_event (_one_line) | aucun | test_security_http.py::test_access_log_is_one_escaped_json_line | Faible |
| Injection CSV et de formules | FinOps, exports | eai.domains.finops.importers.base.neutralize_formula | aucun | test_security_inputs.py::test_csv_formulas_neutralized, test_security_inputs.py::test_csv_import_keeps_numbers_and_quotes_formulas | Faible |
| ReDoS | Détection d'injection | Entrée bornée et motifs linéaires dans eai.domains.privacy.injection | aucun | test_security_prompt_injection.py::test_bounded_input_is_linear | Faible |
| Affectation de masse | API | Modèles Pydantic de patch, set_clause avec colonnes autorisées | aucun | test_security_inputs.py::test_patch_rejects_non_updatable_columns, test_security_inputs.py::test_role_escalation_refused, test_security_attack_suite.py::test_mass_assignment, test_security_attack_suite.py::test_viewer_cannot_mutate | Faible |
| IDOR et BOLA | Données | RLS PostgreSQL via eai.db.tx, 404 pour une ressource d'un autre tenant | aucun | test_security_inputs.py::test_cross_tenant_access_is_404, test_security_attack_suite.py::test_cross_tenant_idor | Requêtes admin hors RLS |
| Attaques d'authentification (JWT alg none, confusion HS/RS, kid, expiration) | API | eai.auth : liste d'algorithmes, kid obligatoire avec plusieurs clés, rafraîchissement JWKS limité, délai de grâce ; garde de démarrage refusant HS* et none | EAI_JWT_ALGORITHMS, EAI_JWT_LEEWAY_SECONDS | test_security_auth.py::test_alg_none_refused, test_security_auth.py::test_hs256_signed_with_public_key_refused, test_security_auth.py::test_kid_required_with_several_keys, test_security_auth.py::test_claims_enforced, test_security_auth.py::test_unknown_kid_refresh_is_rate_limited | Compromission de l'IdP |
| Force brute et limitation de débit | API | eai.security.ratelimit : check_principal, record_auth_failure, check_auth_lockout, AnonymousRateLimitMiddleware ; WAF | EAI_RATE_LIMIT_ENABLED, EAI_RATE_LIMIT_PER_MINUTE, EAI_RATE_LIMIT_GATEWAY_PER_MINUTE, EAI_RATE_LIMIT_AUTH_FAILURES_PER_MINUTE, EAI_REDIS_URL | test_security_http.py::test_auth_failure_lockout_per_ip, test_security_http.py::test_rate_limit_per_principal, test_security_http.py::test_anonymous_per_ip, test_security_auth.py::test_api_key_format_checked_before_db | Attaques distribuées sur de nombreuses IP |
| Corps trop gros ou trop imbriqués | API | eai.security.limits.LimitsMiddleware, json_depth_exceeds | EAI_MAX_BODY_BYTES, EAI_MAX_UPLOAD_BYTES, EAI_MAX_JSON_DEPTH | test_security_http.py::test_body_cap_content_length_and_chunked, test_security_http.py::test_json_depth, test_security_http.py::test_upload_routes_use_the_upload_cap, test_security_auth.py::test_token_size_cap | Faible |
| Injection de prompt (directe et indirecte) | LLM, agents, RAG | eai.domains.privacy.injection.detect, guard.screen, guard.wrap_messages, guard.blocked_error | EAI_PROMPT_INJECTION_DEFAULT_MODE, tenant prompt_injection_mode, untrusted_content_wrapping | test_security_prompt_injection.py::test_detects_direct_injection_fr_en, test_security_prompt_injection.py::test_detects_obfuscated_injection, test_security_prompt_injection.py::test_indirect_injection_tool_message_and_wrapping, test_security_prompt_injection.py::test_indirect_injection_rag_part, test_security_prompt_injection.py::test_mode_off_detect_block | Détection heuristique contournable ; compléter par garak et promptfoo |
| Exfiltration par la sortie du modèle (images et liens markdown) | LLM | guard.OutputGuard, guard.StreamGuard, guard.host_allowed | tenant output_links, output_link_allowlist | test_security_prompt_injection.py::test_output_guard_rules, test_security_prompt_injection.py::test_stream_guard_split_link, test_security_prompt_injection.py::test_output_links_non_stream_and_stream, test_security_prompt_injection.py::test_detects_exfiltration | Mode allow choisi par le tenant |
| Fuite du prompt système (canari) | LLM | guard.new_canary, guard.add_canary | tenant prompt_injection_mode | test_security_prompt_injection.py::test_canary_leak_detect_and_block | Paraphrase du prompt sans le canari |
| Fuite de secrets (masquage SDK, journaux) | SDK, API | Masquage eai_*** dans les SDK (python, go, java), erreurs sans détails internes (eai.errors), URL rédigées (outbound._redact) | aucun | test_security_http.py::test_errors_never_leak_internals, test_security_inputs.py::test_errors_do_not_leak_sql | Secrets collés par l'utilisateur dans un prompt (DLP) |
| Injection terminal dans la CLI | CLI | chat et logs suppriment les séquences ANSI et échappent les caractères de contrôle (cli) | aucun | test_security.py::test_terminal_output_is_neutralized, test_security.py::test_cli_chat_neutralizes_escape_sequences (SDK Python) | Faible |
| Webhooks forgés et rejoués | Connecteurs, canaux | Signature HMAC et horodatage (connectors.service._parse_signature, channels.service._check_signature) | secrets du connecteur | test_capabilities_gateways.py::test_webhook_signature_replay_and_dedupe, test_security_attack_suite.py::test_webhook_signature_required | Secret de webhook divulgué : le faire tourner |
| Injection indirecte par un résultat d'outil, du MCP, d'un connecteur, un rappel de mémoire ou un message A2A | Tool Gateway, MCP Gateway, webhooks de connecteurs, mémoire, A2A | guard.screen_untrusted avant la réinjection : détection (injection.detect), mode prompt_injection_mode (detect ou block) et encapsulation untrusted_content_wrapping du locataire, comme le RAG ; événements security.prompt_injection.detected (risque moyen ou élevé) et security.prompt_injection.blocked | security.prompt_injection_mode, security.untrusted_content_wrapping | test_gateway_pep_untrusted.py::test_untrusted_tool_result, test_gateway_pep_untrusted.py::test_untrusted_mcp_result, test_gateway_pep_untrusted.py::test_untrusted_connector_webhook, test_gateway_pep_untrusted.py::test_untrusted_memory_recall, test_gateway_pep_untrusted.py::test_untrusted_a2a_message | Heuristiques : une injection reformulée peut passer en mode detect, l'encapsulation reste la défense en profondeur |
| Action d'une gateway sans décision de politique | MCP, connaissance, mémoire, temps réel, connecteurs, canaux, multimodal, A2A, Model Gateway | PEP policy.gate avant tout appel sortant, décision dans eai.policy_decisions, refus 403 policy_denied ; paquet OPA eai.gateway_access (deploy/policies/opa/gateway_access.rego) | politiques du locataire, data.eai.config.gateway_access | test_gateway_pep_untrusted.py::test_pep_model_gateway_denied, test_gateway_pep_untrusted.py::test_pep_mcp_denied, test_gateway_pep_untrusted.py::test_pep_knowledge_and_memory_denied, test_gateway_pep_untrusted.py::test_pep_realtime_multimodal_denied, test_gateway_pep_untrusted.py::test_pep_connector_channel_a2a_denied, gateway_access_test.rego (opa test) | Une obligation d'approbation est refusée aux points d'entrée synchrones |
| Chaîne d'approvisionnement (images signées, SBOM, audit des dépendances) | CI/CD | Jobs trivy-image, sbom-sign, pip-audit, npm-audit (.gitlab-ci.yml), security-deps-python, security-deps-node, security-manifests (.forgejo/workflows/ci.yml), Kyverno | ci-security-gates | test_deploy_ci_evidence.py::test_kyverno_platform_images_need_ci_key | Vulnérabilités inconnues (0-day) |