Skip to content

Repository files navigation

LinView

Web dashboard to receive and display LinSpec kernel hardening scan reports.

Platform-Linux Language-Python Framework-Flask License-MIT Status CI Tested-on Domain

Etymology

LinView = LinSpec + View.

A web dashboard purpose-built to receive, store, and display LinSpec kernel hardening scan reports — extending LinSpec from a CLI tool into a centralized security visibility layer.

Overview

Collects scan reports via REST API, stores them in SQLite, and displays aggregate statistics and per-scan details. Natively compatible with LinSpec JSON output via --webhook.

Quick Start

pip install -r requirements.txt
python app.py

Open http://localhost:5000

Project in Action

LinView Dashboard

LinView dashboard showing aggregate hardening statistics and per-scan details.

Generate an API key

Set the LINVIEW_ADMIN_PASSWORD environment variable, then visit /admin/setup and authenticate to create the first API key for submitting scans.

API

Submit a scan report

Accepts both LinSpec-native format (lowercase result) and legacy format (uppercase status). Examples:

# LinSpec-native format (from --webhook)
curl -X POST http://localhost:5000/api/scan \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <your-key>" \
  -d '{
    "hostname": "server01",
    "kernel": "6.8.0",
    "os": "Linux",
    "checks": [
      {"id": 1, "name": "aslr", "result": "pass", "category": "memory",
       "current": 2, "expected": 2, "message": ""},
      {"id": 2, "name": "kptr_restrict", "result": "vuln", "category": "kernel",
       "current": 0, "expected": 2, "message": "kptr_restrict=0"}
    ]
  }'

# Legacy format
curl -X POST http://localhost:5000/api/scan \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <your-key>" \
  -d '{
    "hostname": "server01",
    "checks": [
      {"check": "aslr", "category": "memory", "status": "PASS", "message": ""},
      {"check": "kptr_restrict", "category": "kernel", "status": "VULN", "message": "bad"}
    ]
  }'

View a raw scan

GET /api/scan/<id>/raw

Environment Variables

Variable Default Description
PORT 5000 HTTP port
SECRET_KEY auto Flask session secret
LINVIEW_DB data.db SQLite database path
LINVIEW_DEBUG false Enable Flask debug mode
LINVIEW_RATE_LIMIT 60 Max requests per minute per IP
LINVIEW_ADMIN_PASSWORD empty Password required to generate API keys at /admin/setup
LINVIEW_ALLOWED_ORIGINS empty Comma-separated list of allowed CORS origins (empty = CORS disabled)

Security Notes

  • API key is read from the X-API-Key header only (query string ?key= not accepted)
  • CORS is disabled by default; enable only specific origins via LINVIEW_ALLOWED_ORIGINS
  • /admin/setup is protected by LINVIEW_ADMIN_PASSWORD — never expose it without one
  • CSRF tokens are required for all state-changing form submissions
  • Security headers (CSP, X-Frame-Options, X-Content-Type-Options, etc.) are applied to every response
  • Rate limiting is in-memory per-worker (not shared across gunicorn workers)
  • Always use a reverse proxy (nginx/caddy) for TLS termination

Docs-Security

Production

Use the bundled start.sh with gunicorn:

./start.sh

Never run with LINVIEW_DEBUG=true in production.

Tests

pip install pytest
python -m pytest tests/

Documentation

Docs-Architecture Docs-Usage Docs-Deployment

About

🐧 Web dashboard for LinSpec kernel hardening scan reports.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages