🔎 Outils d’analyse statique d’une base de code

L’analyse statique du code consiste à l’analyser SANS le lancer.

Petite définition

L’analyse du code statique, appelée aussi analyse du code source ou révision du code statique, est le processus consistant à détecter les mauvaises habitudes de codage, les vulnérabilités potentielles et les défauts de sécurité dans le code source d’un logiciel, sans pour autant exécuter ce dernier. Il s’agit d’une forme de testing en boîte blanche.

Ce type d’analyse permet à vos équipes de repérer les bugs ou vulnérabilités que les autres outils et méthodes de test, par exemple les révisions de code manuelles et les compilateurs, ne relèvent généralement pas.

Quel objectif ?

Se prémunir de problèmes d’execution à venir sur un code écrit, sans avoir a l’executer à partir d’un sous set de règles, de bonnes pratiques et de contrôles sur le code.

Linting

Pour tous les languages en particulier les languages non fortement typés, il est souvent assez utile d’établir des conditions d’acceptation du code source. Pour cela, on utilise en général des outils de validation ou linter.

En python on utilisera parmi par exemple : flake8 pylint autopep8

Dans ces conditions on retrouvera aussi bien des conditions purement stylistiques : utilisation d’espaces plutôt que de tabulations, nommage des méthodes, …

Quelques règles sont édictées dans des propostions d’amélioration et d’uniformisation de code de python PEP :

Les règles sont modulables par projet et vous êtes libre de configurer pour votre projet les règles qu’il vous semble pertinent ou non de garder.

Fun Fact : Vous utilisez déjà un linter sans le savoir dans les IDE mais non configurés

Mais également la vérification de certaines règles sur le code :

  • Vérification de la présence du package pour réaliser l’import
  • Vérification de la validité de l’usage des fonctions par rapport a la signature des méthodes

Exemple d’usages :

# exemple avec black
pip3 install pylint
# puis
pylint ./app
# Vous pouvez le lancer depuis partout avec la commande :
pylint $(git ls-files '*.py')

Quel intêret me diriez vous :

Pour le style : La cohérence du code, permettre de se fixer des règles entre développeurs as code qui ensuite sont péreinnes et factuelles. Pour la vérification : Eviter les erreurs au lancement du code, et donc anticiper les bugs 🐛

Pour aller plus loin
L'usage et les règles appliquées sont bien entendues paramétrables : ex : https://www.codeac.io/documentation/pylint-configuration.html

Formatting

Pour répondre aux besoins de bon respect des règles établies en amont (voir linting). Il peut être pertinent de s’équiper d’un formatter, associé généralement a l’IDE (Visual studio code / Pycharm). Les formatters classiques pour python sont : black yapf Python-autopep8 isort

Exemple d’usages :

# exemple avec black
pip3 install black
# puis
black --check app

Quel intêret me diriez vous :

Etablir des changements seulement de contenu et fonctionnels dans le code permet réellement de ne garder que les changements fonctionnels et non de format lors de l’ajout de fonctionnalité. La relecture est donc facilitée. Et les règles établies lors du linting sont appliquées par défaut.

Pour aller plus loin 2.
Une liste bien plus exhaustive de linters en python en fonction des besoins : https://github.com/vintasoftware/python-linters-and-code-analysis

Security testing (SAST : Static application security testing)

Les Static Application Security Testing (SAST) sont des outils et des techniques utilisés dans le domaine de la sécurité informatique pour identifier les vulnérabilités potentielles dans le code source des applications.

Ils permettent de détecter des problèmes de sécurité dans le code sans l’executer.

Les SAST peuvent repérer des vulnérabilités telles que les injections SQL, les failles XSS, les erreurs de gestion de la mémoire, etc. Leur utilisation régulière permet de renforcer la sécurité des applications dès leur conception et de réduire les risques de failles de sécurité.

Securité : quelques rappels

Pour ce cours nous utiliserons l’outil Snyk mais de nombreux outils permettent de couvrir l’analyse de la sécurité des applications.

Différent types d’attaque en sécurité informatique:

  • Injection (SQL, texte, ..) ~50% : on manipule les entrants de l’application pour dépasser les fonctionnalités prévues.
  • Cross Site Scripting : On injecte un script dans une application pour qu’elle l’execute ensuite pour effectuer des actions malveillantes
  • Failles de sécurité - CVE : Bugs connus contenus dans des librairies et versions des systèmes qui sont ensuites exploités.
  • Attaque par déni de service - DDOS: attaque pour surcharger l’usage d’un service au niveau réseau / mémoire pour empêcher tout ou partie de ses usages possibles.
  • Man in the middle : récupération des informations utilisateurs pour usurper son identité et donc corrompre un système d’information

