<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Code Analysis on My personal blog</title>
        <link>https://www.matteobianchi.eu/tags/code-analysis/</link>
        <description>Recent content in Code Analysis on My personal blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Tue, 14 Apr 2026 09:00:00 +0200</lastBuildDate><atom:link href="https://www.matteobianchi.eu/tags/code-analysis/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>SAST: analizzare il codice senza eseguirlo</title>
        <link>https://www.matteobianchi.eu/p/sast-analisi-statica/</link>
        <pubDate>Tue, 14 Apr 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/sast-analisi-statica/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/sast-analisi-statica/cover.png" alt="Featured image of post SAST: analizzare il codice senza eseguirlo" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Tolti i &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/gestione-dei-segreti/&#34; &gt;segreti dal codice&lt;/a&gt;, possiamo analizzare il
codice stesso. Il &lt;strong&gt;SAST (Static Application Security Testing)&lt;/strong&gt; legge il sorgente — senza eseguirlo —
cercando pattern che portano a vulnerabilità. È il primo controllo che tocca la logica di ciò che
scriviamo, e si attiva prima ancora della compilazione, nel punto più a sinistra possibile dopo il
threat modeling.&lt;/p&gt;
&lt;h2 id=&#34;cosa-trova-e-cosa-no&#34;&gt;Cosa trova (e cosa no)
&lt;/h2&gt;&lt;p&gt;Il SAST eccelle sui difetti &lt;em&gt;locali e riconoscibili nel codice&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Injection&lt;/strong&gt; (SQL, comandi, LDAP): input non sanitizzato che finisce in una query o in una shell.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Path traversal&lt;/strong&gt;, &lt;strong&gt;XSS&lt;/strong&gt;, deserializzazione insicura.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crypto debole&lt;/strong&gt;: MD5 per le password, algoritmi deprecati, chiavi hardcoded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pattern pericolosi&lt;/strong&gt;: &lt;code&gt;eval&lt;/code&gt;, formattazione di stringhe in query.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Non vede i difetti che emergono solo a runtime o dalla &lt;em&gt;configurazione&lt;/em&gt;: un bucket pubblico, un
header mancante, una logica di autorizzazione sbagliata che il codice esprime &amp;ldquo;correttamente&amp;rdquo;. Per
quelli servono DAST e analisi di configurazione, capitoli successivi.&lt;/p&gt;
&lt;h2 id=&#34;come-funziona-la-taint-analysis&#34;&gt;Come funziona: la taint analysis
&lt;/h2&gt;&lt;p&gt;Il cuore del SAST moderno è l&amp;rsquo;analisi del &lt;em&gt;flusso dei dati contaminati&lt;/em&gt; (taint): segue un dato da una
&lt;strong&gt;sorgente&lt;/strong&gt; non fidata (input utente) fino a un &lt;strong&gt;sink&lt;/strong&gt; pericoloso (una query), controllando se
passa per un &lt;em&gt;sanitizer&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart LR
    SRC[&amp;#34;Source&amp;lt;br/&amp;gt;request.getParameter()&amp;#34;] --&amp;gt;|dato contaminato| F[Flusso nel codice]
    F --&amp;gt; SAN{&amp;#34;Passa da un&amp;lt;br/&amp;gt;sanitizer?&amp;#34;}
    SAN --&amp;gt;|no| SINK[&amp;#34;Sink&amp;lt;br/&amp;gt;db.execute(sql)&amp;#34;]
    SAN --&amp;gt;|sì| OK[Sicuro]
    SINK --&amp;gt; V[VULNERABILITÀ:&amp;lt;br/&amp;gt;SQL injection]
    style V fill:#fde2e4,stroke:#e63946
&lt;/pre&gt;

&lt;p&gt;Se un dato arriva dalla sorgente al sink senza sanitizzazione, lo strumento segnala. Questo spiega
sia la potenza (trova catene non ovvie) sia i limiti (non sa che una certa funzione &lt;em&gt;è&lt;/em&gt; un sanitizer
se non gliel&amp;rsquo;hai detto → falso positivo).&lt;/p&gt;
&lt;h2 id=&#34;il-problema-dei-falsi-positivi&#34;&gt;Il problema dei falsi positivi
&lt;/h2&gt;&lt;p&gt;Il SAST ingenuo è famoso per il rumore. Un tool che segnala 500 problemi di cui 480 irrilevanti
viene disattivato in una settimana. Le contromisure in una pipeline sana:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# esempio di gate SAST ragionevole nella CI&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;fail_on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;high         &lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# blocca solo su severità alta, non su tutto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;diff_aware&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# analizza solo il codice cambiato nella PR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;baseline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# ignora il debito preesistente, blocca il NUOVO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;suppress_with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;comment&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# i falsi positivi si marcano, tracciati e revisionati&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le righe evidenziate sono ciò che rende il SAST sopportabile: &lt;strong&gt;blocca solo il nuovo rischio alto&lt;/strong&gt;,
non tutto il debito storico, e lascia una via esplicita (tracciata) per i falsi positivi.&lt;/p&gt;
&lt;h2 id=&#34;nel-flusso-di-lavoro&#34;&gt;Nel flusso di lavoro
&lt;/h2&gt;&lt;p&gt;Il posto giusto è la &lt;strong&gt;pull request&lt;/strong&gt;: il feedback arriva come commento in linea, nel contesto, a chi
ha appena scritto quel codice. Molti team aggiungono il SAST anche nell&amp;rsquo;IDE (feedback in tempo reale)
e un passaggio nella CI come gate. Regole personalizzate (Semgrep rende questo semplice) codificano
gli &lt;em&gt;abuse case&lt;/em&gt; del threat model: la minaccia diventa una regola che fallisce se la falla ritorna.&lt;/p&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se il SAST ha tanti falsi positivi e non vede i difetti di runtime, perché non affidarsi solo al DAST che testa l&#39;app reale?&lt;/summary&gt;
&lt;p&gt;Perché vedono cose diverse e in momenti diversi, e scartarne uno lascia un buco. Il SAST ha una
visibilità totale sul codice — ogni ramo, ogni percorso, anche quelli che un test dinamico non
raggiungerebbe mai senza l&#39;input giusto — e dà feedback sulla singola riga, in fase di scrittura, quando
correggere costa un minuto. Il DAST vede l&#39;applicazione viva, quindi trova i difetti di configurazione e
di ambiente che il SAST ignora, ma solo sui percorsi che riesce effettivamente a esercitare, e arriva
tardi, in staging, quando il codice è già scritto e il contesto mentale perso. Non sono ridondanti, sono
complementari: il SAST è la copertura ampia e precoce con il prezzo del rumore, il DAST è la conferma
realistica ma tardiva e parziale. La risposta ai falsi positivi non è eliminare il SAST, è configurarlo
bene — diff-aware, baseline, gate solo su severità alta, regole tarate sul tuo codice — così il segnale
emerge dal rumore. Un difetto di injection trovato dal SAST sulla pull request costa un commento; lo
stesso difetto trovato dal DAST in staging costa un ticket; trovato in produzione costa un incidente.
Vuoi entrambe le reti, non la più comoda.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Il SAST legge il codice senza eseguirlo e segue i dati contaminati dalla sorgente al sink: ampio,
precoce, ma rumoroso se non tarato su diff, baseline e severità. Cattura però solo il codice che
&lt;em&gt;scriviamo noi&lt;/em&gt;. La maggior parte di un&amp;rsquo;applicazione moderna, però, è codice che non abbiamo scritto:
le dipendenze. Analizzarle è un problema diverso — la Software Composition Analysis, prossimo capitolo.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
