NeuroGuard
AI-native code security review powered by Gemma 4 Thinking Mode.
neuroguard-psi.vercel.app · github.com/tyy130/neuroguard-ai
Your AI writes bugs. NeuroGuard explains why — streaming Gemma 4's full reasoning trace while it produces a verified, secure rewrite.
Built for the Dev.to Google Gemma 4 Challenge · Python · JavaScript · TypeScript
The Problem
Studies find the majority of AI-generated applications ship to production with critical security vulnerabilities (source), mirroring classic OWASP Top 10 flaws. The most dangerous failure mode is the hallucinated bypass: an AI agent deletes authentication checks to resolve a compilation error — silently stripping the application of its security infrastructure.
The root cause is opacity. When a black-box model generates insecure code, you can't see why it made that decision — and neither can the model.
The Solution
Gemma 4's ThinkingConfig(include_thoughts=True) API turns the model into a glass box. Every reasoning step is emitted as a separate thought=True stream part — structurally separated from the final response at the API level. NeuroGuard wires this directly into a security workflow:
- Feed it a Python file or directory
- Gemma 4 streams its full cognitive trace — you watch it find each vulnerability in real-time
- It produces a complete, secure rewrite grounded in that explicit reasoning
- Bandit independently verifies the rewrite is clean
Why Gemma 4 specifically: GPT-4o and standard Claude hide their chain-of-thought entirely. DeepSeek-R1 exposes reasoning as raw text inside
<think>tags in the final response — making it impossible to cleanly separate reasoning from answer at the API level. Gemma 4'sinclude_thoughts=Truegives a structurally clean separation that makes NeuroGuard's two-pane architecture possible.
Demo
The built-in demo file contains 5 intentional vulnerabilities:
- Hardcoded
SECRET_KEYin source - Unauthenticated admin routes (broken access control)
- SQL injection via f-string interpolation (×2)
eval()on user input (remote code execution)- Debug mode enabled in production
Before: 4 HIGH/MEDIUM Bandit findings
After: ✓ CLEAN — Gemma 4's reasoning explains every fix
What NeuroGuard Catches
| Vulnerability | OWASP | Python | JS/TS |
|---|---|---|---|
| SQL Injection | A03 | ✓ | ✓ |
| Hardcoded secrets | A02 | ✓ | ✓ |
| Missing authentication | A01 | ✓ | ✓ |
eval() / code injection |
A03 | ✓ | ✓ |
| Debug mode in production | A05 | ✓ | ✓ |
| Insecure deserialization | A08 | ✓ | — |
| Weak cryptography / Math.random() | A02 | ✓ | ✓ |
| Path traversal | A01 | ✓ | ✓ |
| XSS (innerHTML / dangerouslySet) | A03 | — | ✓ |
| Command injection (exec) | A03 | — | ✓ |
| Prototype pollution | A08 | — | ✓ |
NeuroGuard is a first-pass tool — it complements, not replaces, tools like Semgrep, Snyk, or manual penetration testing. Runtime behavior, business logic flaws, and infrastructure misconfigurations are out of scope.
Quickstart
pip install neuroguard-ai
export GEMINI_API_KEY=your_key # Get a free key → https://aistudio.google.com/apikey
neuroguard review app.py
Try it in 60 seconds — run NeuroGuard against the built-in vulnerable demo:
pip install neuroguard-ai
export GEMINI_API_KEY=your_key # https://aistudio.google.com/apikey
git clone https://github.com/tyy130/neuroguard-ai
cd neuroguard-ai
neuroguard review demo/vuln_sample.py
You'll see: 4 HIGH/MEDIUM Bandit findings in the original → Gemma 4 reasoning through each one in real-time → a clean, verified secure rewrite.
Installation
Requirements: Python 3.12+ · Free Google AI Studio API key · Node.js (optional, for JS/TS projects)
pip install neuroguard-ai
Configure your API key (one-time):
export GEMINI_API_KEY=your_api_key_here
Or add to a .env file in your project root:
GEMINI_API_KEY=your_api_key_here
Usage
# Review a single Python file
neuroguard review app.py
# Review a JavaScript or TypeScript file
neuroguard review server.js
neuroguard review api.ts
# Review an entire directory (Python + JS/TS)
neuroguard review src/
# Save the secure rewrite
neuroguard review app.py --save app_secure.py
# JSON output (for CI/CD pipelines)
neuroguard review app.py --format json
# Use the MoE model (faster, slightly lower quality)
neuroguard review app.py --model gemma-4-26b-a4b-it
# Skip Bandit SAST verification
neuroguard review app.py --no-sast
# Add as a pre-commit hook
neuroguard install-hooks
# Version
neuroguard --version
Exit codes:
0— file is clean (no HIGH/MEDIUM findings in original)1— vulnerabilities found in original code
This makes it CI/CD friendly: your pipeline fails if a file with known vulnerabilities is committed without review.
CI/CD Integration
GitHub Actions
Copy .github/workflows/neuroguard.yml into your repository. Add GEMINI_API_KEY to your repo secrets and NeuroGuard will run on every pull request that touches Python files.
Pre-commit Hook
neuroguard install-hooks
pre-commit install
Or manually add to .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: neuroguard
name: NeuroGuard Security Review
entry: neuroguard review .
language: system
files: \.(py|js|jsx|ts|tsx)$
pass_filenames: false
require_serial: true
JSON Output
neuroguard review app.py --format json | jq '.original_findings'
Schema:
{
"file": "app.py",
"model": "gemma-4-31b-it",
"original_findings": 4,
"rewrite_findings": [],
"rewrite_valid": true,
"thinking": "...",
"response": "...",
"secure_code": "..."
}
Architecture
neuroguard/
├── cli.py # Typer CLI — review, install-hooks, --version
├── agent.py # Gemma 4 streaming client (google-genai SDK)
├── thinking_parser.py # Real-time <think>…</think> stream splitter
├── prompts.py # Language-aware system prompt + SAST findings injection
├── integrations.py # Slack Block Kit, generic webhook, GitHub PR comments
├── tools/
│ ├── sast.py # Bandit subprocess wrapper → Python findings
│ └── js_sast.py # semgrep/regex SAST → JS/TS findings
└── ui.py # Rich split-pane terminal layout
How Thinking Mode Works
NeuroGuard calls the Google AI Studio API with ThinkingConfig(include_thoughts=True), which causes Gemma 4 to emit reasoning tokens as separate thought=True stream parts — cleanly separated from the final response at the API level.
ThinkingStreamParser routes thought parts to the left "🧠 Gemma 4 Thinking" pane and response parts to the right "🔒 Secure Rewrite" pane in real-time. SAST findings from Bandit/semgrep are injected into the prompt so the model's reasoning is grounded in concrete, tool-verified signals — making the thinking trace an auditable chain of evidence, not free-form output.
The thinking budget scales dynamically: 4096 + HIGH_count × 512 + MEDIUM_count × 256 tokens (capped at 16384), so files with more severe findings get proportionally deeper reasoning.
Models
| Model | Type | Active Params | Notes |
|---|---|---|---|
gemma-4-31b-it |
Dense | 31B | Default — highest quality |
gemma-4-26b-a4b-it |
MoE | ~4B active / 26B total | Fallback — faster, lower cost |
Demo-proof: if the 31B model hits a rate limit during a live demo, NeuroGuard automatically falls back to the MoE variant with no interruption.
Why Gemma 4
Standard LLMs are black boxes for security review — you see the output but not the reasoning. Gemma 4's Thinking Mode changes this:
- Auditable: inspect the exact reasoning path before accepting any rewrite
- Trustworthy: the model can't silently delete auth checks if its reasoning is visible
- Compliance-ready: regulated industries can log and audit AI decision-making
- Open weight: Apache 2.0 license — run on-premise with the Kaggle weights or Ollama, no code ever leaves your network
This is the shift from vibe coding to AI-native development — treating AI output as an untrusted first draft, verified by both visible reasoning and automated SAST.
Integrations
NeuroGuard fires configured integrations after every review:
# Slack notification (findings + model reasoning excerpt)
neuroguard review app.py --notify-slack https://hooks.slack.com/...
# Generic webhook (Linear, Jira, Discord, etc.)
neuroguard review app.py --webhook https://your-endpoint.com/hook
# GitHub PR comments — auto-detected in GitHub Actions
# Set GITHUB_TOKEN in your workflow, no flags needed
Or configure via environment variables so every review fires automatically:
export NEUROGUARD_SLACK_WEBHOOK=https://hooks.slack.com/...
export NEUROGUARD_WEBHOOK_URL=https://your-endpoint.com/hook
Slack notifications include the vulnerability count, model used, rewrite status, and Gemma 4's top reasoning excerpts — making every security finding a traceable, shareable artifact.
License
Apache 2.0 — same as Gemma 4 itself.
If you found NeuroGuard useful, consider leaving a reaction on the Dev.to submission — it helps with the challenge judging.
Metadata
Release files for neuroguard-ai 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| neuroguard_ai-0.1.3.tar.gz | 402.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neuroguard_ai-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 425.7 kB
Release files / neuroguard_ai-0.1.3.tar.gz
| Download URL | neuroguard_ai-0.1.3.tar.gz |
|---|---|
| Size | 402.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fbd7d1ee0234f3465cbf3690799ddd192a2ea1b93ba1d9c6843390c561851c9d
|
|
BLAKE2b-256 checksum How to use checksums |
10ad5d270ce736b559034e7d743b9b7e95914de5c06b30c47f0d07ce87e64c7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / neuroguard_ai-0.1.3-py3-none-any.whl
| Download URL | neuroguard_ai-0.1.3-py3-none-any.whl |
|---|---|
| Size | 23.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
89c3589eb7cf226ff50b526e317071e65a09afa3dff8ff9039f91909aaf01d3a
|
|
BLAKE2b-256 checksum How to use checksums |
4d3fcd65688f55eaa74d21caa5e576b7cb2c79b18c7f6d21d633a2575a028a7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|