Générer des empreintes sémantiques déterministes pour les fonctions Go. Détecter les backdoors de style xz et vérifier l'équivalence sémantique à l'aide de l'analyse Static Single Assignment (SSA) et de Scalar Evolution.
sfw est un analyseur statique pour le code source Go. Il construit la SSA avec golang.org/x/tools/go/ssa, réécrit chaque fonction en une IR canonique, et calcule l'empreinte de la fonction comme le SHA-256 de cette IR. Au-dessus de l'empreinte :
sfw diff compare deux fichiers fonction par fonction. Il apparie les fonctions renommées par topologie et évalue chaque changement selon les capacités nouvellement atteintes et les gardes, vérifications et paramètres de sécurité supprimés.sfw deps diff compare le code tiers que deux arborescences d'un module compilent : fonctions modifiées, fonctions exportées qui atteignent nouvellement une capacité, et fichiers modifiés que l'analyse ne peut pas voir.sfw audit envoie les changements à haut risque d'un diff, leur code source et le message de commit à un LLM, qui lit le code (via des outils, avec un modèle Claude) et décide si le message décrit le changement.sfw index et sfw scan comparent les topologies de fonctions à un magasin de signatures (PebbleDB ou JSON).L'analyse n'exécute jamais le code testé.
[!CAUTION] Cet outil est fourni uniquement à des fins de recherche en sécurité défensive et de tests autorisés. Ne l'utilisez pas pour créer, distribuer ou déployer des logiciels malveillants. Les utilisateurs sont responsables du respect des lois applicables et des politiques organisationnelles. L'auteur décline toute responsabilité en cas de mauvaise utilisation.
go install github.com/BlackVectorOps/semantic_firewall/v7/cmd/[email protected]
go.mod déclare go 1.27.2. sfw version affiche la version de compilation :
Semantic Firewall CLI
Build: v7.1.1 (Pebble/Gob+PackedIdx)
Les options doivent précéder les arguments positionnels. La CLI analyse chaque commande avec le paquet flag de Go, qui s'arrête au premier argument non-option ; les options placées après un nom de fichier sont silencieusement ignorées.
| Commande | Options (valeur par défaut) | Arguments | Sandbox |
|---|---|---|---|
check | --strict (false), --scan (false), --db (""), --no-sandbox (false) | <file.go|dir> | oui |
diff | --no-sandbox (false), --batch ("") | <old.go> <new.go>, ou aucun avec --batch <pairs-file> | oui |
deps diff | --no-sandbox (false) | <old-module-dir> <new-module-dir> | oui |
audit | --model (claude-opus-5-5), --api-key (""), --api-base (""), --no-sandbox (false) | <old.go> <new.go> "<commit message>" | oui (l'étape de diff) |
index | --name (requis), --severity (HIGH), --category (malware), --db ("") | <file.go|dir> | non |
scan | --db (""), --threshold (0.75), --exact (false), --deps (false), --deps-depth (direct), --no-sandbox (false) | <file.go|dir> | oui |
migrate | --from (requis), --to (requis) | aucun | non |
stats | --db ("") | aucun | non |
version | aucune | aucun | non |
sfw <command> -h liste les options d'une commande. --severity est stocké tel que fourni, sans validation. Toute valeur de --deps-depth autre que transitive est traitée comme direct.
Codes de sortie :
| Commande | Sortie 0 | Sortie 1 |
|---|---|---|
check | l'analyse s'est exécutée, même lorsqu'un fichier n'a pas pu être chargé (signalé dans le champ error de ce fichier) | --strict et au moins un fichier en erreur ; erreurs fatales |
diff | diff produit, quel que soit le risque | erreurs fatales |
diff --batch | chaque paire comparée, quel que soit le risque | au moins une paire en échec (après affichage de tous les résultats) ; erreurs fatales |
deps diff | diff produit, quel que soit le risque | l'un des arbres n'a pas pu être chargé ; erreurs fatales |
scan | l'analyse s'est exécutée, quelles que soient les alertes | erreurs fatales (par ex. absence de base de données) |
audit | verdict MATCH | verdict LIE, SUSPICIOUS ou ERROR |
diff traite un fichier d'entrée manquant comme un fichier vide.
Affiche un tableau JSON avec une entrée par fichier. Un répertoire est parcouru récursivement, en ignorant vendor/, les répertoires cachés et les fichiers _test.go. Les noms de fonctions sont qualifiés par le paquet : un fichier chargé seul appartient à command-line-arguments.
sfw check --no-sandbox new.go
[
{
"file": "new.go",
"functions": [
{ "function": "command-line-arguments.Handle", "fingerprint": "4acdccda3895dd4cec3af2d55ad43489f91860cd226f82091eaf0a2429849e2f", "file": "/work/new.go", "line": 5 },
{ "function": "command-line-arguments.Handle$1", "fingerprint": "1777c5c3ae9a69e395f6bbe8f35a1e447d25534afec7bb907eacf873e7d4917c", "file": "/work/new.go", "line": 7 },
{ "function": "command-line-arguments.Sum", "fingerprint": "7cc1efa6ef6ca643863de5dcb0a68f7c80cd6dae8c530697706f40ce737030ae", "file": "/work/new.go", "line": 10 },
{ "function": "command-line-arguments.init", "fingerprint": "825a2d206f4eb4ea4413c050e4ca9e4b8e439c2067219829a8fef891031a1850", "file": "" }
]
}
]
La sortie ci-dessus a été capturée à partir d'une exécution réelle, avec le chemin absolu raccourci en /work et chaque objet placé sur une seule ligne. new.go est le fichier de l'exemple sfw diff.
--strict : une instruction SSA non gérée fait échouer le canonicaliseur au lieu d'émettre UnhandledInstr<T>, et toute erreur par fichier fait sortir la commande avec le code 1.--scan : la topologie de chaque fonction est également comparée à la base de données de signatures (--db, ou la résolution par défaut) à un seuil fixe de 0,75. Les correspondances sont placées dans un champ scan_results. Une base de données manquante est une erreur fatale.Entrée :
// old.go
package p
import "fmt"
func Handle(cmd string) { fmt.Println(cmd) }
func Add(a, b int) int { return a + b }
// new.go
package p
import "net"
func Handle(cmd string) {
net.Dial("tcp", cmd)
go func() {}()
}
func Sum(a, b int) int { return a + b }
sfw diff --no-sandbox old.go new.go affiche ce qui suit. Il s'agit de la sortie complète, à ceci près que l'entrée init est abrégée à son statut et à son delta.