GRC Policy Analysis — Powered by Fine-Tuned Mistral 7B + Retrieval-Augmented Generation
Lacunae ControlSense analyzes security control statements against recognized frameworks, identifies implementation gaps, and produces structured, auditable gap registers. Upload your policy documents for organization-specific analysis, or analyze individual controls against general best practice.
- Framework mapping — Maps controls to NIST CSF 2.0, CIS 18, NIST AI RMF, and OWASP LLM Top 10 with confidence scoring
- Gap identification — Finds implementation gaps with practitioner-level reasoning
- Remediation guidance — Structured remediation suggestions for each gap
- Risk acceptance criteria — Populated risk acceptance structure for every finding
- Document assessment — Scans entire policy documents, produces downloadable gap registers
- Org mode — Ingests your own policy library for organization-specific analysis
| Requirement | Notes |
|---|---|
| Docker Desktop | docker.com/products/docker-desktop |
| NVIDIA GPU | RTX 3070 or better recommended (8GB+ VRAM) |
| NVIDIA Container Toolkit | docs.nvidia.com/datacenter/cloud-native/container-toolkit |
| 30GB free disk | For model files |
| 24GB system RAM | For the one-time model merge (16GB may work but is tight) |
| HuggingFace account | Free — for model download |
git clone https://github.com/mrBenL/controlsense
cd controlsense
cp .env.example .envEdit .env and add your HuggingFace token:
HF_TOKEN=hf_your_token_here
Get a free token at huggingface.co/settings/tokens (read access is sufficient).
hf download MrBenL/controlsense --local-dir models/controlsense-adapterThis pulls the fine-tuned LoRA adapter (~84MB) into the location the merge step expects. If the hf command is not found, run pip install huggingface_hub first, or use the Python equivalent:
python3 -c "from huggingface_hub import snapshot_download; snapshot_download('MrBenL/controlsense', local_dir='models/controlsense-adapter')"This one-time preparation runs on your host machine. First install the preparation dependencies (these are separate from the lean runtime set and are not needed once the model is built):
pip install -r requirements-prepare.txt# Merge LoRA adapter into base model (~20 min)
python3 scripts/prepare_model.py
# Convert to GGUF format for Ollama (~20 min, requires Docker)
bash scripts/convert_to_gguf.shThis produces models/lacunae-controlsense-q8.gguf (~8GB).
docker compose upFirst launch downloads the Ollama image and loads the model. Subsequent launches start in ~30 seconds.
Open http://localhost:7860 in your browser.
Paste a security control statement and select a mode:
- Standard Mode — Analysis using general security best practice (no documents required)
- Org Mode — Analysis enriched with your uploaded policy documents
Example control:
"The organization shall implement multi-factor authentication for all privileged accounts and review access quarterly."
- Upload a policy document in the Document Library tab (PDF, DOCX, or TXT)
- Click Ingest Documents
- Switch to Assessment tab
- Select your document and the framework areas it should cover
- Click Scan for Gaps →
- Download the gap register CSV when complete
Upload and manage organizational policy documents for Org Mode analysis. Supported formats: PDF, DOCX, TXT.
| Operation | Time |
|---|---|
| Single control analysis | ~25-35 seconds |
| 30-control document scan | ~15-20 minutes |
| Document ingestion (10 pages) | ~30 seconds |
docker compose up
│
├── lacunae-app (python:3.12-slim)
│ Gradio UI + RAG pipeline
│ Sends inference requests via HTTP
│
└── lacunae-ollama (ollama/ollama)
Mistral-7B Q8_0 GGUF
GPU inference
User data is stored in local mounted volumes — nothing is sent to external services.
# Stop
docker compose down
# Restart (fast, model stays loaded)
docker compose up
# Full rebuild after code changes
docker compose up --buildgit pull
docker compose up --buildYour documents, ChromaDB index, and gap registers are preserved in local volumes.
"Cannot connect to Ollama"
docker compose logs ollama
# Ensure NVIDIA Container Toolkit is installed
nvidia-smi # Should show your GPU"Model not found in Ollama"
# Re-register the model
docker compose run --rm ollama ollama create lacunae-controlsense -f /scripts/ModelfilePort 7860 already in use
# Change port in docker-compose.yml
ports:
- "7861:7860"Out of VRAM The Q8_0 model requires ~8GB VRAM. If you see CUDA OOM errors, close other GPU-intensive applications.
GGUF conversion fails on tokenizer
If convert_to_gguf.sh errors with a tokenizer or TokenizersBackend
message, the SentencePiece tokenizer.model is missing from the merged
model directory. prepare_model.py fetches it automatically; if you are
converting a manually-prepared model, copy tokenizer.model from the base
model into models/controlsense-merged/ before running the conversion.
- Coverage is limited to the frameworks and control domains represented in the training data; controls outside that scope may be mapped poorly or not at all.
- The model can produce plausible but incorrect framework citations, and can occasionally assign a confident but fabricated code (a non-existent framework version or an invented subcategory). The output sanitizer rejects fabricated codes structurally, so the affected control is surfaced as "No confident mapping" rather than a false mapping. Confidence scores and citations support human verification, not replace it; review mappings before relying on them.
- Output is non-deterministic; identical inputs may produce slightly different results.
Lacunae ControlSense is released under a dual license:
- Personal use: Free for individual practitioners, researchers, and students
- Commercial use: Organizations using this software for business purposes require a commercial license
See LICENSE for details.
Issues and pull requests welcome. See CONTRIBUTING.md for guidelines.