TP : Mise en place de ces outils sur une base de code

Pour ce TP on partira cette fois ci d’un projet déjà élaboré par une équipe au sein du ssplab. Prédicat.

https://github.com/InseeFrLab/predicat.git => disponible forké ici : https://github.com/conception-logicielle-ensai/predicat

Pour faciliter la vie des gens, j’ai forké ce projet dans le groupe conception logicielle ensai sur github, si vous ne voulez pas notifier la personne que vous forkez son projet.

https://github.com/conception-logicielle-ensai/predicat.git

Exercice 1 : Mise en place

(Wait it’s git again ? :OOO)

  1. Forkez le projet : https://github.com/conception-logicielle-ensai/predicat.git, pour les gens qui ne sont pas sur github, clonez le directement (passez donc la partie 2)

  2. Cloner le repository dans un sous dossier de votre TP, dans votre environnement de travail préféré

  3. Depuis le dépot récupéré, suivre les instructions pour l’installation via le README.md, veuillez toutefois a bien faire cela dans le repertoire app du dépot git, par défaut : predicat/app

  4. Lancez l’application via la commande uvicorn main:app, pensez bien a installer les dépendances au préalable, et vous pouvez utiliser un environnement virtuel.

AIDE 1 (clickable): Comment savoir les dépendances nécessaires à l'exécution de l'application ?

Rappel :

Pour un projet python, les dépendances sont en général gérées par pip (https://packaging.python.org/tutorials/installing-packages/) et sont listées dans le fichier requirements.txt

pip install -r requirements.txt

AIDE 2 (clickable) : Comment débugguer si l'application qui ne se lance pas / crash ?

Vous avez probablement mal lu le README.md.

Pour résoudre le problème, vous aurez besoin d’un modèle. On pourra utiliser le modèle de test disponible ici : https://minio.lab.sspcloud.fr/conception-logicielle/model_na2008.bin

Vous devez ensuite enlever du fichier de configuration yaml, les lignes concernant les modèles qui ne sont pas le modèle 2020_old.

Une fois l’application lancée, vous pouvez la requêter avec votre c lient HTTP préféré et adapté à votre environnement de travail (curl, navigateur web, insomnia …) : http://localhost:8000/label?q=confiture ou encore http://localhost:8000/label?q=omelette%20du%20fromage

Si ça ne resoud pas, cherchez par rapport a l’erreur renvoyée par la console.

Exercice 2 : Analyse statique du code - Linting / Formatting

Pour cette partie on va analyser le code de l’application prédicat.

Installons les paquets black, isort et pylint.

=> pip3 install black isort pylint

  • Lancez pylint sur le projet (il applique par défaut la config de la PEP8)

pylint app (app étant le dossier de l’appli, si vous y êtes déjà pylint *.py)

Que constatez vous ? Est ce qu’il y a des erreurs? De quel type ?

=> Petit tour d’horizon des erreurs possibles : <a href=“https://pylint.readthedocs.io/en/stable/user_guide/messages/messages_overview.html"

  • Appliquez le formattage avec black et isort

black app et isort --profile black app

Réappliquez votre linter sur l’application. Constatez vous un changement dans la notation du code ?

Pour valider un dépôt de code on peut par exemple se dire qu’on n’autorise pas une note inférieure a 7 pour le projet et s’y tenir.

pylint --fail-under=7
  • Vous pouvez également configurer un fichier .pylintrc (formaté en TOML):

Ce fichier est appliqué pour configurer les règles de pylint sur le projet (donc depuis le repertoire où on l’execute).

Exemple :

[MESSAGES CONTROL]
# Activer ou désactiver certains types de messages
disable = 
    missing-module-docstring,  # Pas de docstring pour les modules
    missing-function-docstring, # Pas de docstring pour les fonctions

[DESIGN]
# Configuration pour les lignes longues
max-line-length = 120  # Limiter à 120 caractères par ligne

[FORMAT]
# Configuration de formatage
good-names = i,j,k,e,x,run,_)  # Noms "bons" pour les variables

[REPORTS]
# Format de sortie pour les résultats de Pylint
output-format = text  # Format de sortie en texte

Vous pouvez en ajouter un et constater que cela réduit drastiquement le nombre d’erreurs.

Exercice 3 : Analyse de la sécurité du code et de ses dépendances

  • Créez un compte sur Snyk
  • Paramétrez l’accès a votre projet sur l’application par l’onglet : Projects => Github => {user}/predicat
  • Profit !

Si vous avez du temps vous pouvez regarder un peu les résultats sur le projet.

Exercice 4 : Votre projet

En attendant la fin de la séquence, mettez en place les outils sur votre projet. (ou réfléchissez sur votre projet)