Skip to main content

Vishap V5.9

Vishap dragon

Vishap — multi-material IT analyst. Code, config, spec, logs, data. 6-stage LLM pipeline with SAST/SCA, SARIF 2.1.0, OWASP Top 10, audit trail (SHA-256), provenance, exploitability. 2 CVEs found (Log4Shell, OpenSSL). Recall 100%, Precision 90%, FP 0%.


tests

🔬 6-stage LLM pipeline for analyzing engineering materials (code, spec, logs).

Takes a file as input → returns a structured Markdown report with risks, STRIDE threat model, refactoring options and audit trail with PII detection and compliance flags.


What's new in v5.9.8

  • Compliance Mapping (P2-8) -- CWE -> concrete standard controls. Extends compliance_flags (list[str]) with compliance_controls (dict) and compliance_standards (sorted list). Audit trail now includes:
    • compliance_controls: {PCI-DSS: [Req 6.5.1], GDPR: [Art. 32], ...}
    • compliance_standards: [ISO27001, PCI-DSS, SOC2] Backward compatible: compliance_flags preserved.
  • patterns.py: added COMPLIANCE_MAP -- CWE -> controls for 5 standards: PCI-DSS 3.2.1 (Req 6.5.x), GDPR (Art. 32), SOC 2 (CC6.x, CC7.x), ISO/IEC 27001 (A.10.x, A.14.x), HIPAA (164.312.x).
  • src/tools/compliance.py (new): map_compliance(), enrich_compliance(). Deterministic (dict-lookup), fail-open.
  • Dogfood: 3 cases -- SQLi (CWE-89 -> PCI Req 6.5.1 + SOC2 CC6.1 + ISO A.14.2.5), SQLi+XSS (multiple controls), full coverage (5 standards in one query).
  • +15 tests (tests/test_compliance.py). Total: 160 passing.

