Security Report Transformer: JSON β JSON, SARIF, PDF
ReportGen is a stateless microservice that takes security findings in JSON format and transforms them into standardized JSON, SARIF, and PDF reports. It aggregates results from multiple analysis services and generates comprehensive security reports for easy consumption by both humans and machines.
- Overview
- Architecture
- Features
- Installation
- Usage
- API Reference
- Report Formats
- Docker Deployment
- Integration Guide
- Configuration
- Development
ReportGen is a transformation engine for security reports. It takes raw scanner results in JSON format and converts them into standardized, high-quality reports in JSON, SARIF, and PDF formats. It acts as the final aggregation and rendering layer in a security analysis pipeline.
- Multi-Service Aggregation: Merge findings from unlimited scanner services
- Intelligent Deduplication: Remove duplicate findings based on content fingerprinting
- Risk Scoring: Weighted risk calculation (0-100 scale)
- CWE Enrichment: Automatic mapping to Common Weakness Enumeration
- OWASP MASVS Mapping: Mobile Application Security Verification Standard alignment
- Multi-Format Output:
- JSON: Full structured data
- SARIF 2.1.0: GitHub Code Scanning compatible
- PDF: Executive-ready reports
Input findings from different scanners are normalized to a standard schema:
{
"id": "uuid",
"service": "CryptoCheck",
"category": "crypto",
"severity": "high",
"confidence": "high",
"cwe": "CWE-327",
"owasp_masvs": "MSTG-CRYPTO-2",
"title": "Use of Broken Cryptographic Algorithm",
"description": "AES ECB mode detected in CryptoUtils.java",
"file": "src/crypto/CryptoUtils.java",
"line_number": 42,
"recommendation": "Use AES/GCM with random IV",
"risk_score": 8.5
}- Node.js >= 18.0.0
- npm or yarn
# Clone repository
git clone https://github.com/houssamb4/reportgen.git
cd reportgen
# Install dependencies
npm install
# Copy environment configuration
cp .env.example .env
# Start development server
npm run devnpm ci --only=production
npm start# Start the service
npm start
# Service will be available at http://localhost:8005Check Service Health:
# PowerShell
Invoke-RestMethod -Uri "http://localhost:8005/health"
# curl
curl http://localhost:8005/healthReportGen transforms your scanner JSON results into multiple formats. You can send a POST request to the /api/v1/generate-report endpoint with your findings.
Example Request (PowerShell):
$body = @{
scan_id = [guid]::NewGuid().ToString()
app = @{
package_name = "com.example.app"
version = "1.0.0"
}
inputs = @(
@{
service = "NetworkInspector"
findings = @(
@{
id = "NET-001"
severity = "high"
issue = "Insecure Connection"
cwe_id = "CWE-319"
}
)
}
)
output_formats = @("json", "sarif", "pdf")
} | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "http://localhost:8005/api/v1/generate-report" -Method Post -ContentType "application/json" -Body $bodyReportGen only aggregates and renders already-produced results. Provide a scan bundle that contains the app metadata and every service's result file.
Using curl (Linux/macOS):
curl -X POST http://localhost:8005/api/v1/generate-report \
-H "Content-Type: application/json" \
-d '{
"scan_id": "5d4a3c35-5781-4dd8-9129-158f20f13f56",
"app": {
"platform": "android",
"package_name": "com.example.app",
"version": "1.0.0"
},
"inputs": [
{
"source_file": "network_results.json",
"service": "NetworkInspector",
"service_version": "1.0.0",
"findings": [
{
"id": "NET-001",
"category": "TLS",
"severity": "critical",
"cwe_id": "CWE-319",
"issue": "Cleartext Transmission of Sensitive Information",
"endpoint": "http://connectivitycheck.gstatic.com/generate_204",
"recommendation": "Use HTTPS for all communications",
"confidence": 0.95,
"timestamp": 1765822761.766333
}
]
},
{
"source_file": "secrets.json",
"service": "SecretHunter",
"findings": [
{
"id": "SEC-001",
"severity": "high",
"issue": "API Key exposed",
"cwe_id": "CWE-522",
"file": "strings.xml",
"confidence": 0.87
}
]
}
],
"output_formats": ["json", "sarif", "pdf"]
}'Using PowerShell (Windows):
# Using the provided test file
$body = Get-Content test-request.json -Raw
Invoke-RestMethod -Uri "http://localhost:8005/api/v1/generate-report" `
-Method Post `
-ContentType "application/json" `
-Body $body
β οΈ Important:scan_idmust be a valid UUID/GUID format (e.g.,550e8400-e29b-41d4-a716-446655440000). Generate using:
- Node.js:
import { v4 as uuidv4 } from 'uuid'; uuidv4()- PowerShell:
[guid]::NewGuid().ToString()- Online: https://www.uuidgenerator.net/
{
"success": true,
"metadata": {
"version": "1.0.0",
"generator": "ReportGen Microservice",
"generation_duration_ms": 1247
},
"summary": {
"total_findings": 1,
"risk_score": 78,
"risk_level": "high",
"severity_distribution": {
"critical": 0,
"high": 1,
"medium": 0,
"low": 0,
"info": 0
}
},
"reports": {
"json": "...",
"sarif": "...",
"pdf_base64": "JVBERi0xLj..."
}
}Health check endpoint
Response:
{
"status": "healthy",
"service": "reportgen",
"version": "1.0.0"
}Service information and capabilities
Response:
{
"service": "ReportGen",
"version": "1.0.0",
"capabilities": {
"input_formats": ["JSON scan results"],
"output_formats": ["JSON", "SARIF", "PDF"],
"features": [
"Multi-service aggregation",
"Finding deduplication",
"Risk scoring"
]
}
}Generate reports in multiple formats
Request Body (preferred bundle format):
{
"scan_id": "5d4a3c35-5781-4dd8-9129-158f20f13f56",
"app": {
"platform": "android",
"package_name": "com.example.app",
"version": "1.0.0"
},
"inputs": [
{
"source_file": "apk_scanner.json",
"service": "APKScanner",
"service_version": "1.0.0",
"findings": [{ "id": "APK-001", "severity": "high", "issue": "Application is debuggable", "cwe_id": "CWE-489" }]
},
{
"source_file": "network.json",
"service": "NetworkInspector",
"findings": [{ "id": "NET-001", "severity": "critical", "issue": "Cleartext HTTP traffic", "cwe_id": "CWE-319" }]
}
],
"output_formats": ["json", "sarif", "pdf"]
}Legacy support: The previous
scan_inputsarray is still accepted for backward compatibility, but new integrations should adopt the bundle format above.
π Note: The
scan_idfield must be a valid UUID/GUID. You can generate one using:
- Node.js:
import { v4 as uuidv4 } from 'uuid'; uuidv4()- PowerShell:
[guid]::NewGuid().ToString()- Online: https://www.uuidgenerator.net/
Response: See Response section above
Generate single format report
Parameters:
format:json,sarif, orpdf
Request Body: Same as multi-format endpoint (without output_formats)
Response:
- JSON/SARIF: Direct format output
- PDF: Binary PDF file
Fully structured, machine-readable format ideal for:
- API consumption
- Database storage
- Programmatic analysis
Key Sections:
- Application metadata
- Executive summary
- Detailed findings (with risk scores)
- Groupings (by category, severity, CWE)
- Scan metadata
Static Analysis Results Interchange Format
Compatible With:
- β GitHub Code Scanning
- β GitLab Security Dashboard
- β Azure DevOps
- β SonarQube
Features:
- Inline code annotations
- Automated security alerts
- Rule-based categorization
- Fix suggestions
Example Usage in GitHub Actions:
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: security-report.sarifProfessional, human-readable format for:
- Executive presentations
- Security audits
- Compliance documentation
Includes:
- Executive summary with risk score
- Severity distribution charts
- Detailed findings table
- Top priority recommendations
- Remediation guidance
npm run docker:builddocker run -d \
-p 8005:8005 \
--name reportgen \
-e NODE_ENV=production \
-e LOG_LEVEL=info \
reportgen:latestversion: '3.8'
services:
reportgen:
build:
context: .
dockerfile: docker/Dockerfile
ports:
- "8005:8005"
environment:
- NODE_ENV=production
- PORT=8005
- LOG_LEVEL=info
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8005/health"]
interval: 30s
timeout: 3s
retries: 3Each scanner service should output findings in this format:
{
"scan_id": "550e8400-e29b-41d4-a716-446655440000", // Valid UUID/GUID required
"service_name": "YourScanner",
"app_metadata": {
"package_name": "com.example.app",
"version": "1.0.0"
},
"findings": [
{
"severity": "high",
"type": "vulnerability_type",
"description": "Detailed description",
"file": "path/to/file.java",
"line": 123,
"cwe": "CWE-XXX",
"recommendation": "How to fix"
}
]
}# Example: GitHub Actions
name: Security Scan
on: [push]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Run your scanners
- name: Run APK Scanner
run: ./scanners/apk-scanner scan app.apk > apk-results.json
- name: Run Secret Hunter
run: ./scanners/secret-hunter scan . > secret-results.json
# Generate reports
- name: Generate Security Report
run: |
curl -X POST http://reportgen:8005/api/v1/generate-report \
-H "Content-Type: application/json" \
-d @combined-scan-inputs.json \
-o security-report.json
# Upload SARIF to GitHub
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: security-report.sarif| Variable | Default | Description |
|---|---|---|
PORT |
8005 |
Server port |
NODE_ENV |
development |
Environment mode |
LOG_LEVEL |
info |
Logging level (error, warn, info, debug) |
MAX_PAYLOAD_SIZE |
10mb |
Maximum request body size |
PDF_GENERATION_TIMEOUT_MS |
30000 |
PDF generation timeout |
criticalhighmediumlowinfo
secret- Hardcoded credentials, API keyscrypto- Cryptographic vulnerabilitiesnetwork- Network security issuespermission- Permission misconfigurationscode- Code quality issuescomponent- Vulnerable dependencies
reportgen/
βββ src/
β βββ index.js # Main entry point
β βββ aggregator/
β β βββ mergeResults.js # Finding aggregation logic
β βββ normalizer/
β β βββ normalizeFinding.js # Data normalization
β βββ scoring/
β β βββ riskCalculator.js # Risk scoring engine
β βββ renderers/
β β βββ jsonRenderer.js # JSON report generator
β β βββ sarifRenderer.js # SARIF report generator
β β βββ pdfRenderer.js # PDF report generator
β βββ templates/
β β βββ report.html # PDF report template
β βββ models/
β β βββ finding.schema.js # Data validation schemas
β βββ utils/
β βββ metadata.js # Utility functions
βββ docker/
β βββ Dockerfile # Production Docker image
βββ package.json
βββ README.md
npm testnpm run dev # Auto-restart on file changesThis project uses ES6 modules and follows Node.js best practices.
Problem: The scan_id field in your request is not a valid UUID/GUID.
Solution:
# Generate a valid UUID in PowerShell
[guid]::NewGuid().ToString()Use the generated UUID in your request:
{
"scan_id": "550e8400-e29b-41d4-a716-446655440000"
}Problem: Using GET instead of POST method.
Solution: The endpoint requires POST method:
Invoke-RestMethod -Uri "http://localhost:8005/api/v1/generate-report" -Method Post -ContentType "application/json" -Body $bodyProblem: Another process is using port 8005.
Solution:
# Find process using port 8005
Get-NetTCPConnection -LocalPort 8005 | Select-Object OwningProcess
Stop-Process -Id <ProcessId>
# Or use a different port
$env:PORT=3001; npm startProblem: Puppeteer/Chromium not installed properly.
Solution:
# Reinstall dependencies
npm clean-installThis microservice is designed for academic research and demonstration purposes. It implements industry-standard security reporting practices and can be used as a reference implementation for:
- Security tool development
- CI/CD security automation
- SARIF format implementation
- Risk scoring algorithms
- β Accepts multi-service scan input
- β Produces valid JSON, SARIF 2.1.0, and PDF reports
- β Deterministic and reproducible output
- β CI/CD integration ready
- β Stateless architecture
- β Docker deployment support
- β Comprehensive API documentation