renderer

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2025 License: MIT Imports: 6 Imported by: 0

README

Vulnerability CLI Renderer

This package provides a flexible CLI renderer for vulnerability search results that uses a JSON-based layout configuration system.

Features

  • Flexible Layout Configuration: Define output format using JSON configuration
  • Smart Omission Rules: Automatically hide empty or irrelevant fields
  • List Truncation: Show first N items with "+X more" indicator
  • Formatted Output: Pretty-print numbers, booleans, and exposure counts
  • Exploit Detection: Automatically detect if a vulnerability has been exploited

Usage

package main

import (
    "fmt"
    "log"

    "github.com/projectdiscovery/cvemap/pkg/tools/renderer"
    "github.com/projectdiscovery/cvemap"
)

func main() {
    // Define layout configuration
    layoutJSON := `[
        {
            "line": 1,
            "format": "[{doc_id}] {severity} - {title}",
            "omit_if": []
        },
        {
            "line": 2,
            "format": "↳ Authors: {authors} | Vuln Age: {age_in_days}d | EPSS: {epss_score} | CVSS: {cvss_score}",
            "omit_if": ["authors.length == 0", "epss_score == 0", "cvss_score == 0"]
        }
    ]`

    // Parse layout
    layout, err := renderer.ParseLayout([]byte(layoutJSON))
    if err != nil {
        log.Fatal(err)
    }

    // Convert vulnerability to entry
    entry := renderer.FromVulnerability(vuln)
    entries := []*renderer.Entry{entry}

    // Render output
    result := renderer.Render(entries, layout, 1, 1)
    fmt.Println(result)
}

Layout Configuration

The layout is defined as a JSON array of LayoutLine objects:

[
  {
    "line": 1,
    "format": "[{doc_id}] {severity} - {title}",
    "omit_if": []
  },
  {
    "line": 2,
    "format": "↳ Authors: {authors} | Vuln Age: {age_in_days}d",
    "omit_if": ["authors.length == 0"]
  }
]
Available Placeholders
Placeholder Description Example
{doc_id} Document ID CVE-2024-1234
{severity} Severity level (capitalized) Critical
{title} Vulnerability title Remote Code Execution
{authors} Authors (max 3, then "+N") author1, author2, author3 +2
{age_in_days} Age in days 123
{age_urgency} Age with urgency indicators 5d (NEW), 25d (RECENT), 90d
{epss_score} EPSS score 0.85
{cvss_score} CVSS score 9.1
{exposure} Exposure count ~15.0K or unknown
{vendors} Distinct vendors (max 3) vendor1, vendor2 +1
{products} Distinct products (max 3) product1, product2 +1
{patch} Patch availability or
{poc_count} POC count 3 or
{kev} KEV status or
{template} Template availability or
{exploit_seen} Exploit detected or
{hackerone} HackerOne reports or
{tags} Tags (max 3) rce, auth-bypass +1
Omission Rules

The omit_if array contains conditions that will cause a line to be omitted:

  • "authors.length == 0" - Omit if no authors
  • "epss_score == 0" - Omit if EPSS score is 0
  • "cvss_score == 0" - Omit if CVSS score is 0
  • "exposure == 0" - Omit if exposure is 0 or unknown
  • "vendors.length == 0" - Omit if no vendors
  • "products.length == 0" - Omit if no products
  • "tags.length == 0" - Omit if no tags

Formatting Rules

Exposure Formatting
  • 0"unknown"
  • 1-999 → as-is (e.g., "500")
  • 1000+"~12.3K" format
Boolean Formatting
  • true"✔"
  • false"✘"
POC Count Formatting
  • 0"✘"
  • >0 → numeric value (e.g., "3")
List Truncation
  • Shows up to 3 items
  • Additional items shown as " +N"
  • Example: "item1, item2, item3 +2"
Age Urgency Indicators
  • ≤7 days"5d (NEW)" - Shows NEW indicator for recently disclosed vulnerabilities
  • ≤30 days"25d (RECENT)" - Shows RECENT indicator for recently disclosed vulnerabilities
  • >30 days"90d" - Shows age only for older vulnerabilities

Exploit Detection

The renderer automatically detects if a vulnerability has been exploited based on:

  1. POC sources containing exploit keywords: exploit, exploiting, exploitation, exploitable
  2. Citation URLs from exploit domains: exploit-db.com, exploitdb.com, metasploit.com
  3. Description/Impact containing phrases:
    • "exploited in the wild"
    • "actively exploited"
    • "used in attacks"
    • "real-world exploitation"

Color Highlighting

The renderer includes intelligent color highlighting for better readability:

Severity Colors
  • Critical - Bright red for maximum urgency
  • High - Red for high importance
  • Medium - Yellow for moderate attention
  • Low - Green for low priority
Age Urgency Colors
  • (NEW) - Bright cyan for freshly disclosed vulnerabilities ≤7 days old
  • (RECENT) - Bright blue for recently disclosed vulnerabilities ≤30 days old
Priority & Status Colors
  • IMMEDIATE/URGENT - Red for critical priorities
  • HIGH/MEDIUM - Yellow for important priorities
  • LOW - Green for low priority
  • EXPLOITS AVAILABLE - Bright yellow for exploit availability
  • KEV LISTED - Bright magenta for KEV status
  • ✔/✘ - Green/Red for boolean indicators
Color Control
  • Colors are automatically enabled for terminal output
  • Colors are disabled for non-terminal output (pipes, files)
  • Use --no-color flag to disable colors manually

Example Output

[CVE-2024-1234] Critical - Remote Code Execution Vulnerability
↳ Authors: security-team, researcher | Vuln Age: 30d | EPSS: 0.85 | CVSS: 9.1
↳ Exposure: ~15.0K | Vendors: example-corp | Products: webapp, api-server
↳ Patch: ✔ | POCs: 2 | KEV: ✔ | Template: ✘ | Exploit Seen: ✔ | HackerOne: ✔
↳ Tags: rce, auth-bypass
↳ Showing 1 of 1 total results

API Reference

Types
type LayoutLine struct {
    Line   int      `json:"line"`
    Format string   `json:"format"`
    OmitIf []string `json:"omit_if"`
}

type Entry struct {
    DocID              string
    Name               string
    Severity           string
    Author             []string
    AgeInDays          int
    EpssScore          float64
    CvssScore          float64
    Exposure           *cvemap.VulnExposure
    AffectedProducts   []*cvemap.ProductInfo
    IsPatchAvailable   bool
    PocCount           int
    IsKev              bool
    IsTemplate         bool
    H1                 *cvemap.H1Stats
    Tags               []string
    Pocs               []*cvemap.POC
    Citations          []*cvemap.Citation
    Description        string
    Impact             string
}
Functions
// ParseLayout parses layout JSON into LayoutLine structs
func ParseLayout(layoutJSON []byte) ([]LayoutLine, error)

// FromVulnerability converts a cvemap.Vulnerability to an Entry
func FromVulnerability(v *cvemap.Vulnerability) *Entry

// Render generates formatted output for vulnerability entries
func Render(entries []*Entry, layout []LayoutLine, totalResults, shownResults int) string

Testing

Run the test suite:

go test ./pkg/tools/renderer/...

The package includes comprehensive tests covering:

  • Layout parsing
  • Placeholder replacement
  • Omission rules
  • Formatting functions
  • Exploit detection
  • List truncation
  • Expected output validation

Documentation

Index

Examples

Constants

View Source
const (
	Reset = "\033[0m"
	Bold  = "\033[1m"
	Dim   = "\033[2m"

	// Colors
	Red     = "\033[31m"
	Green   = "\033[32m"
	Yellow  = "\033[33m"
	Blue    = "\033[34m"
	Magenta = "\033[35m"
	Cyan    = "\033[36m"
	White   = "\033[37m"
	Gray    = "\033[90m"

	// Bright colors
	BrightRed     = "\033[91m"
	BrightGreen   = "\033[92m"
	BrightYellow  = "\033[93m"
	BrightBlue    = "\033[94m"
	BrightMagenta = "\033[95m"
	BrightCyan    = "\033[96m"
	BrightWhite   = "\033[97m"
)

Color constants for ANSI escape codes

Variables

This section is empty.

Functions

func IsTerminal

func IsTerminal() bool

IsTerminal checks if output is a terminal

func Render

func Render(entries []*Entry, layout []LayoutLine, totalResults, shownResults int) string

Render generates formatted output for vulnerability entries using the provided layout

Example
// Define layout configuration
layoutJSON := `[
		{
			"line": 1,
			"format": "[{doc_id}] {severity} - {title}",
			"omit_if": []
		},
		{
			"line": 2,
			"format": "↳ Template Authors: {authors} | Vuln Age: {age_in_days}d | EPSS: {epss_score} | CVSS: {cvss_score}",
			"omit_if": ["authors.length == 0", "epss_score == 0", "cvss_score == 0"]
		},
		{
			"line": 3,
			"format": "↳ Exposure: {exposure} | Vendors: {vendors} | Products: {products}",
			"omit_if": ["exposure == 0", "vendors.length == 0", "products.length == 0"]
		},
		{
			"line": 4,
			"format": "↳ Patch: {patch} | POCs: {poc_count} | KEV: {kev_enhanced} | Nuclei Template: {template} | Exploit Seen: {exploit_seen} | HackerOne: {hackerone}",
			"omit_if": []
		},
		{
			"line": 5,
			"format": "↳ Tags: {tags}",
			"omit_if": ["tags.length == 0"]
		}
	]`

// Parse layout
layout, err := ParseLayout([]byte(layoutJSON))
if err != nil {
	log.Fatal(err)
}

// Create sample vulnerability data
vuln := &cvemap.Vulnerability{
	DocID:     "CVE-2024-1234",
	Name:      "Example Vulnerability",
	Severity:  "critical",
	Author:    []string{"security-team", "researcher"},
	AgeInDays: 30,
	EpssScore: 0.85,
	CvssScore: 9.1,
	Exposure: &cvemap.VulnExposure{
		MaxHosts: 15000,
	},
	AffectedProducts: []*cvemap.ProductInfo{
		{Vendor: "example-corp", Product: "webapp"},
		{Vendor: "example-corp", Product: "api-server"},
	},
	IsPatchAvailable: true,
	PocCount:         2,
	IsKev:            true,
	Kev: []*cvemap.KevInfo{
		{Source: "cisa"},
		{Source: "vulcheck"},
	},
	IsTemplate:  false,
	H1:          &cvemap.H1Stats{Reports: 5},
	Tags:        []string{"rce", "auth-bypass"},
	Description: "Critical vulnerability that has been exploited in the wild",
}

// Convert to Entry and render
entry := FromVulnerability(vuln)
entries := []*Entry{entry}

result := RenderWithColors(entries, layout, 1, 1, NoColorConfig())
fmt.Println(result)
Output:

[CVE-2024-1234] Critical - Example Vulnerability
↳ Template Authors: security-team, researcher | Vuln Age: 30d | EPSS: 0.85 | CVSS: 9.1
↳ Exposure: ~15.0K | Vendors: example-corp | Products: webapp, api-server
↳ Patch: ✔ | POCs: 2 | KEV: ✔ (CISA, VULCHECK) | Nuclei Template: ✘ | Exploit Seen: ✔ | HackerOne: ✔
↳ Tags: rce, auth-bypass

↳ Showing 1 of 1 total results

func RenderDetailed

func RenderDetailed(entry *Entry, colors *ColorConfig) string

RenderDetailed generates detailed formatted output for a single vulnerability

func RenderWithColors

func RenderWithColors(entries []*Entry, layout []LayoutLine, totalResults, shownResults int, colors *ColorConfig) string

RenderWithColors generates formatted output with color support

Types

type ColorConfig

type ColorConfig struct {
	Enabled bool

	// CVE ID and severity
	CveID    string
	Critical string
	High     string
	Medium   string
	Low      string
	Unknown  string

	// Content elements
	Title     string
	Arrow     string
	Label     string
	Value     string
	Separator string

	// Status indicators
	Success string
	Warning string
	Error   string
	Info    string

	// Numbers and metrics
	Number string
	Metric string

	// Tags
	Tag string

	// Footer
	Footer string
}

ColorConfig holds color configuration

func DefaultColorConfig

func DefaultColorConfig() *ColorConfig

DefaultColorConfig returns a default color configuration

func NoColorConfig

func NoColorConfig() *ColorConfig

NoColorConfig returns a color configuration with no colors

func (*ColorConfig) ColorAgeUrgency

func (c *ColorConfig) ColorAgeUrgency(ageInDays int) string

ColorAgeUrgency colors vulnerability age with urgency indicators

func (*ColorConfig) ColorArrow

func (c *ColorConfig) ColorArrow(arrow string) string

ColorArrow colors the arrow symbol

func (*ColorConfig) ColorBoolean

func (c *ColorConfig) ColorBoolean(checkmark string) string

ColorBoolean colors boolean checkmarks

func (*ColorConfig) ColorCVEID

func (c *ColorConfig) ColorCVEID(cveID string) string

ColorCVEID colors CVE ID

func (*ColorConfig) ColorCVSSScore

func (c *ColorConfig) ColorCVSSScore(score float64) string

ColorCVSSScore colors CVSS score with severity indicators

func (*ColorConfig) ColorEPSSScore

func (c *ColorConfig) ColorEPSSScore(score float64) string

ColorEPSSScore colors EPSS score with probability indicators

func (*ColorConfig) ColorExploitAvailability

func (c *ColorConfig) ColorExploitAvailability(available bool, pocCount int, kevStatus bool) string

ColorExploitAvailability colors exploit availability with urgency

func (*ColorConfig) ColorExposure

func (c *ColorConfig) ColorExposure(exposure string) string

ColorExposure colors exposure values with appropriate colors

func (*ColorConfig) ColorFooter

func (c *ColorConfig) ColorFooter(footer string) string

ColorFooter colors footer text

func (*ColorConfig) ColorKEVStatus

func (c *ColorConfig) ColorKEVStatus(isKEV bool) string

ColorKEVStatus colors KEV status with high visibility

func (*ColorConfig) ColorLabel

func (c *ColorConfig) ColorLabel(label string) string

ColorLabel colors field labels

func (*ColorConfig) ColorMetric

func (c *ColorConfig) ColorMetric(metric string) string

ColorMetric colors metrics (CVSS, EPSS)

func (*ColorConfig) ColorNumber

func (c *ColorConfig) ColorNumber(number string) string

ColorNumber colors numeric values

func (*ColorConfig) ColorResultSeparator

func (c *ColorConfig) ColorResultSeparator(separator string) string

ColorResultSeparator colors the separator between results with special styling

func (*ColorConfig) ColorSeparator

func (c *ColorConfig) ColorSeparator(separator string) string

ColorSeparator colors separators

func (*ColorConfig) ColorSeverity

func (c *ColorConfig) ColorSeverity(severity string) string

ColorSeverity colors severity text based on severity level

func (*ColorConfig) ColorTag

func (c *ColorConfig) ColorTag(tag string) string

ColorTag colors tags

func (*ColorConfig) ColorTitle

func (c *ColorConfig) ColorTitle(title string) string

ColorTitle colors title

func (*ColorConfig) ColorValue

func (c *ColorConfig) ColorValue(value string) string

ColorValue colors field values

func (*ColorConfig) Colorize

func (c *ColorConfig) Colorize(text, color string) string

Colorize applies color to text if colors are enabled

func (*ColorConfig) ColorizeFormattedLine

func (c *ColorConfig) ColorizeFormattedLine(line string, lineNum int) string

ColorizeFormattedLine applies colors to a formatted line

type Entry

type Entry struct {
	DocID            string                `json:"doc_id"`
	Name             string                `json:"name"`
	Severity         string                `json:"severity"`
	Author           []string              `json:"author"`
	AgeInDays        int                   `json:"age_in_days"`
	EpssScore        float64               `json:"epss_score"`
	CvssScore        float64               `json:"cvss_score"`
	Exposure         *cvemap.VulnExposure  `json:"exposure"`
	AffectedProducts []*cvemap.ProductInfo `json:"affected_products"`
	IsPatchAvailable bool                  `json:"is_patch_available"`
	PocCount         int                   `json:"poc_count"`
	IsKev            bool                  `json:"is_kev"`
	Kev              []*cvemap.KevInfo     `json:"kev"`
	IsTemplate       bool                  `json:"is_template"`
	H1               *cvemap.H1Stats       `json:"h1"`
	Tags             []string              `json:"tags"`
	Pocs             []*cvemap.POC         `json:"pocs"`
	Citations        []*cvemap.Citation    `json:"citations"`
	Description      string                `json:"description"`
	Impact           string                `json:"impact"`
	Remediation      string                `json:"remediation"`
	TemplateURI      string                `json:"template_uri"`
	TemplateRaw      string                `json:"template_raw"`
}

Entry represents a vulnerability entry with all fields needed for rendering

func FromVulnerability

func FromVulnerability(v *cvemap.Vulnerability) *Entry

FromVulnerability converts a cvemap.Vulnerability to an Entry

type LayoutLine

type LayoutLine struct {
	Line   int      `json:"line"`
	Format string   `json:"format"`
	OmitIf []string `json:"omit_if"`
}

LayoutLine represents a single line in the layout configuration

func ParseLayout

func ParseLayout(layoutJSON []byte) ([]LayoutLine, error)

ParseLayout parses layout JSON into LayoutLine structs

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL