Catch the risky change a git diff hides.
Semantic Firewall fingerprints Go by its structure and behavior, not its text -- so refactors and renames don't break your security gates, and a newly introduced capability (an os/exec, net, or raw syscall call that wasn't there before) stands out even when it's moved or obfuscated.
Deterministic, and honest about its edges: it tells you what it catches, where it hands off to a judgment layer, and what it does not score -- see Detection scope.
[!CAUTION] Disclaimer: This tool is provided for defensive security research and authorized testing only. The malware scanning features are designed to help security teams detect and analyze malicious code patterns. Do not use this tool to create, distribute, or deploy malware. Users are responsible for ensuring compliance with all applicable laws and organizational policies. The author assumes no liability for misuse.
Semantic Firewall is a new kind of static analysis tool for Go that:
Why is this different?
git diff, grep, or hash-based scanners) are easily fooled by renaming, whitespace, or code shuffling.Key Features:
See full feature table
| Feature | Description |
|---|---|
| Loop Equivalence | Proves loops are logically identical, no matter the syntax |
| Semantic Diff | Diffs code by behavior, not by text |
| Malware Indexing | Store and hunt for known malware patterns |
| Obfuscation Detection | Flags suspiciously complex or packed code |
| Dependency Scanning | Scans your code and all its dependencies |
| gVisor Isolation | Sandboxed execution via runsc for defense-in-depth |
Semantic Firewall is a deterministic structural analyzer, and it is deliberate about its boundaries -- naming them is what makes a green result worth trusting.
What it demonstrably catches. Capability introductions that resolve to a concrete call target -- a function that newly reaches the process-exec, network, or raw-syscall families (os/exec, net, syscall, plugin). This is validated on labeled synthetic pairs run through the full pipeline: each malicious introduction escalates while its size-matched benign twin stays silent (HasExecFamily, HasNetListen, HasRawSyscall). Structural fingerprinting makes this survive renames, moves, and reformatting.
Where it hands off. Calls reached through interface dispatch, function values, or reflection don't resolve to a concrete target -- they land in an invoke: / dynamic: bucket (roughly one in ten call sites across a 10-module corpus). These are ceded, not flagged: the deterministic core marks the seam where a separate judgment layer is needed, rather than guessing.
What it does not score (known limitations).
high_risk_changes or flip the verdict. Closing this requires scoring the loss of structure in the engine itself; until that ships it is a real gap, named here on purpose.The tool that tells you what it doesn't catch earns more trust than the one that implies it catches everything. The seams above (dynamic dispatch, deletion attacks) are exactly where a deeper, model-assisted judgment layer adds value -- and where we'd rather be honest about the gap than paper over it.
go install github.com/BlackVectorOps/semantic_firewall/v4/cmd/sfw@latest
# Check a file for risky changes
sfw check ./main.go
# See what *really* changed between two versions
sfw diff old_version.go new_version.go
# Index a known malware sample
sfw index malware.go --name "Beacon_v1" --severity CRITICAL
# Scan your codebase for malware (fast, O(1) matching)
sfw scan ./suspicious/
# Scan with dependency analysis
sfw scan ./cmd/myapp --deps
# See database stats
sfw stats
flowchart LR
subgraph Lab
M1[Known Malware] --> I[sfw index]
I --> DB[(signatures.db)]
end
subgraph Hunt
T[Target Code] --> S[sfw scan]
DB --> S
S --> A[Alerts]
end
%% Nodes: Deep radioactive green with neon border
classDef default fill:#022c22,stroke:#00ff41,stroke-width:1px,color:#ffffff
%% Subgraphs: Subdued slate blue containers
style Lab fill:#1e293b,stroke:#475569,stroke-width:2px,color:#94a3b8,stroke-dasharray:5 5
style Hunt fill:#1e293b,stroke:#475569,stroke-width:2px,color:#94a3b8
%% Database: Distinct cylinder styling
style DB fill:#064e3b,stroke:#00ff41,stroke-width:2px,color:#ffffff
linkStyle default stroke:#00ff41,stroke-width:1px
Show example outputs
Check Output:
{
"file": "./main.go",
"functions": [
{ "function": "main", "fingerprint": "005efb52a8c9d1e3...", "line": 12 }
]
}
Diff Output (Risk-Aware):
{
"summary": {
"semantic_match_pct": 92.5,
"preserved": 12,
"modified": 1,
"renamed_functions": 2,
"high_risk_changes": 1
},
"functions": [
{
"function": "HandleLogin",
"status": "modified",
"added_ops": ["Call <log.Printf>", "Call <net.Dial>"],
"risk_score": 15,
"topology_delta": "Calls+2, AddedGoroutine"
}
],
"topology_matches": [
{
"old_function": "processData",
"new_function": "handleInput",
"similarity": 0.94,
"matched_by_name": false
}
]
}
Scan Output (Malware Hunter):
{
"target": "./suspicious/",
"backend": "pebbledb",
"total_functions_scanned": 47,
"alerts": [
{
"signature_name": "Beacon_v1",
"severity": "CRITICAL",
"matched_function": "executePayload",
"confidence": 0.92,
"match_details": {
"topology_match": true,
"entropy_match": true,
"topology_similarity": 1.0,
"calls_matched": ["net.Dial", "os.Exec"]
}
}
],
"summary": { "critical": 1, "high": 0, "total_alerts": 1 }
}
| Traditional Tools | Semantic Firewall |
|---|---|
git diff |
sfw diff |
| Sees lines changed | Sees logic changed |
| Fooled by renames | Survives refactors |
| Hash-based AV | Behavioral fingerprints |
| YARA/grep | Topology & intent matching |
Use cases: - Supply chain security: catch backdoors that pass code review - Safe refactoring: prove your refactor is safe - CI/CD gates: block risky PRs - Malware hunting: scan codebases at scale - Obfuscation detection: flag packed/encrypted code - Dependency auditing: scan imported packages
Worried about sneaky changes or hidden intent?
Supply chain attacks often hide behind boring commit messages like "fix typo" or "update formatting." sfw audit uses an LLM (or deterministic simulation if you dont want to bother with an api key) to compare the developer's claim against the code's reality.
Command:
# Check if the commit message matches the code changes
sfw audit old.go new.go "minor refactor of logging" --api-key sk-...
The Verdict:
{
"inputs": {
"commit_message": "minor refactor of logging"
},
"risk_filter": {
"high_risk_detected": true,
"evidence_count": 1
},
"output": {
"verdict": "LIE",
"evidence": "Commit claims 'minor refactor' but evidence shows addition of high-risk network calls (net.Dial) and goroutines."
}
}
How it works:
Typical CI/CD workflow:
jobs:
semantic-firewall:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Semantic Firewall
run: |
go install github.com/BlackVectorOps/semantic_firewall/v4/cmd/sfw@latest
sfw diff old.go new.go
sfw scan . --deps
Result: - PRs that only change formatting or names pass instantly. - PRs that add risky logic or malware get flagged for review.
| Command | Purpose | Time Complexity | Space |
|---|---|---|---|
sfw check |
Generate semantic fingerprints | O(N) | O(N) |
sfw diff |
Semantic delta via Zipper algorithm | O(I) | O(I) |
sfw index |
Index malware samples into PebbleDB | O(N) | O(1) per sig |
sfw scan |
Hunt malware via topology matching | O(1) exact / O(M) fuzzy | O(M) |
sfw migrate |
Migrate JSON signatures to PebbleDB | O(S) | O(S) |
sfw stats |
Display database statistics | O(1) | O(1) |
sfw audit |
Verify commit intent (AI Lie Detector) | O(I) + API | O(I) |
Where N = source size, I = instructions, S = signatures, M = signatures in entropy range.
sfw check [--strict] [--scan --db <path>] [--no-sandbox] <file.go|directory>
Generate semantic fingerprints. Use --strict for validation mode. Use --scan to enable unified security scanning during fingerprinting. Use --no-sandbox to disable gVisor isolation.
sfw diff [--no-sandbox] <old.go> <new.go>
Compute semantic delta using the Zipper algorithm with topology-based function matching. Outputs risk scores and structural deltas.
sfw index <file.go> --name <name> --severity <CRITICAL|HIGH|MEDIUM|LOW> [--category <cat>] [--db <path>]
Index a reference malware sample. Generates topology hash, fuzzy hash, and entropy score.
sfw scan <file.go|directory> [--db <path>] [--threshold <0.0-1.0>] [--exact] [--deps] [--deps-depth <direct|transitive>] [--no-sandbox]
Scan target code for malware signatures. Use --exact for O(1) topology-only matching. Use --deps to scan imported dependencies. Use --no-sandbox to disable gVisor isolation.
sfw migrate --from <json> --to <db>
Migrate legacy JSON database to PebbleDB format for O(1) lookups.
sfw audit <old.go> <new.go> "<commit message>" [--api-key <key>] [--model <model>]
Verify if a commit message matches the structural code changes. Uses an LLM (default: gpt-4o, supports gemini-1.5-pro) to detect deception (e.g., hiding a backdoor in a "typo fix"). API key can also be set via OPENAI_API_KEY or GEMINI_API_KEY environment variables.
By default, sfw check, sfw diff, and sfw scan execute untrusted code analysis inside a gVisor sandbox (runsc) for defense-in-depth. This provides:
$ claude mcp add semantic_firewall \
-- python -m otcore.mcp_server <graph>