Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
enforcement-coverage — Détecte les routes API dont l'autorisation est plus faible que celle de leurs homologues. A récupéré la CVE-2026-45316 à partir du code source. Inclut les résultats négatifs. | Kitploit
Outils/GitHubGitHub/arian-gogani/enforcement-coverage
Analyse Statique de Code (SAST)Analyse des VulnérabilitésAnalyse de CodeTests d'IntrusionDevSecOpsSécurité des API
GitHubarian-gogani/enforcement-coverage

enforcement-coverage

Détecte les routes API dont l'autorisation est plus faible que celle de leurs homologues. A récupéré la CVE-2026-45316 à partir du code source. Inclut les résultats négatifs.

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt
il y a 15h 36mPas encore vérifié

Couverture d’application

Détecte les routes API qui portent un contrôle d’autorisation plus faible que leurs routes sœurs.

Il a trouvé la CVE-2026-45316 dans Open WebUI à partir du seul code source, sans connaissance préalable d’un avis de sécurité :

root@kitploit:~
[MISMATCH] POST /notes/{id}/pin  (notes.py:pin_note_by_id)
  3/3 comparable write operations on note require has_access(write);
  this route requires only has_access(read)

    POST   /notes/{id}/update          has_access(write)
    POST   /notes/{id}/access/update   has_access(write)
    DELETE /notes/{id}/delete          has_access(write)

Sur 2 568 routes dans cinq bases de code en production, il a produit 4 résultats. Deux étaient réels. Ce README explique ces deux nombres.

L’idée

Une grande classe de bugs d’autorisation n’est pas un contrôle cassé. C’est un contrôle manquant ou affaibli sur une route dont toutes les sœurs ont été correctement protégées.

Portainer autorisait quatre endpoints de modèles sœurs mais pas le cinquième. Signal K limitait le débit de connexion HTTP mais pas celui de WebSocket. La route d’épinglage de note d’Open WebUI modifiait une note tout en vérifiant la permission de lecture, alors que toutes les autres mutations de note vérifiaient l’écriture.

Toujours la même forme :

root@kitploit:~
✓ ✓ ✓ ✓ ✗

Le dépôt contient déjà la règle. Une route l’a enfreinte. Il suffit donc de reconstruire la règle à partir du code et de signaler l’exception. Ni fichier de politique, ni configuration, ni annotations. L’ensemble de preuves est constitué des routes sœurs elles-mêmes.

Exécution

root@kitploit:~
python3 enforcement_coverage.py /path/to/repo
python3 enforcement_coverage.py /path/to/repo --density
python3 enforcement_coverage.py /path/to/repo --json

Python 3.10+, aucune dépendance. FastAPI uniquement.

Les verdicts sont MISSING, MISMATCH, PRESERVED, UNKNOWN. UNKNOWN s’abstient et n’est jamais signalé.

Ce qu’il fait

Extraction. Résout les contrôles à partir de la signature Depends(), du décorateur dependencies=[], des dépendances au niveau du routeur, des corps de fonctions, des fonctions d’encapsulation et des listes de classes de permissions.

L’extraction depuis le corps est essentielle. Dans Open WebUI, 216 des 608 gestionnaires portent le contrôle décisif à l’intérieur de la fonction :

root@kitploit:~
if user.role != 'admin' and not await AccessGrants.has_access(
    user_id=user.id, resource_type='note',
    resource_id=note.id, permission='write', db=db,
):
    raise HTTPException(status_code=403)

La classe d’opération provient de ce que le gestionnaire fait à la ressource, et non du verbe HTTP. POST /notes/{id}/chat est un POST qui lit une note.

Classification du vocabulaire. Deux valeurs dans une même famille de contrôles ne forment pas nécessairement une échelle de force :

root@kitploit:~
has_access             {read, write}                      LEVEL
ensure_flow_permission {create,delete,execute,read,write}  ACTION
has_permission         {features.notes, workspace.tools}   SCOPE

Seuls les vocabulaires de niveau (LEVEL) permettent une comparaison de force. Comparer FlowAction.CREATE à un WRITE dominant a produit six faux positifs dans Langflow avant que cela ne soit corrigé.

Filtre de direction. Seules les déviations vers un contrôle moins restrictif sont signalées. Plus strict que le précédent n’est pas une vulnérabilité.

Ce qu’il a trouvé

Deux vrais positifs.

POST /notes/{id}/pin dans Open WebUI — CVE-2026-45316.

Un autre résultat est une asymétrie de permissions dans Netflix Dispatch : POST /{incident_id}/resources utilise IncidentViewPermission alors que six opérations d’écriture sœurs utilisent IncidentEditPermission. IncidentViewPermission renvoie True pour tout incident non restreint ; IncidentEditPermission exige d’être admin, commandant ou rapporteur. Le gestionnaire met en file la création de tickets et de groupes sans autre contrôle.

