Skip to content

Hasooo1/PT-Hub

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PT-Hub

A full-stack vulnerability management application for penetration testers to manage clients, projects, findings, and generate reviewable assessment reports with a hard no-review → no-export gate and true WYSIWYG PDF export.


Tech stack

Layer Technology
Backend FastAPI · SQLAlchemy 2.0 · Pydantic v2
Database SQLite (local dev) — PostgreSQL-ready via DATABASE_URL
Auth JWT (PyJWT) + bcrypt, role-aware (Tester / Reviewer)
PDF Playwright (Chromium) — renders the same HTML as the browser preview
Frontend React + TypeScript · Vite · Tailwind CSS · React Router
Charts Recharts (dashboard) + server-rendered SVG (report)

How WYSIWYG parity is guaranteed

The backend renders one canonical report HTML from a Jinja2 template (backend/app/templates/report.html). The frontend preview embeds that exact HTML in an iframe, and PDF export runs Playwright/Chromium over the same HTML. Same bytes through the same rendering engine → the preview and the PDF are identical. Evidence images are inlined as base64 data URIs and the severity chart is server-rendered SVG, so the report is fully self-contained.


Prerequisites

  • Python 3.11+ (developed on 3.13)
  • Node.js 18+ (developed on 22)

Backend — setup & run

cd backend

# 1. Create a virtual environment
python -m venv .venv
# Windows PowerShell:  .venv\Scripts\Activate.ps1
# macOS/Linux:         source .venv/bin/activate

# 2. Install dependencies
pip install -r requirements.txt

# 3. Install the Chromium browser used for PDF export (one-time, ~download)
python -m playwright install chromium

# 4. (optional) configure environment
cp .env.example .env          # defaults work out of the box for local dev

# 5. Seed demo data (users + a sample engagement with two versions)
python seed.py

# 6. Run the API  ->  http://localhost:8000   (docs at /docs)
python -m uvicorn app.main:app --reload --port 8000

If you skip playwright install chromium, the app still runs and previews work; only PDF export returns a 503 with a clear message until Chromium is installed.

Frontend — setup & run

cd frontend
npm install
npm run dev          # -> http://localhost:5173

The frontend talks to http://localhost:8000 by default. To point elsewhere, set VITE_API_URL in frontend/.env.


Demo accounts

Role Email Password
Tester tester@pthub.io Passw0rd!
Reviewer reviewer@pthub.io Passw0rd!

The seed creates client Acme Financial → project Acme Online Banking with:

  • v1.0Approved (export unlocked, PDF downloadable)
  • v2.0Pending Review (export locked) and a meaningful diff vs v1.0 (1 New, 1 Regressed, 2 Still Open, 2 Resolved).

The review workflow (the critical feature)

  1. A Tester adds findings to a project version and clicks Mark Ready for Review. The version enters Pending Review and export buttons lock.
  2. A Reviewer opens the version, adds per-finding comments, writes an overall verdict, and clicks Approve or Request Changes.
  3. Only after Approved does the report unlock for export.

The gate is enforced in both places:

  • Frontend — the Export button is disabled and visibly locked (🔒) unless can_export.
  • BackendGET /versions/{id}/report/export.pdf returns 403 unless the version is Approved.

Safety properties enforced server-side:

  • A reviewer cannot approve a version they authored (author_id != reviewer_id).
  • Roles are distinct: only Testers create/edit data; only Reviewers post review comments and verdicts.

Key screens

  • Dashboard — client/project/version counts, open findings by severity (Recharts), reports pending review.
  • ClientsClient detail (their projects).
  • Project detail — version timeline + version-diff view (New / Resolved / Still Open / Regressed).
  • Version detail — findings table (filter/sort by severity & status) + review panel.
  • Finding editor — standardized layout (Severity beside title, Category, Description, Implications, Remediation, References) with URL validation, CVSS/CWE/OWASP, evidence text + image upload, and the per-finding review-comment thread.
  • Report builder — editable metadata tables (Document Approval, Version Control, Review) then the review gate.
  • Report preview — WYSIWYG iframe with the export button locked until approved.

Project structure

PT-Hub/
├─ backend/
│  ├─ app/
│  │  ├─ main.py            # FastAPI app, CORS, router mounts, static uploads
│  │  ├─ config.py          # pydantic-settings (env)
│  │  ├─ database.py        # engine + session
│  │  ├─ models.py          # SQLAlchemy models
│  │  ├─ schemas.py         # Pydantic schemas (URL + CVSS validation)
│  │  ├─ enums.py           # shared enums
│  │  ├─ security.py        # bcrypt + JWT
│  │  ├─ deps.py            # auth dependencies / role guards
│  │  ├─ serializers.py     # ORM -> response (computed fields)
│  │  ├─ api/               # routers: auth, clients, projects, versions,
│  │  │                     #          findings, reports, dashboard
│  │  ├─ services/          # diff engine, report_render (Jinja2+SVG), pdf (Playwright)
│  │  └─ templates/report.html
│  ├─ seed.py
│  └─ requirements.txt
└─ frontend/
   └─ src/
      ├─ api/               # client.ts, index.ts (typed), types.ts (mirror schemas)
      ├─ auth/AuthContext.tsx
      ├─ components/        # badges, layout, modal, finding editor
      ├─ lib/               # severity palette + constants
      └─ pages/             # Login, Dashboard, Clients, ClientDetail,
                            # ProjectDetail, VersionDetail, ReportBuilder, ReportPreview

API quick reference

All routes are under /api. Highlights:

Method Path Notes
POST /auth/login returns JWT + user
GET /dashboard aggregate stats
GET/POST /clients, /projects, … CRUD (writes require Tester)
POST /projects/{id}/versions optional clone_from_version_id for re-tests
GET /versions/{id}/diff diff vs previous (or ?base_version_id=)
POST /versions/{id}/ready-for-review Tester submits
POST /versions/{id}/review Reviewer Approve / Request Changes
POST /findings/{id}/comments per-finding review comment (Reviewer)
POST /findings/{id}/evidence evidence image upload
GET /versions/{id}/report/preview canonical HTML (iframe)
GET /versions/{id}/report/export.pdf 403 unless Approved

Interactive docs: http://localhost:8000/docs


Notes / production considerations

  • Database: set DATABASE_URL to a PostgreSQL URL (postgresql+psycopg://…) and add psycopg[binary] to use Postgres. Tables are auto-created on startup for dev; use Alembic migrations for production.
  • Secrets: change SECRET_KEY outside local dev.
  • Report content (descriptions, evidence) is auto-escaped in the Jinja2 template to prevent injection into the rendered report/PDF.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors