suvoro 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- suvoro-0.1.0/.dockerignore +27 -0
- suvoro-0.1.0/.env.example +88 -0
- suvoro-0.1.0/.github/workflows/ci.yml +55 -0
- suvoro-0.1.0/.github/workflows/docker-publish.yml +69 -0
- suvoro-0.1.0/.github/workflows/multi-project-scan.yml +133 -0
- suvoro-0.1.0/.gitignore +99 -0
- suvoro-0.1.0/.suvoro/config.yaml +105 -0
- suvoro-0.1.0/.vibesec/logs/vibesec.log +47 -0
- suvoro-0.1.0/.vibesec/reports/latest_scan.md +952 -0
- suvoro-0.1.0/.vibesec/reports/scan_report_20260901_214217.md +952 -0
- suvoro-0.1.0/.vibesec/vibesec.db +0 -0
- suvoro-0.1.0/DOCKER.md +512 -0
- suvoro-0.1.0/Dockerfile +47 -0
- suvoro-0.1.0/LICENSE +20 -0
- suvoro-0.1.0/PKG-INFO +366 -0
- suvoro-0.1.0/PRD.md +1279 -0
- suvoro-0.1.0/README.md +320 -0
- suvoro-0.1.0/ROADMAP.md +310 -0
- suvoro-0.1.0/SECURITY.md +31 -0
- suvoro-0.1.0/USAGE.md +576 -0
- suvoro-0.1.0/docker-compose.yml +104 -0
- suvoro-0.1.0/pyproject.toml +101 -0
- suvoro-0.1.0/scripts/scan-all-in-parent.sh +120 -0
- suvoro-0.1.0/scripts/scan-multi-projects.sh +197 -0
- suvoro-0.1.0/scripts/setup-docker.sh +48 -0
- suvoro-0.1.0/src/suvoro/__init__.py +79 -0
- suvoro-0.1.0/src/suvoro/_meta.py +17 -0
- suvoro-0.1.0/src/suvoro/cli/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/cli/commands/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/cli/commands/audit.py +271 -0
- suvoro-0.1.0/src/suvoro/cli/commands/baseline.py +33 -0
- suvoro-0.1.0/src/suvoro/cli/commands/findings.py +98 -0
- suvoro-0.1.0/src/suvoro/cli/commands/fix.py +138 -0
- suvoro-0.1.0/src/suvoro/cli/commands/monitor.py +134 -0
- suvoro-0.1.0/src/suvoro/cli/commands/prove.py +55 -0
- suvoro-0.1.0/src/suvoro/cli/commands/report.py +43 -0
- suvoro-0.1.0/src/suvoro/cli/commands/suppress.py +76 -0
- suvoro-0.1.0/src/suvoro/cli/main.py +359 -0
- suvoro-0.1.0/src/suvoro/client.py +466 -0
- suvoro-0.1.0/src/suvoro/core/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/core/config.py +421 -0
- suvoro-0.1.0/src/suvoro/core/discovery.py +264 -0
- suvoro-0.1.0/src/suvoro/core/logging.py +131 -0
- suvoro-0.1.0/src/suvoro/core/paths.py +56 -0
- suvoro-0.1.0/src/suvoro/core/redact.py +170 -0
- suvoro-0.1.0/src/suvoro/core/schemas.py +376 -0
- suvoro-0.1.0/src/suvoro/events/__init__.py +28 -0
- suvoro-0.1.0/src/suvoro/events/types.py +148 -0
- suvoro-0.1.0/src/suvoro/findings/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/findings/baseline.py +54 -0
- suvoro-0.1.0/src/suvoro/findings/identity.py +123 -0
- suvoro-0.1.0/src/suvoro/findings/normalizer.py +113 -0
- suvoro-0.1.0/src/suvoro/findings/prioritizer.py +71 -0
- suvoro-0.1.0/src/suvoro/findings/suppression.py +89 -0
- suvoro-0.1.0/src/suvoro/models/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/models/budget.py +63 -0
- suvoro-0.1.0/src/suvoro/models/estimator.py +60 -0
- suvoro-0.1.0/src/suvoro/models/prompts.py +287 -0
- suvoro-0.1.0/src/suvoro/models/provider.py +158 -0
- suvoro-0.1.0/src/suvoro/models/triage.py +126 -0
- suvoro-0.1.0/src/suvoro/options.py +100 -0
- suvoro-0.1.0/src/suvoro/pipeline.py +420 -0
- suvoro-0.1.0/src/suvoro/qa/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/qa/agent.py +79 -0
- suvoro-0.1.0/src/suvoro/remediation/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/remediation/approval.py +54 -0
- suvoro-0.1.0/src/suvoro/remediation/patcher.py +85 -0
- suvoro-0.1.0/src/suvoro/remediation/safety.py +72 -0
- suvoro-0.1.0/src/suvoro/remediation/verifier.py +168 -0
- suvoro-0.1.0/src/suvoro/remediation/worktree.py +68 -0
- suvoro-0.1.0/src/suvoro/reports/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/reports/renderer.py +257 -0
- suvoro-0.1.0/src/suvoro/result.py +121 -0
- suvoro-0.1.0/src/suvoro/runtime/__init__.py +18 -0
- suvoro-0.1.0/src/suvoro/runtime/detector.py +329 -0
- suvoro-0.1.0/src/suvoro/runtime/ingest.py +398 -0
- suvoro-0.1.0/src/suvoro/runtime/middleware.py +173 -0
- suvoro-0.1.0/src/suvoro/runtime/monitor.py +266 -0
- suvoro-0.1.0/src/suvoro/runtime/responder.py +212 -0
- suvoro-0.1.0/src/suvoro/sandbox/__init__.py +3 -0
- suvoro-0.1.0/src/suvoro/sandbox/docker.py +245 -0
- suvoro-0.1.0/src/suvoro/sandbox/exploit_taxonomy.py +199 -0
- suvoro-0.1.0/src/suvoro/sandbox/mock.py +187 -0
- suvoro-0.1.0/src/suvoro/sandbox/prover.py +132 -0
- suvoro-0.1.0/src/suvoro/sandbox/provider.py +21 -0
- suvoro-0.1.0/src/suvoro/sandbox/redteam.py +286 -0
- suvoro-0.1.0/src/suvoro/scanners/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/scanners/bandit.py +100 -0
- suvoro-0.1.0/src/suvoro/scanners/base.py +92 -0
- suvoro-0.1.0/src/suvoro/scanners/checkov.py +117 -0
- suvoro-0.1.0/src/suvoro/scanners/gitleaks.py +132 -0
- suvoro-0.1.0/src/suvoro/scanners/installer.py +209 -0
- suvoro-0.1.0/src/suvoro/scanners/nuclei.py +92 -0
- suvoro-0.1.0/src/suvoro/scanners/osv.py +103 -0
- suvoro-0.1.0/src/suvoro/scanners/pins.json +145 -0
- suvoro-0.1.0/src/suvoro/scanners/registry.py +174 -0
- suvoro-0.1.0/src/suvoro/scanners/semgrep.py +113 -0
- suvoro-0.1.0/src/suvoro/scanners/syft.py +88 -0
- suvoro-0.1.0/src/suvoro/scanners/trivy.py +131 -0
- suvoro-0.1.0/src/suvoro/scanners/zap.py +126 -0
- suvoro-0.1.0/src/suvoro/storage/__init__.py +1 -0
- suvoro-0.1.0/src/suvoro/storage/ledger.py +557 -0
- suvoro-0.1.0/src/suvoro/storage/models.py +183 -0
- suvoro-0.1.0/tests/conftest.py +69 -0
- suvoro-0.1.0/tests/fakes.py +63 -0
- suvoro-0.1.0/tests/test_audit_cli.py +97 -0
- suvoro-0.1.0/tests/test_cli_commands.py +54 -0
- suvoro-0.1.0/tests/test_config.py +126 -0
- suvoro-0.1.0/tests/test_exclusions.py +40 -0
- suvoro-0.1.0/tests/test_fix_batch.py +19 -0
- suvoro-0.1.0/tests/test_fix_flow.py +101 -0
- suvoro-0.1.0/tests/test_identity.py +55 -0
- suvoro-0.1.0/tests/test_installer.py +111 -0
- suvoro-0.1.0/tests/test_ledger.py +63 -0
- suvoro-0.1.0/tests/test_middleware_safety.py +63 -0
- suvoro-0.1.0/tests/test_redact.py +50 -0
- suvoro-0.1.0/tests/test_redteam_prompts.py +90 -0
- suvoro-0.1.0/tests/test_renderer.py +40 -0
- suvoro-0.1.0/tests/test_runtime_detector.py +170 -0
- suvoro-0.1.0/tests/test_runtime_ingest.py +88 -0
- suvoro-0.1.0/tests/test_runtime_integration.py +68 -0
- suvoro-0.1.0/tests/test_runtime_middleware.py +75 -0
- suvoro-0.1.0/tests/test_runtime_responder.py +62 -0
- suvoro-0.1.0/tests/test_sandbox.py +86 -0
- suvoro-0.1.0/tests/test_sandbox_mock.py +50 -0
- suvoro-0.1.0/tests/test_scan_pipeline.py +102 -0
- suvoro-0.1.0/tests/test_scanner_parsers.py +38 -0
- suvoro-0.1.0/tests/test_sdk.py +324 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.git
|
|
2
|
+
.github
|
|
3
|
+
.vscode
|
|
4
|
+
.idea
|
|
5
|
+
|
|
6
|
+
.env
|
|
7
|
+
.env.*
|
|
8
|
+
.venv
|
|
9
|
+
env/
|
|
10
|
+
venv/
|
|
11
|
+
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.py[cod]
|
|
14
|
+
*.so
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
.suvoro/
|
|
22
|
+
# Keep pre-Suvoro local scan data out of Docker build contexts.
|
|
23
|
+
.provepatch/
|
|
24
|
+
tests/
|
|
25
|
+
|
|
26
|
+
PRD.md
|
|
27
|
+
USAGE.md
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Suvoro Model Provider API Keys & Endpoints (BYOK)
|
|
3
|
+
# ==============================================================================
|
|
4
|
+
# Copy this file to .env and fill in the keys for the providers you want to use.
|
|
5
|
+
# LiteLLM automatically picks up these environment variables.
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
|
|
8
|
+
# ==============================================================================
|
|
9
|
+
# FREE TIER PROVIDERS (Zero Cost / No Credit Card Required)
|
|
10
|
+
# ==============================================================================
|
|
11
|
+
|
|
12
|
+
# 1. Google AI Studio — Gemini 3.7 Flash & 3.5 Flash (15 RPM, 1.5M tokens/day)
|
|
13
|
+
# Get your free key at: https://aistudio.google.com → "Get API key"
|
|
14
|
+
GEMINI_API_KEY=AIzaSy...
|
|
15
|
+
|
|
16
|
+
# 2. Groq Cloud — Llama 3.3 70B & Llama 3.1 8B (30 RPM, 500 tok/s speed)
|
|
17
|
+
# Get your free key at: https://console.groq.com → "API Keys"
|
|
18
|
+
GROQ_API_KEY=gsk_...
|
|
19
|
+
|
|
20
|
+
# 3. DeepSeek Platform — DeepSeek V3 (deepseek-chat) & R1 (deepseek-reasoner)
|
|
21
|
+
# Get 5M free tokens on signup at: https://platform.deepseek.com → "API keys"
|
|
22
|
+
DEEPSEEK_API_KEY=sk-...
|
|
23
|
+
|
|
24
|
+
# 4. SiliconFlow (SiliconCloud) — Qwen3, DeepSeek R1 Distill (Free tier models)
|
|
25
|
+
# Get your free key at: https://cloud.siliconflow.com (or .cn) → "API Keys"
|
|
26
|
+
SILICONFLOW_API_KEY=sk-...
|
|
27
|
+
|
|
28
|
+
# 5. Z.ai (Zhipu AI) — GLM-5.3-Flash (New hybrid MoE flash model, free tier)
|
|
29
|
+
# Get your free key at: https://open.bigmodel.cn → API Keys
|
|
30
|
+
ZHIPUAI_API_KEY=...
|
|
31
|
+
|
|
32
|
+
# 6. OpenRouter — Access 300+ models, free auto-router (20 RPM, 50-1000 req/day)
|
|
33
|
+
# Get your free key at: https://openrouter.ai → "Keys" tab
|
|
34
|
+
OPENROUTER_API_KEY=sk-or-v1-...
|
|
35
|
+
|
|
36
|
+
# ==============================================================================
|
|
37
|
+
# PAID PROVIDERS (Credit Card Required)
|
|
38
|
+
# ==============================================================================
|
|
39
|
+
|
|
40
|
+
# OpenAI (GPT-4o, GPT-4o-mini, o1, o3-mini)
|
|
41
|
+
# OPENAI_API_KEY=sk-...
|
|
42
|
+
|
|
43
|
+
# Anthropic (Claude 3.5 Sonnet, Claude 3.5 Haiku)
|
|
44
|
+
# ANTHROPIC_API_KEY=sk-ant-...
|
|
45
|
+
|
|
46
|
+
# Mistral AI (Mistral Large, Codestral)
|
|
47
|
+
# MISTRAL_API_KEY=...
|
|
48
|
+
|
|
49
|
+
# HuggingFace Inference API
|
|
50
|
+
# HUGGINGFACE_API_KEY=hf_...
|
|
51
|
+
|
|
52
|
+
# NVIDIA NIM
|
|
53
|
+
# NVIDIA_NIM_API_KEY=nvapi-...
|
|
54
|
+
|
|
55
|
+
# Cohere
|
|
56
|
+
# COHERE_API_KEY=...
|
|
57
|
+
|
|
58
|
+
# Together AI
|
|
59
|
+
# TOGETHERAI_API_KEY=...
|
|
60
|
+
|
|
61
|
+
# ==============================================================================
|
|
62
|
+
# ENTERPRISE & CLOUD INFRASTRUCTURE
|
|
63
|
+
# ==============================================================================
|
|
64
|
+
|
|
65
|
+
# Azure OpenAI
|
|
66
|
+
# AZURE_API_KEY=...
|
|
67
|
+
# AZURE_API_BASE=https://your-resource-name.openai.azure.com/
|
|
68
|
+
# AZURE_API_VERSION=2024-02-01
|
|
69
|
+
|
|
70
|
+
# AWS Bedrock
|
|
71
|
+
# AWS_ACCESS_KEY_ID=...
|
|
72
|
+
# AWS_SECRET_ACCESS_KEY=...
|
|
73
|
+
# AWS_REGION_NAME=us-east-1
|
|
74
|
+
|
|
75
|
+
# ==============================================================================
|
|
76
|
+
# LOCAL & SELF-HOSTED MODELS (Ollama / vLLM / LM Studio)
|
|
77
|
+
# ==============================================================================
|
|
78
|
+
|
|
79
|
+
# Ollama (default: http://localhost:11434)
|
|
80
|
+
# OLLAMA_API_BASE=http://localhost:11434
|
|
81
|
+
|
|
82
|
+
# vLLM / LM Studio / Any OpenAI-compatible local server
|
|
83
|
+
# OPENAI_API_BASE=http://localhost:8000/v1
|
|
84
|
+
|
|
85
|
+
# ==============================================================================
|
|
86
|
+
# Model assignments per pipeline task (Triage, Patch, Red Team, QA, Detection)
|
|
87
|
+
# are configured in `.suvoro/config.yaml`.
|
|
88
|
+
# ==============================================================================
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- run: pip install "ruff>=0.5"
|
|
20
|
+
- run: ruff check src tests
|
|
21
|
+
|
|
22
|
+
test:
|
|
23
|
+
needs: lint
|
|
24
|
+
strategy:
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
os: [ubuntu-latest, macos-latest]
|
|
28
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
29
|
+
runs-on: ${{ matrix.os }}
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: ${{ matrix.python-version }}
|
|
35
|
+
cache: pip
|
|
36
|
+
- run: python -m pip install -e ".[dev]"
|
|
37
|
+
- run: python -m pytest -q --cov=suvoro --cov-report=term --cov-report=xml
|
|
38
|
+
- name: pip check (our install must not break dependencies)
|
|
39
|
+
run: python -m pip check
|
|
40
|
+
|
|
41
|
+
build:
|
|
42
|
+
needs: test
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- uses: actions/setup-python@v5
|
|
47
|
+
with:
|
|
48
|
+
python-version: "3.12"
|
|
49
|
+
- run: python -m pip install build twine
|
|
50
|
+
- run: python -m build
|
|
51
|
+
- run: python -m twine check dist/*
|
|
52
|
+
- uses: actions/upload-artifact@v4
|
|
53
|
+
with:
|
|
54
|
+
name: dist
|
|
55
|
+
path: dist/
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Build and Push Docker Image
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*.*.*'
|
|
9
|
+
pull_request:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
REGISTRY: ghcr.io
|
|
15
|
+
IMAGE_NAME: ${{ github.repository }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build-and-push:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
# Permissions required for pushing to GHCR
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
packages: write
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout repository
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Docker Buildx
|
|
31
|
+
uses: docker/setup-buildx-action@v3
|
|
32
|
+
|
|
33
|
+
- name: Log in to Container Registry
|
|
34
|
+
if: github.event_name != 'pull_request'
|
|
35
|
+
uses: docker/login-action@v3
|
|
36
|
+
with:
|
|
37
|
+
registry: ${{ env.REGISTRY }}
|
|
38
|
+
username: ${{ github.actor }}
|
|
39
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
40
|
+
|
|
41
|
+
- name: Extract metadata
|
|
42
|
+
id: meta
|
|
43
|
+
uses: docker/metadata-action@v5
|
|
44
|
+
with:
|
|
45
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
46
|
+
tags: |
|
|
47
|
+
type=ref,event=branch
|
|
48
|
+
type=semver,pattern={{version}}
|
|
49
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
50
|
+
type=semver,pattern={{major}}
|
|
51
|
+
type=sha,prefix={{branch}}-
|
|
52
|
+
type=raw,value=latest,enable={{is_default_branch}}
|
|
53
|
+
|
|
54
|
+
- name: Build and push Docker image
|
|
55
|
+
uses: docker/build-push-action@v5
|
|
56
|
+
with:
|
|
57
|
+
context: .
|
|
58
|
+
push: ${{ github.event_name != 'pull_request' }}
|
|
59
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
60
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
61
|
+
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
|
62
|
+
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
|
63
|
+
|
|
64
|
+
- name: Generate image digest
|
|
65
|
+
if: github.event_name != 'pull_request'
|
|
66
|
+
run: |
|
|
67
|
+
echo "Image pushed successfully:"
|
|
68
|
+
echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
|
|
69
|
+
echo "Digest: ${{ steps.build.outputs.digest }}"
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
name: Suvoro Security Scan (Example Multi-Project)
|
|
2
|
+
|
|
3
|
+
# This is an EXAMPLE workflow showing how to scan multiple repositories.
|
|
4
|
+
# Customize for your needs by adjusting the matrix projects list.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
# Scheduled daily scan (disabled by default for example workflow; uncomment to enable):
|
|
8
|
+
# schedule:
|
|
9
|
+
# - cron: '0 2 * * *'
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
projects:
|
|
13
|
+
description: 'Comma-separated list of project paths to scan'
|
|
14
|
+
required: false
|
|
15
|
+
default: 'src/'
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
scan:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
strategy:
|
|
22
|
+
# Scan multiple projects in parallel
|
|
23
|
+
matrix:
|
|
24
|
+
project:
|
|
25
|
+
- 'my-backend' # Replace with your project
|
|
26
|
+
- 'my-frontend' # Replace with your project
|
|
27
|
+
- 'my-infra' # Replace with your project
|
|
28
|
+
fail-fast: false # Continue scanning even if one project fails
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout Suvoro repository
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
with:
|
|
34
|
+
repository: iamvictorok/suvoro
|
|
35
|
+
path: suvoro
|
|
36
|
+
|
|
37
|
+
- name: Checkout project to scan
|
|
38
|
+
uses: actions/checkout@v4
|
|
39
|
+
with:
|
|
40
|
+
repository: ${{ github.repository }} # Your own repository
|
|
41
|
+
path: workspace/${{ matrix.project }}
|
|
42
|
+
|
|
43
|
+
- name: Build Suvoro Docker image
|
|
44
|
+
working-directory: suvoro
|
|
45
|
+
run: docker build -t suvoro:latest .
|
|
46
|
+
|
|
47
|
+
- name: Run Suvoro audit
|
|
48
|
+
working-directory: suvoro
|
|
49
|
+
run: |
|
|
50
|
+
docker run --rm \
|
|
51
|
+
-v "$(pwd)/../workspace/${{ matrix.project }}:/workspace:ro" \
|
|
52
|
+
-v suvoro-data:/home/suvoro/.local/share/suvoro \
|
|
53
|
+
suvoro:latest \
|
|
54
|
+
audit /workspace -f json > findings.json
|
|
55
|
+
|
|
56
|
+
- name: Generate markdown report
|
|
57
|
+
working-directory: suvoro
|
|
58
|
+
run: |
|
|
59
|
+
docker run --rm \
|
|
60
|
+
-v "$(pwd)/../workspace/${{ matrix.project }}:/workspace:ro" \
|
|
61
|
+
-v suvoro-data:/home/suvoro/.local/share/suvoro \
|
|
62
|
+
suvoro:latest \
|
|
63
|
+
report -f markdown -o report.md
|
|
64
|
+
|
|
65
|
+
- name: Upload results
|
|
66
|
+
uses: actions/upload-artifact@v4
|
|
67
|
+
if: always()
|
|
68
|
+
with:
|
|
69
|
+
name: ${{ matrix.project }}-findings
|
|
70
|
+
path: suvoro/findings.json
|
|
71
|
+
|
|
72
|
+
- name: Upload report
|
|
73
|
+
uses: actions/upload-artifact@v4
|
|
74
|
+
if: always()
|
|
75
|
+
with:
|
|
76
|
+
name: ${{ matrix.project }}-report
|
|
77
|
+
path: suvoro/report.md
|
|
78
|
+
|
|
79
|
+
- name: Comment PR with findings summary
|
|
80
|
+
if: github.event_name == 'pull_request'
|
|
81
|
+
uses: actions/github-script@v7
|
|
82
|
+
with:
|
|
83
|
+
script: |
|
|
84
|
+
const fs = require('fs');
|
|
85
|
+
const findings = JSON.parse(fs.readFileSync('suvoro/findings.json', 'utf8'));
|
|
86
|
+
const severities = {};
|
|
87
|
+
|
|
88
|
+
findings.findings?.forEach(f => {
|
|
89
|
+
severities[f.severity] = (severities[f.severity] || 0) + 1;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const summary = Object.entries(severities)
|
|
93
|
+
.map(([s, c]) => `${c} ${s}`)
|
|
94
|
+
.join(', ') || 'No findings';
|
|
95
|
+
|
|
96
|
+
github.rest.issues.createComment({
|
|
97
|
+
issue_number: context.issue.number,
|
|
98
|
+
owner: context.repo.owner,
|
|
99
|
+
repo: context.repo.repo,
|
|
100
|
+
body: `## Suvoro Security Scan - ${{ matrix.project }}\n\n${summary}`
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
- name: Fail on critical findings
|
|
104
|
+
run: |
|
|
105
|
+
critical=$(jq '[.findings[] | select(.severity == "CRITICAL")] | length' suvoro/findings.json)
|
|
106
|
+
if [ "$critical" -gt 0 ]; then
|
|
107
|
+
echo "Found $critical critical issues!"
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
summary:
|
|
112
|
+
runs-on: ubuntu-latest
|
|
113
|
+
needs: scan
|
|
114
|
+
if: always()
|
|
115
|
+
|
|
116
|
+
steps:
|
|
117
|
+
- name: Download all artifacts
|
|
118
|
+
uses: actions/download-artifact@v4
|
|
119
|
+
|
|
120
|
+
- name: Generate summary
|
|
121
|
+
run: |
|
|
122
|
+
echo "# Security Scan Summary" > summary.md
|
|
123
|
+
echo "" >> summary.md
|
|
124
|
+
|
|
125
|
+
for findings in *-findings/findings.json; do
|
|
126
|
+
[ -f "$findings" ] || continue
|
|
127
|
+
project=$(basename "$(dirname "$findings")" | sed 's/-findings//')
|
|
128
|
+
total=$(jq '.findings | length' "$findings" 2>/dev/null || echo 0)
|
|
129
|
+
echo "- **$project**: $total findings" >> summary.md
|
|
130
|
+
done
|
|
131
|
+
|
|
132
|
+
- name: Display summary
|
|
133
|
+
run: cat summary.md
|
suvoro-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Environments
|
|
55
|
+
.env
|
|
56
|
+
.venv
|
|
57
|
+
env/
|
|
58
|
+
venv/
|
|
59
|
+
ENV/
|
|
60
|
+
env.bak/
|
|
61
|
+
venv.bak/
|
|
62
|
+
|
|
63
|
+
# suvoro runtime, ledger, and log outputs
|
|
64
|
+
.suvoro/*
|
|
65
|
+
!.suvoro/config.yaml
|
|
66
|
+
!.suvoro/config.yml
|
|
67
|
+
.suvoro/logs/
|
|
68
|
+
.suvoro/reports/
|
|
69
|
+
.suvoro/scanners/
|
|
70
|
+
.suvoro/worktrees/
|
|
71
|
+
.suvoro/suvoro.db*
|
|
72
|
+
# Preserve and ignore local data from the previous state directory.
|
|
73
|
+
.provepatch/
|
|
74
|
+
/reports/
|
|
75
|
+
|
|
76
|
+
# suvoro generated reports and scan artifacts
|
|
77
|
+
suvoro-report.*
|
|
78
|
+
report.json
|
|
79
|
+
report.md
|
|
80
|
+
report.sarif
|
|
81
|
+
results.json
|
|
82
|
+
results.md
|
|
83
|
+
results.sarif
|
|
84
|
+
audit-report*
|
|
85
|
+
audit_report*
|
|
86
|
+
zap-report*
|
|
87
|
+
nuclei-report*
|
|
88
|
+
rawscan*
|
|
89
|
+
*.sarif
|
|
90
|
+
*.patch
|
|
91
|
+
.suvoro_fix.patch
|
|
92
|
+
|
|
93
|
+
# IDEs / Editors
|
|
94
|
+
.vscode/
|
|
95
|
+
.idea/
|
|
96
|
+
*.swp
|
|
97
|
+
*.swo
|
|
98
|
+
*~
|
|
99
|
+
.DS_Store
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
project_root: "."
|
|
2
|
+
|
|
3
|
+
scanners:
|
|
4
|
+
semgrep: true
|
|
5
|
+
bandit: true
|
|
6
|
+
checkov: true
|
|
7
|
+
osv: true
|
|
8
|
+
gitleaks: true
|
|
9
|
+
syft: true
|
|
10
|
+
trivy: false
|
|
11
|
+
nuclei: false
|
|
12
|
+
zap: false
|
|
13
|
+
|
|
14
|
+
vulndb:
|
|
15
|
+
mode: online
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Multi-Provider Free LLM Configuration (Zero-Cost E2E)
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Provider 1: Google AI Studio → GEMINI_API_KEY (free, no card)
|
|
21
|
+
# Provider 2: Groq Cloud → GROQ_API_KEY (free, no card)
|
|
22
|
+
# Provider 3: DeepSeek Platform → DEEPSEEK_API_KEY (free 5M tokens)
|
|
23
|
+
# Provider 4: SiliconFlow → SILICONFLOW_API_KEY (free credits + free models)
|
|
24
|
+
# Provider 5: Z.ai (Zhipu AI) → ZHIPUAI_API_KEY (free Flash models, no card)
|
|
25
|
+
# Provider 6: OpenRouter → OPENROUTER_API_KEY (free rotating models)
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
#
|
|
28
|
+
# Load distribution (5 providers, 7 roles):
|
|
29
|
+
# Groq → 2 roles (triage, detection) — speed-critical real-time tasks
|
|
30
|
+
# DeepSeek → 1 role (remediation) — top-tier code diffs (V3)
|
|
31
|
+
# SiliconFlow→ 1 role (red team reviewer) — free Qwen3-8B, fast inference
|
|
32
|
+
# Z.ai → 1 role (qa) — free GLM-4.5-Flash
|
|
33
|
+
# Gemini → 1 role (prover) — multi-step bash/Python exploit gen
|
|
34
|
+
# DeepSeek → 1 role (red team planner) — R1 chain-of-thought reasoning
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
models:
|
|
37
|
+
# 1. Triage: Classify & explain scanner findings in plain English.
|
|
38
|
+
# Groq Llama 3.3 70B — 30 RPM free, blazing inference (~500 tok/s).
|
|
39
|
+
triage:
|
|
40
|
+
provider: groq
|
|
41
|
+
model: llama-3.3-70b-versatile
|
|
42
|
+
|
|
43
|
+
# 2. Remediation: Generate verified unified diffs & regression tests.
|
|
44
|
+
# DeepSeek V3 (deepseek-chat) — exceptional code intelligence, 5M free tokens.
|
|
45
|
+
remediation:
|
|
46
|
+
provider: deepseek
|
|
47
|
+
model: deepseek-chat
|
|
48
|
+
|
|
49
|
+
# 3. Sandbox Prover: Write bash exploit validation scripts.
|
|
50
|
+
# Gemini 3.7 Flash — strong multi-step bash/Python, 1M context window.
|
|
51
|
+
prover:
|
|
52
|
+
provider: gemini
|
|
53
|
+
model: gemini-3.7-flash
|
|
54
|
+
|
|
55
|
+
# 4. Multi-Agent Red Team:
|
|
56
|
+
redteam:
|
|
57
|
+
planner:
|
|
58
|
+
# DeepSeek R1 — purpose-built chain-of-thought reasoning for adversarial
|
|
59
|
+
# exploit planning. Arguably the strongest free reasoning model available.
|
|
60
|
+
provider: deepseek
|
|
61
|
+
model: deepseek-reasoner
|
|
62
|
+
reviewer:
|
|
63
|
+
# SiliconFlow Qwen3-8B — free tier, fast tactical telemetry extraction.
|
|
64
|
+
# Uses OpenAI-compatible endpoint at https://api.siliconflow.com/v1
|
|
65
|
+
provider: openai
|
|
66
|
+
model: Qwen/Qwen3-8B
|
|
67
|
+
api_key: ${SILICONFLOW_API_KEY}
|
|
68
|
+
api_base: https://api.siliconflow.com/v1
|
|
69
|
+
max_iterations: 3
|
|
70
|
+
|
|
71
|
+
# 5. Senior QA Code Vetter: Static code quality review.
|
|
72
|
+
# Z.ai GLM-5.3-Flash — brand new native multimodal MoE (320B/18B active).
|
|
73
|
+
# Uses OpenAI-compatible endpoint at https://open.bigmodel.cn/api/paas/v4
|
|
74
|
+
qa:
|
|
75
|
+
provider: openai
|
|
76
|
+
model: GLM-5.3-Flash
|
|
77
|
+
api_key: ${ZHIPUAI_API_KEY}
|
|
78
|
+
api_base: https://open.bigmodel.cn/api/paas/v4
|
|
79
|
+
|
|
80
|
+
# 6. Runtime Live Attack Detection (Phase 3): Stage 2 AI classifier.
|
|
81
|
+
# Groq Llama 3.1 8B — sub-second response for real-time log telemetry.
|
|
82
|
+
detection:
|
|
83
|
+
provider: groq
|
|
84
|
+
model: llama-3.1-8b-instant
|
|
85
|
+
|
|
86
|
+
# Budget protection — stops spending tokens if limits are hit.
|
|
87
|
+
budgets:
|
|
88
|
+
max_calls_per_scan: 50
|
|
89
|
+
max_tokens_per_scan: 250000
|
|
90
|
+
on_budget_exceeded: stop_and_report
|
|
91
|
+
|
|
92
|
+
storage:
|
|
93
|
+
backend: sqlite
|
|
94
|
+
sqlite_path: .suvoro/suvoro.db
|
|
95
|
+
|
|
96
|
+
data_policy:
|
|
97
|
+
raw_logs: network_allowed
|
|
98
|
+
secrets: never_send
|
|
99
|
+
|
|
100
|
+
runtime:
|
|
101
|
+
enabled: true
|
|
102
|
+
log_format: auto
|
|
103
|
+
severity_threshold: medium
|
|
104
|
+
|
|
105
|
+
auto_install_scanners: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{"timestamp": "2026-09-01T21:25:36.884076+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting vibesec scan on ."}
|
|
2
|
+
{"timestamp": "2026-09-01T21:25:36.885979+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting full scan pipeline..."}
|
|
3
|
+
{"timestamp": "2026-09-01T21:25:36.900670+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting project discovery..."}
|
|
4
|
+
{"timestamp": "2026-09-01T21:25:36.911903+00:00", "level": "INFO", "name": "vibesec.discovery", "message": "Discovered project profile: {'languages': ['python'], 'package_managers': ['pip'], 'test_frameworks': ['pytest'], 'env_files': ['.env', '.env.example'], 'databases': ['postgresql', 'sqlite']}"}
|
|
5
|
+
{"timestamp": "2026-09-01T21:25:36.912860+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished project discovery in 0.01s"}
|
|
6
|
+
{"timestamp": "2026-09-01T21:25:36.913656+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting scanning phase..."}
|
|
7
|
+
{"timestamp": "2026-09-01T21:25:36.914676+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'semgrep' not found. Attempting auto-install..."}
|
|
8
|
+
{"timestamp": "2026-09-01T21:25:36.915260+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Installing semgrep via pip..."}
|
|
9
|
+
{"timestamp": "2026-09-01T21:28:01.159840+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Semgrep installed successfully."}
|
|
10
|
+
{"timestamp": "2026-09-01T21:28:01.161947+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'osv-scanner' not found. Attempting auto-install..."}
|
|
11
|
+
{"timestamp": "2026-09-01T21:28:01.162661+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Fetching release v2.5.1 from google/osv-scanner"}
|
|
12
|
+
{"timestamp": "2026-09-01T21:28:02.160491+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Downloading https://github.com/google/osv-scanner/releases/download/v2.5.1/osv-scanner_darwin_arm64"}
|
|
13
|
+
{"timestamp": "2026-09-01T21:36:12.922072+00:00", "level": "INFO", "name": "vibesec.installer", "message": "osv-scanner installed to /Library/Frameworks/Python.framework/Versions/3.13/bin/osv-scanner"}
|
|
14
|
+
{"timestamp": "2026-09-01T21:36:12.926995+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'gitleaks' not found. Attempting auto-install..."}
|
|
15
|
+
{"timestamp": "2026-09-01T21:36:12.927810+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Fetching release v8.30.1 from gitleaks/gitleaks"}
|
|
16
|
+
{"timestamp": "2026-09-01T21:36:13.726566+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Downloading https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_darwin_arm64.tar.gz"}
|
|
17
|
+
{"timestamp": "2026-09-01T21:36:59.168851+00:00", "level": "INFO", "name": "vibesec.installer", "message": "gitleaks installed to /Library/Frameworks/Python.framework/Versions/3.13/bin/gitleaks"}
|
|
18
|
+
{"timestamp": "2026-09-01T21:36:59.171892+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'bandit' not found. Attempting auto-install..."}
|
|
19
|
+
{"timestamp": "2026-09-01T21:36:59.172531+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Installing bandit via pip..."}
|
|
20
|
+
{"timestamp": "2026-09-01T21:37:02.864494+00:00", "level": "INFO", "name": "vibesec.installer", "message": "bandit installed successfully."}
|
|
21
|
+
{"timestamp": "2026-09-01T21:37:02.866708+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'checkov' not found. Attempting auto-install..."}
|
|
22
|
+
{"timestamp": "2026-09-01T21:37:02.867353+00:00", "level": "INFO", "name": "vibesec.installer", "message": "Installing checkov via pip..."}
|
|
23
|
+
{"timestamp": "2026-09-01T21:42:02.887012+00:00", "level": "ERROR", "name": "vibesec.installer", "message": "Failed to install checkov: Command '['/Library/Frameworks/Python.framework/Versions/3.13/bin/python3', '-m', 'pip', 'install', 'checkov', '--quiet']' timed out after 300 seconds"}
|
|
24
|
+
{"timestamp": "2026-09-01T21:42:02.891174+00:00", "level": "ERROR", "name": "vibesec.scanners", "message": "Auto-install failed for 'checkov'. Skipping."}
|
|
25
|
+
{"timestamp": "2026-09-01T21:42:02.892025+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Starting all parallel scanners..."}
|
|
26
|
+
{"timestamp": "2026-09-01T21:42:03.679746+00:00", "level": "ERROR", "name": "vibesec.osv", "message": "OSV-Scanner failed (exit 128): Scanning dir .\nStarting filesystem walk for root: /\nEnd status: 6 dirs visited, 13 inodes visited, 0 Extract calls, 245.75\u00b5s elapsed, 245\u00b5s wall time\nNo package sources found, --help for usage information.\n"}
|
|
27
|
+
{"timestamp": "2026-09-01T21:42:03.681812+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'osv-scanner' completed in 0.8s with 0 finding(s)."}
|
|
28
|
+
{"timestamp": "2026-09-01T21:42:03.747495+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'gitleaks' completed in 0.9s with 5 finding(s)."}
|
|
29
|
+
{"timestamp": "2026-09-01T21:42:03.861112+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'bandit' completed in 1.0s with 158 finding(s)."}
|
|
30
|
+
{"timestamp": "2026-09-01T21:42:06.231207+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'syft' completed in 3.3s with 0 finding(s)."}
|
|
31
|
+
{"timestamp": "2026-09-01T21:42:13.343903+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Scanner 'semgrep' completed in 10.4s with 2 finding(s)."}
|
|
32
|
+
{"timestamp": "2026-09-01T21:42:13.344773+00:00", "level": "INFO", "name": "vibesec.scanners", "message": "Finished all parallel scanners in 10.45s"}
|
|
33
|
+
{"timestamp": "2026-09-01T21:42:13.345538+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished scanning phase in 996.31s"}
|
|
34
|
+
{"timestamp": "2026-09-01T21:42:13.346625+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting normalization phase..."}
|
|
35
|
+
{"timestamp": "2026-09-01T21:42:13.348626+00:00", "level": "INFO", "name": "vibesec.normalizer", "message": "Filtered out 5 findings located in excluded environment/build directories."}
|
|
36
|
+
{"timestamp": "2026-09-01T21:42:13.349119+00:00", "level": "INFO", "name": "vibesec.normalizer", "message": "Normalizing 160 raw findings..."}
|
|
37
|
+
{"timestamp": "2026-09-01T21:42:13.349746+00:00", "level": "INFO", "name": "vibesec.normalizer", "message": "Normalization complete. Reduced to 118 unique findings."}
|
|
38
|
+
{"timestamp": "2026-09-01T21:42:13.350149+00:00", "level": "INFO", "name": "vibesec.prioritizer", "message": "Prioritizing 118 findings..."}
|
|
39
|
+
{"timestamp": "2026-09-01T21:42:13.351096+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Normalization complete: 118 findings remaining"}
|
|
40
|
+
{"timestamp": "2026-09-01T21:42:13.351415+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished normalization phase in 0.00s"}
|
|
41
|
+
{"timestamp": "2026-09-01T21:42:13.352027+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting triage phase..."}
|
|
42
|
+
{"timestamp": "2026-09-01T21:42:17.948023+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Estimation complete: {'calls': 39, 'tokens': 22581, 'status': 'within_budget', 'max_calls': 50, 'max_tokens': 200000}"}
|
|
43
|
+
{"timestamp": "2026-09-01T21:42:17.949324+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished triage phase in 4.60s"}
|
|
44
|
+
{"timestamp": "2026-09-01T21:42:17.950750+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Starting report phase..."}
|
|
45
|
+
{"timestamp": "2026-09-01T21:42:17.996426+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Scan pipeline finished with 118 findings."}
|
|
46
|
+
{"timestamp": "2026-09-01T21:42:17.996931+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished report phase in 0.05s"}
|
|
47
|
+
{"timestamp": "2026-09-01T21:42:17.997538+00:00", "level": "INFO", "name": "vibesec.pipeline", "message": "Finished full scan pipeline in 1000.99s"}
|