Non signalé, car il n’y a nulle part où le signaler : le dépôt a été archivé par Netflix le 3 septembre 2025 et est en lecture seule, il n’a pas de SECURITY.md, le signalement privé des vulnérabilités est désactivé pour les dépôts archivés, et Dispatch est explicitement listé comme hors périmètre dans le programme de bug bounty de Netflix. Le publier ici est le seul canal de divulgation restant. La sévérité est faible — cela nécessite un membre authentifié de l’organisation et n’affecte que les incidents non restreints — et le projet n’est plus maintenu.

Deux faux positifs. POST /tools/{id}/valves/user/update écrit les paramètres de valve propres de l’utilisateur et n’a légitimement besoin que de la lecture sur l’outil — la cible de la mutation est une entité différente du sujet d’autorisation. Et une route de base de connaissances de Langflow où le contrôle des routes sœurs n’est pas requis.

Pourquoi cela ne fonctionne généralement pas

C’est la partie utile.

La densité ne prédit pas les résultats

Danswer a une couverture de contrôle de 95,9 % et a produit zéro résultat avec 80,7 % de UNKNOWN. Son vocabulaire est require_permission('basic_access'), ('manage_connectors') — un espace de noms de capacités, pas une échelle de force. On ne peut pas dire que manage_connectors est plus faible que read_connectors.

Ce qui prédit les résultats est un appel de permission à portée de ressource avec un argument de force ordonné, comme has_access(resource, read|write). Une base de code sur cinq en était dotée.

Chaque base de code a nécessité une extraction différente

Cinq idiomes pour cinq dépôts. Chacun a nécessité un travail d’extraction avant que l’analyse puisse seulement s’exécuter.

UNKNOWN n’est jamais descendu sous 72 %

Dans n’importe quel dépôt, sous n’importe quelle configuration. La plupart des routes n’appartiennent pas à une famille de routes sœurs de trois ou plus avec un contrôle cohérent.

Défauts découverts en exécutant l’outil sur du code réel

Aucun de ces défauts n’avait été anticipé à l’avance.

  1. l’autorisation vit dans les corps de fonctions, pas dans Depends()
  2. les routes portent plusieurs familles de contrôles à la fois
  3. le verbe HTTP n’est pas la classe d’opération
  4. les idiomes d’autorisation diffèrent selon le dépôt
  5. les vocabulaires d’action ne sont pas des échelles de force
  6. plus strict que le précédent n’est pas une vulnérabilité
  7. un vocabulaire classé à partir des seuls précédents masque les familles à valeur unique
  8. les helpers de validation qui lèvent une 422 ne sont pas de l’autorisation
  9. les fonctions d’encapsulation masquent le véritable contrôle
  10. les idiomes de listes de classes de permissions nécessitent une division des noms
  11. l’assouplissement des familles sœurs a multiplié les résultats par 7,5 et fait chuter la précision de 50 % à 13 %
  12. une route avec un contrôle suffisant différent n’en est pas dépourvue
  13. application équivalente implémentée en ligne plutôt que comme dépendance — non résolu

Le défaut 13 est le plus intéressant. Les routes de recommandation de tags de Dispatch n’ont pas le CaseViewPermission que portent leurs sœurs. Mais cette permission renvoie True pour tout cas non restreint, et le service vérifie déjà visibility == restricted en ligne. Les chemins sont équivalents. Détecter cela nécessite une analyse d’équivalence sémantique, pas structurelle.

Évaluation honnête

Le mécanisme fonctionne. Il a retrouvé une CVE publiée et une faille d’autorisation non signalée à partir du code source, avec des ensembles de preuves auditables, en utilisant uniquement les informations disponibles avant la fusion du commit vulnérable.

Le rendement est d’environ un résultat pour 1 000 routes, et il nécessite une architecture que seule l’une des cinq bases de code substantielles possédait.

Utile comme outil d’audit pour une base de code dotée d’un vocabulaire de permissions à portée de ressource. Pas, au vu de ces éléments, un scanneur généraliste.

Travaux antérieurs

La détection statique de vulnérabilités de contrôle d’accès par inférence d’hypothèses implicites remonte à USENIX Security 2011. ACMiner a extrait les contrôles d’autorisation dans les middlewares Android. Semgrep propose une détection basée sur l’IA ciblant les autorisations manquantes et a rapporté une précision de 61 % dans une évaluation client. L’OWASP publie une antisèche de tests de régression d’autorisation dont l’approche recommandée est de maintenir à la main une matrice Acteur × Ressource × Action.

C’est une approche étroite et déterministe : ne récupérer que ce que les routes sœurs prouvent, s’abstenir autrement.

Sous licence MIT.

Télécharger l’outil
dépôtroutescontrôléesrésultats
LiteLLM80887,1 %0
Danswer / Onyx65395,9 %0
Open WebUI52997,2 %2
Netflix Dispatch29136,1 %1
Langflow28747,4 %1
dépôtidiome
Open WebUIAccessGrants.has_access(resource_type=, permission=)
Langflowensure_<resource>_permission(user, Action.X)
LiteLLMcomparaison de rôle sur user_api_key_dict.user_role
Netflix DispatchDepends(PermissionsDependency([CaseEditPermission]))
Danswerrequire_permission('basic_access')