Truscan: open-source LLM security scanning you can ship from day zero

Published on
January 30, 2026

LLM features are landing everywhere—chat assistants, copilots, “agentic” workflows that can read/write files, call internal APIs, trigger payments, and automate ops. The security catch is that these apps introduce new failure modes (prompt injection, excessive agency, insecure output handling, model DoS, supply-chain risks) that don’t always look like classic AppSec bugs, but still lead to classic outcomes: data leakage, unauthorized actions, and code/command execution.

OWASP’s Top 10 for LLM Applications consistently puts Prompt Injection at the top and enumerates the broader categories teams need to engineer for. The UK’s NCSC has also warned that prompt injection is structurally different from SQL injection—there may not be a “one-shot mitigation,” which makes defense-in-depth + detection + containment essential. 

That’s why we’re open-sourcing Truscan: a practical scanner you can wire into repos immediately—so teams start building secure AI systems the same way they build secure web apps: with continuous, automated feedback loops.

What Truscan is

Truscan (Trusys LLM Security Scanner) is a Python-based code scanning tool built on the Semgrep Python SDK to detect AI/LLM-specific vulnerabilities. It’s designed to run in:

  • GitHub Actions / CI (headless), and
  • IDEs (VS Code + Visual Studio) as the scanning engine behind extensions. (GitHub)

Why a dedicated LLM scanner (and why now)

Traditional SAST finds a lot of important issues, but LLM apps have patterns that need specific detection logic:

  • user input used in prompts without guardrails (prompt injection),
  • LLM output used in sensitive sinks (insecure output handling),
  • agent tool execution without authorization boundaries (excessive agency / insecure plugin design),
  • model cost & latency attacks (model DoS),
  • “shadow” models, untrusted packages, and risky connectors (supply chain). (GitHub)

Truscan’s goal is simple: make the secure path the default by scanning these AI-specific patterns continuously.

Core advantages

1) Uses Semgrep’s Python SDK directly (no CLI subprocess glue)

Truscan integrates Semgrep using Python APIs—this matters for embedding scanning inside IDEs and for tighter control over configs, outputs, and performance. (GitHub)

2) Output formats that fit real workflows

Truscan supports:

  • SARIF for GitHub Code Scanning,
  • JSON for IDE integration,
  • Console output for humans. (GitHub)

GitHub Code Scanning supports a subset of SARIF 2.1.0, which is why SARIF output is key for first-class “Security” tab integration. (GitHub Docs)
(And SARIF itself is an OASIS standard format for static analysis results.) (OASIS Open)

3) Offline-first by default

All scanning runs without network access—useful for regulated environments and predictable CI. (GitHub)

4) Extensible rule system mapped to LLM risk categories

Truscan organizes rules as Semgrep rule packs and explicitly aligns coverage to OWASP LLM risk categories (LLM01–LLM10). (GitHub)

5) Performance-oriented scanning

Incremental scanning, .gitignore respect, include/exclude patterns, severity filtering—built to run continuously without killing developer velocity. (GitHub)

What Truscan detects (and how it thinks about risk)

OWASP-aligned coverage (LLM01–LLM10)

The repo lists a structured mapping to categories like:

  • LLM01 Prompt Injection
  • LLM02 Insecure Output Handling
  • LLM04 Model Denial of Service
  • LLM08 Excessive Agency
  • LLM09 Overreliance
  • LLM10 Model Theft
    …and more. (GitHub)

This is deliberately aligned with OWASP’s taxonomy so teams can:

  • track coverage,
  • justify controls to auditors,
  • and prioritize remediation in a language security teams already understand. 

Core “dangerous sink” patterns (pragmatic, high-signal)

Truscan starts with patterns that repeatedly show up in real incidents:

  • Code injection (CWE-94): LLM output passed to eval/exec/compile (GitHub)
  • Command injection (CWE-78): LLM output passed to subprocess.* or os.system (GitHub)
  • XSS (CWE-79): LLM output rendered in HTML without escaping (GitHub)

Supported LLM API patterns (so the scanner finds the real usage)

Out of the box, the rules account for common ways teams call LLMs, including:

  • OpenAI legacy API + v1 client styles,
  • Anthropic messages API,
  • and generic wrapper conventions (call_llm(), .generate(), .chat()). (GitHub)

Architecture (built to be embedded)

Truscan isn’t “just a rules folder”—it’s a full scanning engine you can embed:

  • engine/
    • semgrep_engine.py (Semgrep SDK integration)
    • ai_engine.py + ai_providers.py (optional AI filtering)
  • output/
    • sarif.py, json.py, console.py
  • rules/
    • Provider-organized rule packs (OpenAI, Anthropic, etc.)
  • Optional backend/ (Node + MySQL) to store results, Semgrep-dashboard style
  • IDE integrations for VS Code + Visual Studio (GitHub)

This structure is what enables the “day zero” promise: you can start with CLI/CI, and then graduate to richer IDE and backend experiences without changing scanners.

Optional: AI-powered false positive filtering (noise reduction, not magic)

Static pattern matching is powerful, but any scanner can produce noise—especially as frameworks add safe defaults and sanitizers.

Truscan includes an optional AI-based false positive filter that:

  1. runs Semgrep,
  2. selects findings (by default, medium/low confidence),
  3. asks an LLM to assess exploitability in context (sanitization, framework protections, etc.),
  4. filters only high-confidence false positives (threshold configurable). (GitHub)

This is disabled by default and designed to be used intentionally—especially for large codebases where triage cost is real.

Getting started (fast path)

Install

pip install trusys-llm-scan

(GitHub)

Run a local scan

trusys-llm-scan . --format console

(GitHub)

Generate SARIF for GitHub Code Scanning

python -m llm_scan.runner src/ tests/ \

  --rules llm_scan/rules/python \

  --format sarif \

  --out results.sarif \

  --exclude 'tests/**'

(GitHub)

What “good” looks like in practice

A strong LLM security posture isn’t just “block prompt injection.” Even government guidance is leaning toward the reality that prompt injection may remain a persistent category, pushing teams toward impact reduction through boundaries and controls. (ncsc.gov.uk)

Truscan helps enforce those boundaries continuously by flagging:

  • places where untrusted text becomes instructions,
  • where model output becomes executable,
  • where agents are over-privileged,
  • and where LLM use is creeping into sensitive surfaces without guardrails. (GitHub)

How the community can shape Truscan next

We want this to be a genuine developer-first open source contribution, and we’d love concrete suggestions and PRs. A few high-impact directions:

  1. More frameworks / agent ecosystems
    • LangChain, LlamaIndex, CrewAI, Semantic Kernel, OpenAI Assistants patterns
  2. Better dataflow
    • More taint-style flows and sanitizers (high-confidence, low-noise)
  3. More languages
    • The architecture supports Python/JS/TS, and we want the rule packs to catch up. (GitHub)
  4. Rule quality bar
    • More minimal repro samples + tests per rule to prevent regressions
  5. CI templates
    • Drop-in GitHub Action examples for monorepos and mixed stacks

If you’re building LLM apps and want Truscan to catch something specific you’ve seen in the wild (or in your own code reviews), open an issue with:

  • a minimal code snippet,
  • expected finding,
  • and what “safe” looks like.

Summarise page: