vex2pdf 2.0.0

A tool to convert CycloneDX(VEX) JSON or XML documents to PDF reports
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# CycloneDX (VEX/VDR/(S)BoM) to PDF Converter

[![Rust](https://img.shields.io/badge/rust-stable-brightgreen.svg)](https://www.rust-lang.org/)
[![Documentation](https://docs.rs/vex2pdf/badge.svg)](https://docs.rs/vex2pdf)
[![Crates.io](https://img.shields.io/crates/v/vex2pdf.svg)](https://crates.io/crates/vex2pdf)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT)
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache%20License%202.0-blue)](LICENSE-APACHE)

A command-line tool to convert CycloneDX (VEX/VDR/(S)BoM) Documents in JSON or XML format to PDF reports.

## Why vex2pdf?

- **Blazing Fast**: Rust performance processes large BOMs in milliseconds with efficient concurrent processing
- **Zero Dependencies**: Single static binary with embedded fonts—no runtime dependencies, no package managers, no system libraries
- **Minimal Footprint**: ~10MB binary perfect for slim Docker images and resource-constrained environments
- **True Parallelism**: Thread-safe concurrent batch processing with configurable job limits
- **Memory Safe**: 100% safe Rust code (forbids unsafe)—no runtime crashes or memory issues
- **Cross-Platform**: Same binary works on Linux, Windows, macOS—compile once, run anywhere
- **Air-Gap Friendly**: Fully self-contained with embedded Liberation Sans fonts—works completely offline

Perfect for automated security reporting in containerized workflows, CI/CD pipelines, and production environments where reliability, speed, and minimal dependencies are critical.

<!-- TOC -->
* [CycloneDX (VEX/VDR/(S)BoM) to PDF Converter]#cyclonedx-vexvdrsbom-to-pdf-converter
  * [Why vex2pdf?]#why-vex2pdf
  * [Overview]#overview
  * [Supported Document Types]#supported-document-types
    * [VEX (Vulnerability Exploitability eXchange)]#vex-vulnerability-exploitability-exchange
    * [VDR (Vulnerability Disclosure Report)]#vdr-vulnerability-disclosure-report
    * [BOM/SBOM (Bill of Materials)]#bomsbom-bill-of-materials
  * [Vulnerability Analysis Display]#vulnerability-analysis-display
    * [Analysis States]#analysis-states
    * [Response Actions]#response-actions
    * [Analysis Information]#analysis-information
  * [Fonts Handling]#fonts-handling
    * [Font Licensing]#font-licensing
  * [Features]#features
  * [Installation]#installation
    * [Prerequisites]#prerequisites
    * [As a Command-Line Tool]#as-a-command-line-tool
    * [As a Library]#as-a-library
    * [From Source]#from-source
    * [Linux and Windows Users]#linux-and-windows-users
    * [Mac Users]#mac-users
  * [Usage]#usage
    * [Command-Line Arguments]#command-line-arguments
  * [Example]#example
  * [Example Output]#example-output
  * [Configuration]#configuration
    * [Environment Variables]#environment-variables
      * [VEX2PDF_NOVULNS_MSG]#vex2pdf_novulns_msg
      * [VEX2PDF_REPORT_TITLE]#vex2pdf_report_title
      * [VEX2PDF_PDF_META_NAME]#vex2pdf_pdf_meta_name
      * [VEX2PDF_PURE_BOM_NOVULNS]#vex2pdf_pure_bom_novulns
      * [VEX2PDF_SHOW_COMPONENTS]#vex2pdf_show_components
      * [VEX2PDF_MAX_JOBS]#vex2pdf_max_jobs
  * [Logging]#logging
    * [Log Levels]#log-levels
    * [Controlling Log Output]#controlling-log-output
  * [Documentation]#documentation
    * [Developer Notes]#developer-notes
  * [Testing]#testing
    * [Running Tests]#running-tests
    * [Code Coverage]#code-coverage
  * [CycloneDX Document Format]#cyclonedx-document-format
    * [Version 1.6 Compatibility Mode]#version-16-compatibility-mode
  * [Security Considerations]#security-considerations
  * [Changelog]#changelog
  * [License]#license
    * [Contribution]#contribution
    * [Third-Party Dependencies]#third-party-dependencies
  * [Acknowledgments]#acknowledgments
<!-- TOC -->

## Overview

VEX2PDF is a Rust application that scans the current directory for CycloneDX (VEX/VDR/(S)BoM files (JSON and XML) and converts them to human-readable PDF reports. It fully supports the CycloneDX schema version 1.5 and provides compatibility for version 1.6 documents that only use 1.5 fields. Documents using 1.6-specific fields may not process correctly. The tool handles various elements of the CycloneDX document format including vulnerabilities, components, metadata, and more.

## Supported Document Types

### VEX (Vulnerability Exploitability eXchange)
- **Purpose**: Communicates exploitability of vulnerabilities in specific contexts
- **Focus**: Real-world risk assessment and exploitability analysis

### VDR (Vulnerability Disclosure Report)
- **Purpose**: Provides comprehensive vulnerability assessments for components
- **Focus**: Known and unknown vulnerabilities with detailed analysis
- **Features**: Includes the "affected" property for component-vulnerability correlation

### BOM/SBOM (Bill of Materials)
- **Purpose**: Inventories software components and dependencies
- **Focus**: Component listing and supply chain transparency

## Vulnerability Analysis Display

VEX2PDF renders CycloneDX vulnerability analysis information with visual enhancements to improve readability and quick risk assessment:

### Analysis States

The tool displays vulnerability analysis states with color-coded formatting for immediate visual recognition:

- **Exploitable** (Red) - Vulnerability is directly or indirectly exploitable in the current environment
- **In Triage** (Orange) - Vulnerability is under active investigation by the security team
- **Resolved** (Green) - Vulnerability has been successfully remediated
- **Resolved With Pedigree** (Dark Green) - Remediated with verifiable commit history and audit trail
- **Not Affected** (Forest Green) - Component is confirmed not vulnerable to this issue
- **False Positive** (Steel Blue) - Incorrectly identified as vulnerable; not a real security issue

### Response Actions

Response actions indicate what remediation steps are available or planned:

- **Update** (Blue) - Software update available to fix the vulnerability
- **Rollback** (Blue) - Rollback to a previous non-vulnerable version is the recommended action
- **Workaround Available** (Orange) - Temporary mitigation or configuration change exists
- **Can Not Fix** (Red) - Technical limitations prevent fixing this vulnerability
- **Will Not Fix** (Red) - Vulnerability will not be addressed (risk accepted or deprioritized)

### Analysis Information

When present in the CycloneDX document, the analysis section appears after each vulnerability's description and includes:

1. **State** - Current vulnerability assessment status (color-coded)
2. **Response** - Available or planned remediation actions (displayed as a bracketed list)
3. **Justification** - Explanation for "Not Affected" determinations (e.g., "Code Not Reachable", "Protected By Compiler")
4. **Details** - Comprehensive analysis text explaining the security team's assessment
5. **Timestamps** - First issued and last updated dates for tracking analysis history

Analysis sections only appear when the CycloneDX document includes analysis data. If no analysis information exists for a vulnerability, the section is omitted entirely.

## Fonts Handling

This tool uses Liberation Sans fonts to render PDFs. The fonts are embedded directly in the binary, so **no extra font configuration is required** and the binary works standalone and is fully portable.

### Font Licensing

The embedded Liberation Sans fonts are licensed under the SIL Open Font License (OFL).
Use the `--license` flag to display full license details:

```bash
vex2pdf --license
```

The font license file is also available at [Liberation fonts License file](external/fonts/liberation-fonts/LICENSE) in the current repository.

## Features
- Automatically scans directories for JSON and XML files with VEX/VDR/(S)BoM data
- Converts (VEX/VDR/(S)BoM) documents to structured PDF reports
- Supports both JSON and XML CycloneDX formats
- Preserves all key (VEX/VDR/(S)BoM) information including:
  - Document metadata and timestamps
  - Vulnerability details with severity ratings and sources
  - _**New since v0.8.0**_  : Component-vulnerability correlation via "affected" property (VDR)
  - Exploitability assessments and risk context (VEX)
  - **New**: Vulnerability analysis with color-coded states and responses
    - Analysis states: Exploitable (red), Resolved (green), In Triage (orange), False Positive (blue), Not Affected (green), Resolved With Pedigree (dark green)
    - Response actions: Update/Rollback (blue), Workaround Available (orange), Can Not Fix/Will Not Fix (red)
    - Justification explanations for not-affected vulnerabilities
    - Detailed analysis text and timestamps (firstIssued, lastUpdated)
  - Component inventories and dependencies (BOM/SBOM)
  - Tools used to generate the CycloneDX (VEX/VDR/(S)BoM)) document
- Cross-platform support

## Installation
### Prerequisites
- Rust and Cargo (latest stable version)

### As a Command-Line Tool

Install VEX2PDF directly from crates.io:

```bash
cargo install vex2pdf
```

After installation, the `vex2pdf` binary will be available in your Cargo bin directory.

### As a Library

To use VEX2PDF as a library in your Rust project:

```bash
# Default: CLI + concurrent processing (recommended for most use cases)
cargo add vex2pdf

# Library with concurrent processing (no CLI dependencies)
cargo add vex2pdf --no-default-features --features concurrency

# Library with sequential processing (minimal dependencies)
cargo add vex2pdf --no-default-features

# CLI with sequential processing
cargo add vex2pdf --no-default-features --features cli
```

**Feature Flags:**

| Feature | Description | Default |
|---------|-------------|---------|
| `cli` | Command-line interface and argument parsing (requires `clap`, `env_logger`) | ✓ Yes |
| `concurrency` | Concurrent file processing using threadpool (requires `jlizard-simple-threadpool`) | ✓ Yes |

**Library Usage Example:**

```rust
use vex2pdf::lib_utils::config::Config;
use vex2pdf::run;

fn main() {
  let config = Config::default()
          .working_path("./input")
          .output_dir("./output")
          .max_jobs(Some(4));  // Only available with 'concurrency' feature

  run(config).expect("Failed to process files");
}
```

For complete API documentation, visit [docs.rs/vex2pdf](https://docs.rs/vex2pdf).

> Notice: As of v0.6.1 no extra font configuration is needed. Fonts have been embedded in the software binary. Check [Fonts handling and license]#fonts-handling for further information


### From Source
Clone the repository, then build the application with `cargo build --release`. The binary will be available at target/release/vex2pdf.

### Linux and Windows Users
Users can either:
1. Install via Cargo as described above
2. Build from the source using for the respective platform and operating-system. Please check the [From Source Section]#from-source
3. Use a pre-built binary under the [Release Binaries section]https://gitlab.com/jurassicLizard/vex2pdf/-/releases 

### Mac Users
Currently, No Mac Binaries are provided however Mac Users can build and install with cargo. Please check the [From Source Section](#from-source)

>  If Mac release binaries are needed please [create an issue]https://gitlab.com/jurassicLizard/vex2pdf/-/issues

## Migrating to 2.0

Version 2.0.0 introduces breaking changes to improve the library architecture and provide more flexibility. Most users won't need to make any changes.

### For CLI Users

**No changes required!** The CLI interface remains unchanged. All default features (CLI + concurrency) are enabled by default.

### For Library Users

#### If you're using default features
**No changes required!** Your code will continue to work as-is.

#### If you're using `--no-default-features`
Version 2.0 introduces a new `concurrency` feature that's enabled by default. If you're using `--no-default-features`, you now have two options:

**Option 1: Add concurrency back** (recommended for most use cases)
```bash
# Update your Cargo.toml or installation command
cargo add vex2pdf --no-default-features --features concurrency
```

**Option 2: Use sequential processing** (simpler, no threading)
```bash
# No changes needed - files will now process sequentially
cargo add vex2pdf --no-default-features
```

#### If you're using the `PdfGenerator` API directly
The `PdfGenerator` struct no longer has a lifetime parameter:

**Before (v1.x):**
```rust
let generator: PdfGenerator<'_> = PdfGenerator::new(config);
```

**After (v2.0):**
```rust
let generator: PdfGenerator = PdfGenerator::new(config);
// Or simply let type inference handle it:
let generator = PdfGenerator::new(config);
```

#### Environment Variable Changes
If you were using these deprecated environment variables, switch to CLI flags:

| Removed Variable | Replacement |
|------------------|-------------|
| `VEX2PDF_SHOW_OSS_LICENSES=true` | `vex2pdf --license` |
| `VEX2PDF_VERSION_INFO=true` | `vex2pdf --version` |

### What Changed Internally

- **Concurrency is now optional**: The `concurrency` feature flag allows you to choose between concurrent (faster) or sequential (simpler) processing
- **External threadpool**: Replaced internal implementation with `jlizard-simple-threadpool` for better maintainability
- **Cleaner API**: Removed deprecated fields from `PdfGenerator` struct (deprecated since v0.9.0)

For a complete list of changes, see the [CHANGELOG.md](CHANGELOG.md#200---2025-12-29).

## Usage

VEX2PDF is designed for batch processing and can be run without arguments to automatically process all CycloneDX files in the current directory. As of **v0.9.0**, the tool also supports command-line arguments for more precise control over input files, output directories, and report customization.

Run the application in a directory containing CycloneDX (VEX/VDR/(S)BoM files (JSON or XML):

```shell
./vex2pdf
```
The tool will:
1. Scan the current directory for JSON and XML files
2. Attempt to parse each file as a CycloneDX (VEX/VDR/(S)BoM) document
3. Generate a PDF report with the same name as the original file (with .pdf extension)
4. Display progress and results in the console

### Command-Line Arguments

VEX2PDF supports command-line arguments for convenient configuration. All arguments can also be set via environment variables as shown in the [Configuration](#configuration) section.

To see all available options, run:

```bash
vex2pdf --help
```

**Available options:**

```
A tool to convert CycloneDX(VEX) JSON or XML documents to PDF reports

Usage: vex2pdf [OPTIONS] [FILE_OR_FOLDER_TO_PROCESS]

Arguments:
  [FILE_OR_FOLDER_TO_PROCESS]  File to process (JSON or XML) or Folder containing said file types.
                               Please note that this tool is designed for batch processing. So If
                               this is not set the tool scans the current directory for all parseable
                               files and converts them. if a folder is set the tool scans just the
                               first level of the directory (non-recursive) [env: VEX2PDF_WORKING_PATH=]

Options:
  -m, --show-novulns-msg <SHOW_NOVULNS_MSG>
          [env: VEX2PDF_NOVULNS_MSG=] [possible values: true, false]
  -t, --report-title <REPORT_TITLE>
          Overrides the default title of the report [env: VEX2PDF_REPORT_TITLE=]
  -n, --pdf-meta-name <PDF_META_TITLE>
          Overrides the default PDF meta name [env: VEX2PDF_PDF_META_NAME=]
  -b, --bom-novulns <PURE_BOM_NOVULNS>
          Treats the file as a pure bill of materials and shows only the components
          without the vulnerabilities [env: VEX2PDF_PURE_BOM_NOVULNS=] [possible values: true, false]
  -c, --show-components <SHOW_COMPONENTS>
          Controls whether the component list is shown [env: VEX2PDF_SHOW_COMPONENTS=]
          [possible values: true, false]
  -d, --output-dir <OUTPUT_DIR>
          Sets the directory where the parser should output the files [env: VEX2PDF_OUTPUT_DIR=]
  -j, --max-jobs <MAX_JOBS>
          Sets the maximum number of jobs for concurrent generation tasks, when not set or set to `0`
          this defaults to using the maximum available parallelism on the system which is given by
          [`std::thread::available_parallelism`] [env: VEX2PDF_MAX_JOBS=]
  -L, --license
          Dumps the open-source software license text to the terminal and exits
  -h, --help
          Print help
  -V, --version
          Print version
```

**Examples:**

```bash
# Process a specific file
vex2pdf my-bom.json

# Process a specific directory
vex2pdf /path/to/bom/files/

# Specify output directory
vex2pdf my-bom.json -d /path/to/output/

# Hide components list
vex2pdf -c false

# Custom report title
vex2pdf -t "Security Vulnerability Assessment"

# Process with single-threaded mode (no concurrency)
vex2pdf --max-jobs 1 my-bom.json

# Process with 4 concurrent jobs
vex2pdf --max-jobs 4 /path/to/bom/files/

# Combine multiple options
vex2pdf my-bom.json -d ./reports/ -t "Q4 Security Report"
```


## Example
```
$ ./vex2pdf
[2025-10-24T18:00:00Z INFO] vex2pdf 0.9.0 - CycloneDX (VEX) to PDF Converter
[2025-10-24T18:00:00Z INFO] Copyright (c) 2025 Salem B. - MIT Or Apache 2.0 License
[2025-10-24T18:00:00Z INFO]
[2025-10-24T18:00:00Z INFO] Active font path: <embedded liberationSans fonts> -- use --license to show Font license details
[2025-10-24T18:00:00Z INFO]
[2025-10-24T18:00:00Z INFO] Using default report title
[2025-10-24T18:00:00Z INFO] Using default pdf metadata title
[2025-10-24T18:00:00Z INFO]
[2025-10-24T18:00:00Z INFO] Scanning for BoM/Vex Files in ./documents
[2025-10-24T18:00:00Z INFO] Found 2 JSON files
[2025-10-24T18:00:00Z INFO] Found 5 XML files
[2025-10-24T18:00:00Z INFO] Processing ./documents/example1.json
[2025-10-24T18:00:00Z INFO] Generating PDF:  ./documents/example1.json
[2025-10-24T18:00:00Z INFO] Successfully generated PDF: ./documents/example1.pdf
[2025-10-24T18:00:00Z INFO] Processing ./documents/example2.json
[2025-10-24T18:00:00Z INFO] Generating PDF:  ./documents/example2.json
[2025-10-24T18:00:00Z INFO] Successfully generated PDF: ./documents/example2.pdf
[2025-10-24T18:00:00Z INFO] Processing ./documents/example3.xml
[2025-10-24T18:00:01Z WARN]
[2025-10-24T18:00:01Z WARN] NOTE: Downgrading CycloneDX BOM from spec version 1.6 to 1.5
[2025-10-24T18:00:01Z WARN] Reason: Current implementation does not yet fully support spec version 1.6
[2025-10-24T18:00:01Z WARN] Warning: This compatibility mode only works for BOMs that don't utilize 1.6-specific fields
[2025-10-24T18:00:01Z WARN]          Processing will fail if 1.6-specific fields are encountered
[2025-10-24T18:00:01Z WARN]
[2025-10-24T18:00:01Z INFO] Generating PDF:  ./documents/example3.xml
[2025-10-24T18:00:01Z INFO] Successfully generated PDF: ./documents/example3.pdf
[2025-10-24T18:00:01Z INFO] Processed 7 files
```

## Example Output

See sample generated PDFs from various CycloneDX documents in the repository:

- **[VDR with Vulnerability Analysis]tests/test_artifacts/expected_pdfs/bom_vdr_with_analysis.pdf** - Demonstrates color-coded analysis states (Exploitable, In Triage, Resolved) and response actions
- **[VDR with Multiple Vulnerabilities]tests/test_artifacts/expected_pdfs/bom_vdr_with_many_vulns.pdf** - Complex report showing multiple CVEs and affected components
- **[Simple VEX Report]tests/test_artifacts/expected_pdfs/bom_vex_simple_one_vuln.pdf** - Basic VEX document with single vulnerability
- **[XML-based VDR]tests/test_artifacts/expected_pdfs/bom_xml_vdr_simple.pdf** - Shows XML input processing
- **[VDR with GHSA Entries]tests/test_artifacts/expected_pdfs/bom_vdr_with_ghsa_entries.pdf** - GitHub Security Advisory integration example

All PDFs include embedded Liberation Sans fonts and require no additional dependencies to view.

## Configuration

No configuration files are required. However the application has some customization options available via Environment variables.


### Environment Variables


> **Windows Users**: To set environment variables on Windows, use:
> - **Command Prompt**: `set VEX2PDF_ENV_VARIABLE=false && vex2pdf`
> - **PowerShell**: `$env:VEX2PDF_ENV_VARIABLE="false"; vex2pdf`

The following environment variables can be used to customize behavior:


| Variable                  | Purpose                                                                       | Default                               |
|---------------------------|-------------------------------------------------------------------------------|---------------------------------------|
| VEX2PDF_NOVULNS_MSG       | Controls the "No Vulnerabilities reported" message display                    | true                                  |
| VEX2PDF_REPORT_TITLE      | Overrides the default report title                                            | Not set (uses default title)          |
| VEX2PDF_PDF_META_NAME     | Overrides the PDF metadata title                                              | Not set (uses default metadata title) |
| VEX2PDF_PURE_BOM_NOVULNS  | Whether to treat the file as a component list instead of a vulnerability list | false                                 |
| VEX2PDF_SHOW_COMPONENTS   | Whether to additionally show the component list after the vulnerability list  | true                                  |
| VEX2PDF_MAX_JOBS          | Controls the maximum number of concurrent processing jobs                     | Not set (uses max parallelism)        |                             

#### VEX2PDF_NOVULNS_MSG

This variable controls how the Vulnerabilities section appears when no vulnerabilities exist:
- When set to "true" or not set (default): A "Vulnerabilities" section will be shown with a "No Vulnerabilities reported" message
- When set to "false": The Vulnerabilities section will be completely omitted from the PDF

Example : `VEX2PDF_NOVULNS_MSG=false vex2pdf`

#### VEX2PDF_REPORT_TITLE

Overrides the default report title with custom text

Example : `VEX2PDF_REPORT_TITLE="My Custom VEX Report" vex2pdf`

#### VEX2PDF_PDF_META_NAME

Overrides the PDF metadata title with custom text

Example 1 : `VEX2PDF_PDF_META_NAME="VEX Report - Company XYZ" vex2pdf`
Example 2 : `VEX2PDF_PDF_META_NAME="VEX Report - Company XYZ" VEX2PDF_REPORT_TITLE="My Custom VEX Report" vex2pdf`

#### VEX2PDF_PURE_BOM_NOVULNS

Whether to treat the file as a pure CycloneDX Bill of Materials only listing the components and ignoring the vulnerability list 

Example : `VEX2PDF_PURE_BOM_NOVULNS=true vex2pdf`

#### VEX2PDF_SHOW_COMPONENTS

Whether to show the complete list of components after the vulnerabilities section. The default behaviour is `true` but this can be overridden

Example: `VEX2PDF_SHOW_COMPONENTS=false vex2pdf`

#### VEX2PDF_MAX_JOBS

Controls the maximum number of concurrent jobs for processing multiple BOM files:
- When not set or set to `0` (default): Uses all available CPU cores for maximum parallelism
- When set to `1`: Runs in single-threaded mode (sequential processing in main thread)
- When set to `2-255`: Uses the specified number of concurrent jobs

**Single-threaded mode** is useful for:
- Debugging and troubleshooting
- Systems with limited resources
- Reproducible processing order

**Multi-threaded mode** (default) provides:
- Faster processing of multiple files
- Better resource utilization on multi-core systems

Example (single-threaded): `VEX2PDF_MAX_JOBS=1 vex2pdf`

Example (4 concurrent jobs): `VEX2PDF_MAX_JOBS=4 vex2pdf`

Example (default parallelism): `VEX2PDF_MAX_JOBS=0 vex2pdf` or simply `vex2pdf`

## Logging

VEX2PDF uses structured logging to provide clear visibility into its operation. Logs include timestamps, severity levels, and module paths for easy troubleshooting.

### Log Levels

The tool supports four log levels:

- **ERROR** - Critical errors that prevent operation (output to stderr)
- **WARN** - Warnings about potential issues or compatibility concerns (output to stderr)
- **INFO** - Normal operational messages showing progress and results (output to stdout) - **Default level**
- **DEBUG** - Detailed internal information including worker thread activity (output to stdout)

### Controlling Log Output

By default, the tool shows **INFO** level logs without any configuration. You can control the log level using the `RUST_LOG` environment variable:

```bash
# Default behavior (info level) - no configuration needed
vex2pdf

# Show all logs including debug information (verbose mode)
RUST_LOG=debug vex2pdf

# Show only warnings and errors (quiet mode)
RUST_LOG=warn vex2pdf

# Show only errors (minimal output)
RUST_LOG=error vex2pdf

# Disable all logging
RUST_LOG=off vex2pdf
```

**Note:** Debug logs are completely removed from release builds at compile time for optimal performance and smaller binary size.

**Output Routing:**
- Informational logs (INFO, DEBUG) → stdout - normal operational output
- Problem logs (WARN, ERROR) → stderr - errors and warnings for script handling

This separation allows for proper Unix-style piping and redirection:
```bash
# Capture only errors to a file
vex2pdf 2> errors.log

# Separate normal output and errors
vex2pdf > output.log 2> errors.log
```

## Documentation

For full API documentation, please visit:
- [vex2pdf on docs.rs]https://docs.rs/vex2pdf

To generate documentation locally:
```bash
cargo doc --open
```

### Developer Notes

For information about testing, code coverage, architecture, and the traits system, see [Developer Notes](docs/DEVELOPER_NOTES.md).

## Testing

The test suite includes comprehensive integration tests that validate PDF generation accuracy using BLAKE3 checksums of normalized content (with timestamps and dynamic IDs stripped).

### Running Tests

```bash
# Run all tests (with CLI feature, default)
cargo test

# Run only library unit tests
cargo test --lib

# Run library tests without CLI dependencies
cargo test --lib --no-default-features

# Build library-only (no CLI dependencies)
cargo build --no-default-features
```

**Note:** Integration tests require the `cli` feature and will be skipped when testing with `--no-default-features`.

**Warning:** PDF checksums used in integration tests are generated from debug builds. While checksums should be consistent across builds, differences in compiler optimizations between debug and release modes may occasionally cause checksum mismatches. If you encounter checksum failures in release builds, this is expected behavior and does not indicate a test failure.

### Code Coverage

```bash
# Install coverage tool
cargo install cargo-llvm-cov

# Generate HTML coverage report
cargo llvm-cov --html
# Opens coverage report in browser at target/llvm-cov/html/index.html
```

Tests work seamlessly from both the git repository and crates.io packages.

## CycloneDX Document Format
This tool fully supports CycloneDX schema version 1.5 and provides compatibility for version 1.6 documents that only use 1.5 fields. Documents using 1.6-specific fields may not process correctly. For more information about the CycloneDX format, see:
- [CycloneDX VEX Specification]https://cyclonedx.org/capabilities/vex/
- [CycloneDX VDR Specification]https://cyclonedx.org/capabilities/vdr/
- [CycloneDX Schema]https://cyclonedx.org/docs/1.5/json/

### Version 1.6 Compatibility Mode

This tool implements a special compatibility mode for CycloneDX 1.6 documents:

- When the tool encounters a document with `specVersion: "1.6"`, it will:
  1. Display a notification about downgrading to 1.5
  2. Automatically modify the document's spec version to "1.5"
  3. Attempt to process it using the 1.5 schema parser

This compatibility approach works well for documents that don't use 1.6-specific fields but allows the tool to process newer documents without requiring users to manually modify them.

**Limitations:**
- Documents that use 1.6-specific fields or structures may fail during processing
- No validation is performed for 1.6-specific features
- This is a temporary solution until full 1.6 support is implemented in the underlying cyclonedx-bom library

When processing 1.6 documents, you'll see console messages indicating the compatibility mode is active.

## Security Considerations
- The application reads and processes files from the current directory
- No network connections are established
- Input validation is performed on all JSON files

## Changelog

Changes to the software between version increments are documented under [Changelog.md](CHANGELOG.md).

## License

This project is licensed under either of:

* [MIT License]LICENSE-MIT
* [Apache License, Version 2.0]LICENSE-APACHE

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you shall be dual-licensed as above, without any
additional terms or conditions.

### Third-Party Dependencies

This project uses third-party dependencies that may be distributed under different licenses.
Please refer to the license information provided with each dependency for details.

## Acknowledgments
- [CycloneDX]https://cyclonedx.org/ for CycloneDX document specification
- [cyclonedx-bom]https://crates.io/crates/cyclonedx-bom for CycloneDX parsing
- [genpdf]https://crates.io/crates/genpdf for PDF generation
- [serde_json]https://crates.io/crates/serde_json for JSON processing
- [Liberation Fonts]https://github.com/liberationfonts/liberation-fonts for the PDF rendering fonts