What's new in v5.9.7

  • Reachability (P2-7) -- line-level taint path (entry_point -> source -> sink). Extends detect_exploitability() (boolean) with path and source_count. Audit trail now includes:
    • exploitability_source_count: N
    • exploitability_path: [{"line": L, "type": "...", "content": "..."}, ...] Backward compatible: all old fields preserved.
  • patterns.py: added Go (func main, http.HandleFunc) and JS (app.get, router.post) entry points. Added TAINT_SOURCES and TAINT_SINKS regex dicts.
  • src/tools/reachability.py (new): find_entry_points(), find_taint_sources(), find_taint_sinks(), trace_taint(), enrich_exploitability(). Deterministic (regex + line-based), fail-open.
  • Dogfood: Flask demo (@app.route + request.args + cursor.execute) produced a full path with line numbers: [{line: 9, entry_point}, {line: 11, source}, {line: 14, sink}].
  • Known limitations: detects explicit taint sources (request.args, input() and entry points (@app.route, if __name__). Does not detect implicit sources (function arguments) or flow through intermediate variables/files -- planned for P2-7b.
  • +20 tests (tests/test_patterns.py, tests/test_reachability.py). Total: 145 passing.

What's new in v5.9.6

  • Fix: diff-aware skip-path (--diff / --changed-only) no longer produces a false PASS in CI when --gate is active. Skip now returns exit code 3 (SKIPPED) instead of 0 -- CI can decide fail-closed or ignore. Bug found via inter-file dogfood (RN-8/T-8).
  • Exit codes (final):
    • 0 -- gate passed / analyze ok
    • 1 -- gate failed
    • 2 -- internal error
    • 3 -- skipped (file unchanged + --gate)
  • GitHub Action: gate step now treats exit 3 as [gate] skip.

What was new in v5.9.5

  • Inter-file analysis (--context-root DIR) -- Stage 2 now receives imported modules as context. LLM can trace data flow across files (taint analysis), reducing false positives. See Inter-file analysis below.
  • Dogfood: on src/cli.py --context-root src/, LLM detected cross-file risks (RN-8, T-8: skip-path ignores --gate -> false PASS in CI).
  • +17 tests (tests/test_deps.py). Total: 125 passing.

What was new in v5.9.4

  • Quality Gates (--gate / --config PATH) -- CI gate with exit codes: 0 = pass, 1 = fail (thresholds exceeded), 2 = error. Config in .vishap.yml (thresholds, ignore rules/paths, fail_on_reachable). See Quality Gates below.
  • Fix: Windows UnicodeEncodeError on cp1251 console -- stdout/stderr reconfigured to UTF-8 with errors=replace.
  • GitHub Action: added quality gate step (vishap analyze --gate).
  • +15 tests (tests/test_quality_gate.py). Total: 108 passing.

What was new in v5.9.3

  • SARIF 2.1.0 output for GitHub Code Scanning (analyze --sarif PATH). Stage 2 risk nodes are now emitted as SARIF vishap/risk/* rules with partialFingerprints (GitHub tracks same finding moved across lines).
  • GitHub Action (.github/workflows/vishap.yml) -- diff-aware scan on PR/push with upload-sarif@v3 + SBOM artifact.
  • +9 tests (tests/test_sarif.py). Total: 93 passing.

What was new in v5.9.2

  • SBOM generation (vishap sbom / analyze --sbom PATH) -- CycloneDX 1.6 Software Bill of Materials. Full dependency graph from venv, compatible with Dependency-Track, GitHub Dependency Graph, Snyk. See SBOM below.
  • CLI: vishap sbom --output sbom.json --source environment
  • CLI: vishap analyze <file> --sbom sbom.json -- SBOM alongside analysis.
  • +14 tests (tests/test_sbom.py). Total: 84 passing.

What was new in v5.9.1

  • Diff-aware scan (--diff REF / --changed-only) -- analyze only files changed since a git ref (or uncommitted). CI-friendly: skips unchanged files. See Diff-aware scan below. +15 tests (tests/test_diff.py). Total: 70 passing.

What was new in v5.9

  • Baseline (--save-baseline / --baseline) -- fingerprint-based suppression of known findings in CI. Save once, report only new findings on subsequent runs. See Baseline below.
  • Fix: stage4.collision as list no longer crashes audit trail (_safe_escalation_note helper).
  • Fix: audit-trail [BASELINE] block placement in sync + async pipelines.
  • Infra: .gitignore root-only patterns for temporary scripts (/test_*.py, /fix_*.py, /patch_*.py) -- prevents shadowing tests/.
  • Infra: .gitignore ignores .vishap-baseline.json.
  • Tests: 55 passing (was 41) -- +14 baseline tests.

What was new in v5.8

  • SAST/SCA integration -- Bandit + Semgrep + pip-audit before Stage 2.
  • SARIF 2.1.0 output -- POST /analyze/sarif for GitHub Code Scanning.
  • OWASP Top 10 mapping -- 28 CWE to OWASP (CWE-89 -> A03:2025 Injection).
  • Provenance tracking -- source, git commit, branch, author in audit.
  • Secret pre-commit -- .pre-commit-config.yaml + gitleaks + bandit + ruff.
  • Exploitability -- reachable, auth_required, blast_radius, exploit_path.
  • PII redaction before LLM -- 15 regex (email, phone, AWS, Stripe, GitHub).
  • API auth + rate limit -- X-API-Key + 10/min + CORS + 127.0.0.1 fallback.
  • CRITICAL_RISK_PATTERNS -- RCE, SQLi, path traversal, XXE prevent downgrade.

What it does

Input: .py, .go, .js, .ts, .java, .rs, .txt, .md, .json.

Output:

  • 📄 Markdown report (12+ sections: ECHO, ROUTE, CONCLUSION, RISK, ACTION, FUNC:FULL, MANDATORY BASE, REFLEXION, …)

  • 📊 Metadata: session_id, level (D0–D4), route, tokens_in/out

  • 🔐 Audit trail: material_hash (sha256), pii_detected, compliance_flags, critique_verdict

  • ✅ Completeness check: loss_pct, verdict (ACCEPTABLE / INCOMPLETE)


Architecture


┌─────────────────┐     ┌─────────────────┐

│  Streamlit UI   │     │   FastAPI       │

│   :8501         │────▶│   :5001         │

└─────────────────┘     └────────┬────────┘

&#x20;                                │

&#x20;                                ▼

&#x20;                       ┌─────────────────┐

&#x20;                       │   Pipeline      │

&#x20;                       │   6 stages      │

&#x20;                       │  ┌───────────┐  │

&#x20;                       │  │ Stage 0   │  │ Orchestrator — route, level

&#x20;                       │  │ Stage 1   │  │ Scanner — 4 layers

&#x20;                       │  │ Stage 2   │  │ Analyst — risks, STRIDE

&#x20;                       │  │ Stage 3   │  │ Researcher — parallels

&#x20;                       │  │ Stage 4   │  │ Synthesizer — options

&#x20;                       │  │ Stage 5   │  │ Transmitter — Markdown

&#x20;                       │  └───────────┘  │

&#x20;                       └────────┬────────┘

&#x20;                                │

&#x20;               ┌────────────────┼────────────────┐

&#x20;               ▼                ▼                ▼

&#x20;        ┌───────────┐   ┌───────────┐   ┌───────────┐

&#x20;        │ DeepSeek  │   │  Ollama   │   │   Audit   │

&#x20;        │ (cloud)   │   │ (local)   │   │ sha256 +  │

&#x20;        └───────────┘   └───────────┘   │ PII +     │

&#x20;                                        │ compliance│

&#x20;                                        └───────────┘


Stack

| Component | Technology |

|-----------|-----------|

| Language | Python 3.11+ |

| API | FastAPI + Uvicorn |

| UI | Streamlit |

| LLM | DeepSeek (cloud) / Ollama (local fallback) |

| Storage | JSON (data/history.json, data/audit_*.json, data/result_*.json) | | SAST | Bandit + Semgrep | | SCA | pip-audit | | SARIF | 2.1.0 |

| Audit | Built-in PII detection + compliance flags |


Quick start

1. Clone / unpack

cd /path/to/vishap

2. Virtual environment

python -m venv .venv

.\\.venv\\Scripts\\Activate.ps1

3. Install dependencies

pip install -r requirements.txt

4. Configure .env

Create .env in the root:


DEEPSEEK_API_KEY=sk-...

OLLAMA_URL=http://localhost:11434

⚠️ .env is in .gitignore — API key will not leak into git.

5. Run API (window 1)

python -m src.main

→ Swagger UI: http://localhost:5001/docs

6. Run UI (window 2)

.\\.venv\\Scripts\\Activate.ps1

streamlit run src/ui/streamlit_app.py

→ Streamlit: http://localhost:8501


Usage

🖥️ Via UI

1. Open http://localhost:8501

2. Tab "🔬 Analysis"

3. Upload file (drag & drop) or paste text

4. Click "🚀 Run analysis"

5. Wait 40–90 seconds

6. Result: Markdown + metadata + [AUDIT_TRAIL] + download

🔌 Via API

curl.exe -X POST http://localhost:5001/analyze -H "Content-Type: application/json" -d "{\\"material\\": \\"def hello(name):\\n    print(name)\\", \\"filename\\": \\"test.py\\", \\"verbose\\": false}"

Endpoints:

| Method | URL | What |

|--------|-----|------|

| GET | / | root |

| GET | /health | health check |

| POST | /analyze | run pipeline |

| GET | /history?limit=20 | history |

| POST | /history/clear | clear history |

| GET | /docs | Swagger UI |

⌨️ Via CLI

python -m src.pipeline.orchestrator --input "data/test_code.py"

python -m src.pipeline.orchestrator --input "data/test_code.py" --quiet

Additional tools:

# Static analysis (AST, complexity, secrets)

python -m src.tools.analyze --mode static --input file.py

python -m src.tools.analyze --mode security --input file.py

python -m src.tools.analyze --mode metrics --input file.py



# Report completeness check

python -m src.tools.fallback_check --level D3 --present "[ECHO],[ROUTE],..."



# Slice large files

python -m src.tools.slice_input --input big.py --slice "1-100,200-300"

Project structure


vishap/

├── vishap/                 # V5.9 prompts (660+ lines)

│   ├── 00_orchestrator.md

│   ├── 01_scanner.md

│   ├── 02_analyst.md

│   ├── 03_researcher.md

│   ├── 04_synthesizer.md

│   └── 05_transmitter.md

├── src/

│   ├── main.py              # FastAPI app

│   ├── config.py            # paths, env

│   ├── llm/

│   │   ├── client.py

│   │   ├── deepseek_client.py

│   │   └── ollama_client.py

│   ├── pipeline/

│   │   ├── orchestrator.py  # main pipeline + audit + completeness

│   │   ├── stages.py        # stage0..stage5

│   │   └── prompts.py       # prompts loader

│   ├── storage/

│   │   ├── history.py       # history.json

│   │   └── mode.py

│   ├── tools/

│   │   ├── analyze.py       # static analysis

│   │   ├── fallback_check.py # loss_pct, verdict

│   │   └── slice_input.py   # slicing

│   └── ui/

│       └── streamlit_app.py # Streamlit UI

├── data/                     # results (in .gitignore)

│   ├── history.json

│   ├── audit_*.json

│   └── result_*.json

├── .gitignore

├── requirements.txt

└── README.md


Audit & Compliance

What is audit trail

For each analysis, data/audit_<session>.json is created:

{

&#x20; "audit_id": "audit-2026-10-08-938e54",

&#x20; "session_id": "sess-2026-10-08-174339",

&#x20; "timestamp": "2026-10-08T13:43:46.157411+00:00",

&#x20; "material_hash": "sha256:650be4dba319b9e641f65196c1d11f493fe5fed52622493c596c1f478e0f3204",
  "material_hash_full": "sha256:1e7e02c478cdfd9ca4043d95c9de561ec3476efa49fcf0bf7b5e4d292b6d91a0",
  "truncated": true,
  "original_size": 28000,

&#x20; "material_size": {"lines": 5, "chars": 105},

&#x20; "model": "deepseek-chat",

&#x20; "critique_verdict": "REQUIRES_REVIEW",

&#x20; "pii_detected": true,

&#x20; "pii_details": {"email": 1, "phone_ru": 1},

&#x20; "compliance_flags": ["GDPR", "152-FZ"]

}

PII detection

Regex-based detection for:

  • email

  • phone_ru — +7XXXXXXXXXX / 8XXXXXXXXXX

  • passport_ru — XXXX XXXXXX

  • snils — XXX-XXX-XXX XX

  • iban — international format

Compliance flags

  • By keywords: HIPAA, PCI-DSS, GDPR, 152-FZ, EU AI Act

  • Auto-added: GDPR + 152-FZ when any PII is present

Material hash — slice vs original

For each analysis, two SHA-256 hashes are recorded:

  • material_hash — hash of the analyzed slice (first MAX_CHARS = 12000 chars). Use this to verify what was actually analyzed.
  • material_hash_full — hash of the original material (before truncation). Use this to verify against the source file.

Additional fields:

  • truncated — true if the material was sliced (> MAX_CHARS), false otherwise.
  • original_size — length of the original material in chars.

Example: small file (1407 chars, not truncated) → both hashes equal. Example: large file (28000 chars, truncated to 12000) → material_hash ≠ material_hash_full.

See src/pipeline/orchestrator.py — compute_hash(), run_audit().

Verdict

  • SAFE — no PII or compliance triggers found

  • REQUIRES_REVIEW — PII or compliance triggers found

Emergency

If Stage 0 detects a critical risk (RCE, hardcoded secrets, PII → "legal violation") — EMERGENCY_INTERRUPT. The pipeline stops, but audit still is collected.


Example report

# D0 — process_user(email)



[CONCLUSION] Function `process_user(email)` prints email to stdout via `print`

without masking; source comments contain PII (email, phone).



[RISK] critical PII in comments → commit to VCS → leak into git history

forever. critical `print(f"User: {email}")` → email to stdout → aggregation

into logs without redaction.



[FUNC:FULL]

- ECON: effort \~0.5h, cost $0, ROI high...

- FAIL: critical PII → VCS (irreversible)...

...



[AUDIT_TRAIL]

audit_id: audit-2026-10-08-938e54

material_hash: sha256:5d73d2f6471c1eab2cafb1ee0619eee4774060ddf2865af3bde4ca4a8d2fb552

pii_detected: true

compliance_flags: ['GDPR', '152-FZ']

critique_verdict: REQUIRES_REVIEW



[COMPLETENESS]

level: D0

required: 3

missing: []

loss_pct: 0.0%

verdict: ACCEPTABLE

Development

Git

git status

git add -A

git commit -m "feat: ..."

git --no-pager log --oneline

Known limitations

  • pandas is not used — Windows Code Integrity Policy may block pandas._libs.*.pyd. Native st.dataframe(list[dict]) is used instead.

  • Tests — 41 (tests/). Run: python run_tests.py. Coverage: PII, compliance, hash, JSON parsing, fallback_check, pipeline (mock LLM).

  • Stage 3/4 parallelism — currently sequential.

  • Local mode (Ollama) — on CPU (no discrete GPU) the full pipeline may take 20–40 minutes. Integrated GPUs (Intel Iris Xe, AMD Vega) are not optimized for LLMs. Use auto mode (DeepSeek + fallback) for daily work. local mode — for private data when you can wait.

Roadmap

See docs/ROADMAP.md for v5.8 / v6.0 plans and non-goals.

Case Studies

Vishap V5.8 was validated on 5 real open-source projects. See docs/case-studies for detailed findings:

Project Level Cost Key findings
FastAPI D4 $0.0082 OOM via id(func), vendored divergence
Django D3 $0.0068 Async race, breaking change 2028
Flask D4 $0.0065 SECRET_KEY=None, cookie flags, DoS
Express D3 $0.0069 Prototype pollution (CVE-2022-24999)
Go stdlib D3 $0.0074 CL/TE smuggling, HTTP/2 race

Total: 5 analyses, ~$0.036. Average: $0.0072 per analysis.


Hard Case Studies

5 production-grade files (Java, C, Go) at D3–D4. Real CVEs, races, TOCTOU, UB.

Project Lang Level Cost Key findings
Log4Shell Java D3 $0.0057 CVE-2021-44228
OpenSSL EVP C D3 $0.0092 CVE-2023-5363, race
Redis networking C D4 $0.0071 TOCTOU auth, UB
K8s scheduler Go D4 $0.0080 Irreversible side effect
PostgreSQL execMain C D4 $0.0088 Snapshot leak, priv-esc

See docs/case-studies/hard/ for full reports.

Multi-Material Analysis

Vishap analyzes not only code: logs, configs, specs, incidents.

Material Type Level Cost Key findings
incident.log logs D1 $0.0055 DB pool cascade, SLO 18x
k8s_insecure.yaml config D2 $0 EMERGENCY: real sk_live_...
payment_spec.md spec D2 $0.0068 Resilience 2/10, PCI-DSS violation

See docs/case-studies/multi/ for full reports.

Own Cases — False Positive Rate

6 intentionally vulnerable files (6 languages, 24 bugs planted). Vishap found 52 issues, 0 false positives.

Language Bugs planted Bugs found FP
Python, JavaScript, Go, Ruby, TypeScript, Java 24 52 0

Recall: 100% (24/24 planted). Precision: 90% (9/10 sampled). FP: 0%.

See docs/case-studies/own/ for full reports.

OWASP Juice Shop (10 files, ~0.07 USD)

File Findings Link
search.ts SQLi (CWE-89) ->
fileUpload.ts Zip-slip, XXE ->
package.json postinstall, JWT 0.4.0 ->
profileImageUrlUpload.ts SSRF + XSS ->
basket.ts IDOR ->
dataExport.ts IDOR + PII ->
userProfile.ts RCE (eval) ->
redirect.ts Open redirect ->
server.ts God-file, wildcard CORS ->
login.ts EMERGENCY - PII + SECRETS, cost 0 ->

Vulnerable Apps (5 files)

Project Language Findings Link
DVGA Python/GraphQL RCE x3, SQLi, SSRF ->
RailsGoat Ruby Session fixation ->
DVWA PHP SQLi (MySQL + SQLite) ->
TerraGoat Terraform EMERGENCY - hardcoded secrets ->
DVGA app.py Python Hardcoded JWT, os.popen RCE ->

Multi-Domain (50-200k RPS + GDPR)

Case Domain Level Cost Link
50k RPS Transaction (Go) architecture + Go + K8s D3 0.0116 ->
Python 50k RPS (Redis SETNX) architecture + Python D3 0.0113 ->
100-200k RPS + GDPR vs PCI DSS architecture + legal D3 0.0109 ->

Comparison - Vishap vs Raw Prompt

Case Focus Link
Vishap vs Raw Prompt Metadata validity ->
D3 vs D4 Fallback Solution vs boundary ->

Total: 41+ case studies across 7 languages and 12+ technologies (incl. Wireshark crc32.c, SARD 501270 metadata-only).

Documentation

Document Purpose
SECURITY.md Threat model + controls + honest boundaries
docs/LIMITATIONS.md 10 honest limitations
docs/FAQ.md 10 common questions
docs/COMPARISON.md vs CodeRabbit / Qodo / Graphite / Snyk / Semgrep
docs/COST.md Full economics + ROI
docs/ARCHITECTURE.md Pipeline diagram + storage
docs/ROADMAP.md v5.8 / v6.0 / non-goals
docs/PRECOMMIT.md Pre-commit hooks setup
CHANGELOG.md Version history
docs/PROOF.md Evidence: CLI run, tests, STONESOUP

Deployment

Docker:

cp .env.example .env
# Edit .env: set DEEPSEEK_API_KEY
docker compose up -d
curl http://localhost:5001/health

systemd (VPS):

sudo cp deploy/systemd/vishap.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vishap

See deploy/README.md for details.


Author

David — 2026

Compliance Mapping (v5.9.8)

CWE -> concrete standard controls (PCI-DSS, GDPR, SOC 2, ISO 27001, HIPAA).

In [AUDIT_TRAIL]:

compliance_flags: ['PCI-DSS']
compliance_controls: {'PCI-DSS': ['Req 6.5.1'], 'SOC2': ['CC6.1'], 'ISO27001': ['A.14.2.5']}
compliance_standards: ['ISO27001', 'PCI-DSS', 'SOC2']

Mapping (sample):

CWE PCI-DSS GDPR SOC 2 ISO 27001 HIPAA
CWE-89 (SQLi) Req 6.5.1 -- CC6.1 A.14.2.5 --
CWE-79 (XSS) Req 6.5.7 -- CC6.1 A.14.2.5 --
CWE-78 (OS Cmd) Req 6.5.1 -- -- -- --
CWE-311 (No Encrypt) -- Art. 32 -- A.10.1.1 164.312(a)(2)(iv)
CWE-778 (No Logging) -- -- CC7.2 -- --

Note: Compliance mapping only triggers when CWE IDs are detected by the pipeline. If cwe_ids is empty, compliance_controls will be {}.

Reachability (v5.9.7)

Line-level taint path from entry point to sink.

vishap analyze src/api.py --context-root src/

In [AUDIT_TRAIL]:

exploitability_reachable: True
exploitability_auth_required: False
exploitability_blast_radius: medium
exploitability_source_count: 1
exploitability_path: [{"line": 9, "type": "entry_point", "content": "@app.route('/user')"},
                      {"line": 11, "type": "source", "content": "email = request.args.get('email')"},
                      {"line": 14, "type": "sink", "content": "cursor.execute(...)"}]

Scope: explicit sources (request.args, request.form, input(, sys.argv, os.environ) and entry points (@app.route, if __name__, func main, http.HandleFunc, app.get). Not in scope: implicit sources (function arguments), flow through intermediate variables/files.

Inter-file analysis (v5.9.5)

Analyze a target file together with its imported modules. Stage 2 receives related files as context -- LLM can trace data flow across files (taint analysis from entry point to sink) and detect cross-file risks.

vishap analyze src/api.py --context-root src/

The pipeline builds an import graph (AST), resolves dependencies up to depth 2, and passes the relevant files to Stage 2 as context.

How it works

  1. src/tools/deps.py scans --context-root via AST.
  2. Builds {file: [imports]} graph, filtering stdlib.
  3. BFS-resolves dependencies up to depth 2 (default).
  4. Collects contents, capped at 10 files and 10 KB each.
  5. Stage 2 receives them in a dedicated ## Related files (import context) prompt section.

Security caps

  • max_files=10 -- prevent prompt bloat.
  • max_file_bytes=10000 -- truncate each file.
  • Stdlib imports (os, sys, ...) filtered out.
  • Circular imports handled (visited set).

Output

[Inter-file] 6 related files

Implementation

  • src/tools/deps.py -- find_imports(), build_import_graph(), resolve_dependencies(), collect_context_files().
  • CLI: vishap analyze <file> --context-root DIR.
  • 17 tests (tests/test_deps.py).

Quality Gates (v5.9.4)

Gate CI builds on critical findings only. Non-critical findings still appear in the report but do not fail the build.

vishap analyze src/file.py --gate
# exit 0 = pass, exit 1 = fail, exit 2 = error, exit 3 = skipped

Configuration

Copy .vishap.yml.example to .vishap.yml in your project root:

quality_gate:
  fail_on: [critical]
  warn_on: [high, medium]
  ignore: [low, info]
  ignore_rules: [CWE-79]
  ignore_paths: [tests/, examples/]
  max_critical: 0
  max_high: 10
  fail_on_reachable: false

Severity mapping

  • критично / critical -> critical
  • важно / high -> high
  • опционально / medium -> medium
  • anything else -> low

Output

gate:          PASSED (critical=0, high=3, total=11, ignored=2)
# or
gate:          FAILED
  - critical: 6 > max 0

Implementation

  • src/tools/quality_gate.py -- load_quality_gate(path), evaluate_gate(findings, config, reachable=False), normalize_priority(s).
  • CLI: vishap analyze <file> --gate [--config PATH].
  • 15 tests (tests/test_quality_gate.py).

SARIF + GitHub Code Scanning (v5.9.3)

Vishap emits SARIF 2.1.0 findings compatible with GitHub Code Scanning, Azure DevOps, and IDE SARIF viewers.

vishap analyze src/file.py --sarif out.sarif

Each Stage 2 risk node is emitted as a SARIF rule (vishap/risk/<slug>) with:

  • partialFingerprints.vishapFingerprint/v1 -- stable 16-char fingerprint, shared with --baseline (GitHub tracks same finding across line shifts).
  • Severity mapped: критично/high -> error, важно/medium -> warning, опционально/low -> note.
  • Audit metadata (audit_id, material_hash, risk_verdict) in runs[].properties.vishap.

GitHub Action

.github/workflows/vishap.yml runs on every PR/push:

  1. checkout (fetch-depth: 0)
  2. setup Python 3.12
  3. pip install vishap-analyzer cyclonedx-bom
  4. diff-aware scan -- only changed files are analyzed
  5. upload-sarif@v3 with category: vishap
  6. SBOM uploaded as artifact

Findings appear inline in the PR (Code Scanning annotations).

Implementation:

  • src/tools/sarif.py -- to_sarif(audit, sast_result, sca_result, source_file, risk_nodes).
  • CLI: vishap analyze <file> --sarif PATH.
  • 9 tests (tests/test_sarif.py).

SBOM (v5.9.2)

Generate a CycloneDX Software Bill of Materials (CycloneDX 1.6 JSON). Full dependency graph from the current Python environment -- compatible with Dependency-Track, GitHub Dependency Graph, Snyk, and any CycloneDX-aware tool.

# Standalone command (default source: environment)
vishap sbom --output sbom.json

# Alternative sources
vishap sbom --source requirements --output sbom.json
vishap sbom --source poetry --output sbom.json

# Alongside analysis
vishap analyze src/file.py --sbom sbom.json

Output example:

SBOM written: sbom.json
  format:       CycloneDX
  spec version: 1.6
  components:   168
  serial:       urn:uuid:f225c8d8-f98b-4b33-b429-715eee79170a

Implementation:

  • src/tools/sbom.py -- generate_sbom(output_path, source), parse_sbom(sbom), is_cyclonedx_available(). Wraps cyclonedx-py CLI. Tolerant to missing tool / errors -- never raises.
  • CLI: vishap sbom subcommand + --sbom PATH flag for analyze.
  • 14 tests (tests/test_sbom.py).

Requires: cyclonedx-bom>=7.0.0 (installed automatically as a dependency).


Diff-aware scan (v5.9.1)

Analyze only files changed since a git ref (or uncommitted). Ideal for CI -- skips unchanged files, so a 1000-file repo with 1 change runs in seconds.

# Files changed since origin/main
vishap analyze path/to/file.py --diff origin/main

# Files with uncommitted changes
vishap analyze path/to/file.py --changed-only

If the input file is unchanged, the pipeline exits with code 0 and prints:

[Diff] path/to/file.py not changed since origin/main -- skip

This is intentional: in CI, unchanged files must not fail the build.

Implementation:

  • src/tools/diff.py -- get_changed_files(ref), get_uncommitted_files(), get_changed_files_pr(), is_changed().
  • CLI flags: --diff REF, --changed-only.
  • 15 tests (tests/test_diff.py).

Baseline (v5.9.0)

Vishap supports fingerprint-based baseline to suppress known findings in CI.

First run - save baseline: vishap analyze src/ --save-baseline .vishap-baseline.json

Subsequent runs - report only new findings: vishap analyze src/ --baseline .vishap-baseline.json

In the report:

[BASELINE]
baseline_used: true
baseline_new: 0
baseline_known: 11

Baseline limitations

  • Fingerprint stability depends on LLM determinism. Risk nodes from Stage 2 are generated by an LLM (DeepSeek), which may rephrase name/note between runs. This is a fundamental limitation of baseline on LLM-generated findings.

  • Mitigation planned (P0-1b): constrain the Stage 2 prompt to emit a stable category / rule_id from a fixed taxonomy (idempotency, sharding, gdpr). Then fingerprints become filename | category | priority - stable.

  • Fingerprint components: filename | name | priority | note[:100], normalized (lowercase, whitespace collapsed). IDs are intentionally ignored.

  • Baseline file format: JSON, versioned (v1.0), git-friendly.

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).

  • ✅ Free to use, modify, and distribute
  • ✅ SaaS use allowed — but if you offer it as a network service, you must release your source code under AGPL
  • ❌ Cannot be taken closed-source

See LICENSE for full text.

Metadata

Release files for vishap-analyzer 5.9.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vishap-analyzer 5.9.8
File Size Uploaded
vishap_analyzer-5.9.8.tar.gz 131.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vishap-analyzer 5.9.8
File Interpreter ABI Platform
vishap_analyzer-5.9.8-py3-none-any.whl Python 3 none any Details

Total release size: 246.1 kB

Release files / vishap_analyzer-5.9.8.tar.gz

Download URL vishap_analyzer-5.9.8.tar.gz
Size 131.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ed15d9dcf83c61158a5ec7537068855d4a60e57ea57c371c9409b100b460936b
BLAKE2b-256 checksum
How to use checksums
fb635049e6478c0ac4c90c7bfa0c0ffd1dad90f79277788b34f858d9595e5b78
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release files / vishap_analyzer-5.9.8-py3-none-any.whl

Download URL vishap_analyzer-5.9.8-py3-none-any.whl
Size 114.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c558dababbdecc54149f54a680bbc3ced2614f5a34945a7df26902a27f6ddcb
BLAKE2b-256 checksum
How to use checksums
c9718824c8c4bf4bc5e4bf65607c0865b6f6fe20cba1e9df948d90be0a8b3045
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

5.9.8 This release

2 release files

5.8.3

2 release files

5.8.2

2 release files

5.8.1

2 release files

5.8.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page