or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdcli-commands.mdconfiguration.mderrors.mdformatters.mdindex.mdmodels.mdprogrammatic.mdscanning.md

formatters.mddocs/

0

# Output and Formatters

1

2

Safety CLI provides a comprehensive formatting and output system that supports multiple report formats for vulnerability scanning, license checking, and other analysis results. The system uses a strategy pattern with pluggable formatters for different output types.

3

4

## Core Formatter Architecture

5

6

### FormatterAPI Base Class { .api }

7

8

**Import Statements:**

9

10

```python

11

from safety.formatter import FormatterAPI, SafetyFormatter

12

from safety.formatters.json import JsonReport, build_json_report

13

from safety.formatters.text import TextReport

14

from safety.formatters.screen import ScreenReport

15

from safety.formatters.html import HTMLReport

16

from safety.formatters.bare import BareReport

17

from safety.models import SafetyEncoder

18

```

19

20

#### FormatterAPI Abstract Base { .api }

21

22

**Description**: Abstract base class defining the interface for all output formatters.

23

24

```python

25

class FormatterAPI:

26

"""Strategy pattern base class for report formatters."""

27

28

def __init__(self, **kwargs: Any) -> None:

29

"""

30

Initialize formatter with configuration options.

31

32

Args:

33

**kwargs: Formatter-specific configuration options

34

"""

35

36

@abstractmethod

37

def render_vulnerabilities(

38

self,

39

announcements: List[Dict[str, Any]], # Platform announcements

40

vulnerabilities: List[Dict[str, Any]], # Found vulnerabilities

41

remediations: Dict[str, Any], # Remediation suggestions

42

full: bool, # Include full details

43

packages: List[Dict[str, Any]], # Scanned packages

44

fixes: Tuple = () # Applied fixes

45

) -> Optional[str]:

46

"""

47

Render vulnerability scan results.

48

49

Args:

50

announcements: Platform announcements and notices

51

vulnerabilities: Detected vulnerabilities

52

remediations: Available remediation options

53

full: Whether to include detailed information

54

packages: List of analyzed packages

55

fixes: Applied automatic fixes

56

57

Returns:

58

Optional[str]: Formatted report output

59

"""

60

61

@abstractmethod

62

def render_licenses(

63

self,

64

announcements: List[Dict[str, Any]], # Platform announcements

65

licenses: List[Dict[str, Any]] # License information

66

) -> Optional[str]:

67

"""

68

Render license compliance report.

69

70

Args:

71

announcements: Platform announcements

72

licenses: Package license information

73

74

Returns:

75

Optional[str]: Formatted license report

76

"""

77

78

@abstractmethod

79

def render_announcements(

80

self,

81

announcements: List[Dict[str, Any]] # Platform announcements

82

) -> Optional[str]:

83

"""

84

Render platform announcements.

85

86

Args:

87

announcements: Platform announcements and notices

88

89

Returns:

90

Optional[str]: Formatted announcements

91

"""

92

```

93

94

### SafetyFormatter Factory { .api }

95

96

**Description**: Factory class that creates appropriate formatter instances based on output format specification.

97

98

```python

99

class SafetyFormatter(FormatterAPI):

100

"""Factory formatter that delegates to specific format implementations."""

101

102

def __init__(self, output: str, **kwargs: Any) -> None:

103

"""

104

Initialize formatter factory with target output format.

105

106

Args:

107

output (str): Target output format ('json', 'html', 'bare', 'text', 'screen')

108

**kwargs: Additional configuration passed to specific formatter

109

"""

110

111

# Supported output formats

112

SUPPORTED_FORMATS = [

113

'json', # Machine-readable JSON

114

'html', # Web-viewable HTML report

115

'bare', # Minimal text output

116

'text', # Formatted text report

117

'screen' # Rich terminal output (default)

118

]

119

```

120

121

**Example Usage:**

122

123

```python

124

from safety.formatter import SafetyFormatter

125

126

# Create JSON formatter

127

json_formatter = SafetyFormatter(output='json')

128

129

# Create HTML formatter with custom template

130

html_formatter = SafetyFormatter(

131

output='html',

132

template_dir='/custom/templates'

133

)

134

135

# Create screen formatter for terminal output

136

screen_formatter = SafetyFormatter(output='screen')

137

```

138

139

## Format-Specific Implementations

140

141

### JSON Formatter { .api }

142

143

#### JsonReport Class { .api }

144

145

**Description**: Generates machine-readable JSON reports for vulnerability and license data.

146

147

```python

148

class JsonReport(FormatterAPI):

149

"""JSON formatter for machine-readable output."""

150

151

def __init__(self, version: str = "3.0", **kwargs: Any) -> None:

152

"""

153

Initialize JSON formatter.

154

155

Args:

156

version (str): JSON schema version to use

157

**kwargs: Additional configuration options

158

"""

159

160

def render_vulnerabilities(

161

self,

162

announcements: List[Dict[str, Any]],

163

vulnerabilities: List[Dict[str, Any]],

164

remediations: Dict[str, Any],

165

full: bool,

166

packages: List[Dict[str, Any]],

167

fixes: Tuple = ()

168

) -> str:

169

"""

170

Generate JSON vulnerability report.

171

172

Returns:

173

str: JSON-formatted vulnerability report

174

"""

175

176

def render_licenses(

177

self,

178

announcements: List[Dict[str, Any]],

179

licenses: List[Dict[str, Any]]

180

) -> str:

181

"""

182

Generate JSON license report.

183

184

Returns:

185

str: JSON-formatted license report

186

"""

187

```

188

189

#### JSON Report Builder { .api }

190

191

```python

192

def build_json_report(

193

announcements: List[Dict], # Platform announcements

194

vulnerabilities: List[Dict], # Vulnerability data

195

remediations: Dict[str, Any], # Remediation options

196

packages: List[Any] # Package information

197

) -> Dict[str, Any]:

198

"""

199

Build structured JSON report from scan results.

200

201

Args:

202

announcements: Platform announcements and notices

203

vulnerabilities: Detected vulnerabilities

204

remediations: Available remediation suggestions

205

packages: Scanned package information

206

207

Returns:

208

Dict[str, Any]: Structured report data ready for JSON serialization

209

"""

210

```

211

212

**JSON Report Structure:**

213

214

```json

215

{

216

"report_meta": {

217

"scan_target": "project_directory",

218

"timestamp": "2024-01-15T10:30:00Z",

219

"safety_version": "3.6.1",

220

"vulnerabilities_found": 2,

221

"vulnerabilities_ignored": 1,

222

"remediations_recommended": 1

223

},

224

"vulnerabilities": [

225

{

226

"vulnerability_id": "VULN-12345",

227

"package_name": "requests",

228

"installed_version": "2.20.0",

229

"affected_versions": ">=2.0.0,<2.20.1",

230

"advisory": "Security vulnerability description",

231

"cve": {

232

"name": "CVE-2023-12345",

233

"cvssv3": 7.5

234

},

235

"severity": {

236

"source": "safety",

237

"cvssv3": 7.5

238

},

239

"fixed_versions": ["2.20.1", "2.21.0"],

240

"ignored": false,

241

"more_info_url": "https://safety.com/vuln/12345"

242

}

243

],

244

"ignored_vulnerabilities": [...],

245

"remediations": {...},

246

"packages": [...],

247

"announcements": [...]

248

}

249

```

250

251

### Screen Formatter { .api }

252

253

#### ScreenReport Class { .api }

254

255

**Description**: Rich terminal formatter with colors, formatting, and interactive elements.

256

257

```python

258

class ScreenReport(FormatterAPI):

259

"""Rich terminal formatter for interactive console output."""

260

261

def __init__(self,

262

console=None, # Rich console instance

263

emoji: bool = True, # Enable emoji output

264

**kwargs: Any) -> None:

265

"""

266

Initialize screen formatter.

267

268

Args:

269

console: Rich console instance for output

270

emoji: Enable emoji in output

271

**kwargs: Additional configuration

272

"""

273

274

def render_vulnerabilities(self, ...) -> str:

275

"""

276

Generate rich terminal vulnerability report with:

277

- Color-coded severity levels

278

- Formatted tables and lists

279

- Progress indicators

280

- Interactive elements

281

"""

282

283

def render_licenses(self, ...) -> str:

284

"""Generate formatted license compliance report."""

285

```

286

287

**Screen Output Features:**

288

289

- **Color Coding**: Severity-based color schemes (red=critical, orange=high, etc.)

290

- **Rich Formatting**: Tables, lists, and structured layout

291

- **Emoji Support**: Visual indicators for status and severity

292

- **Progress Indicators**: Real-time scan progress

293

- **Interactive Elements**: Clickable links and expandable sections

294

295

### Text Formatter { .api }

296

297

#### TextReport Class { .api }

298

299

**Description**: Plain text formatter for non-interactive environments and file output.

300

301

```python

302

class TextReport(FormatterAPI):

303

"""Plain text formatter for file output and non-interactive terminals."""

304

305

def render_vulnerabilities(self, ...) -> str:

306

"""

307

Generate plain text vulnerability report suitable for:

308

- File output

309

- Email reports

310

- CI/CD logs

311

- Non-interactive terminals

312

"""

313

314

def render_licenses(self, ...) -> str:

315

"""Generate plain text license report."""

316

```

317

318

### HTML Formatter { .api }

319

320

#### HTMLReport Class { .api }

321

322

**Description**: HTML formatter for web-viewable reports with styling and interactivity.

323

324

```python

325

class HTMLReport(FormatterAPI):

326

"""HTML formatter for web-viewable vulnerability reports."""

327

328

def __init__(self,

329

template_dir: Optional[str] = None, # Custom template directory

330

**kwargs: Any) -> None:

331

"""

332

Initialize HTML formatter.

333

334

Args:

335

template_dir: Custom Jinja2 template directory

336

**kwargs: Additional template variables

337

"""

338

339

def render_vulnerabilities(self, ...) -> str:

340

"""

341

Generate HTML vulnerability report with:

342

- Styled tables and layouts

343

- Interactive filtering

344

- Sortable columns

345

- Embedded CSS and JavaScript

346

"""

347

```

348

349

**HTML Report Features:**

350

351

- **Responsive Design**: Mobile and desktop compatible

352

- **Interactive Tables**: Sortable and filterable vulnerability lists

353

- **Severity Styling**: Color-coded severity indicators

354

- **Embedded Assets**: Self-contained HTML files

355

- **Print Optimized**: Clean printing layouts

356

357

### Bare Formatter { .api }

358

359

#### BareReport Class { .api }

360

361

**Description**: Minimal formatter for machine processing and scripting integration.

362

363

```python

364

class BareReport(FormatterAPI):

365

"""Minimal formatter for machine processing and automation."""

366

367

def render_vulnerabilities(self, ...) -> str:

368

"""

369

Generate minimal vulnerability output:

370

- One vulnerability per line

371

- Tab or delimiter-separated fields

372

- No headers or formatting

373

- Suitable for grep, awk, etc.

374

"""

375

376

def render_licenses(self, ...) -> str:

377

"""Generate minimal license output."""

378

```

379

380

**Bare Output Format:**

381

382

```

383

package_name\tvulnerability_id\tseverity\tinstalled_version\tfixed_version

384

requests\tVULN-12345\thigh\t2.20.0\t2.20.1

385

django\tVULN-67890\tcritical\t3.0.0\t3.0.14

386

```

387

388

## Data Encoding and Serialization

389

390

### SafetyEncoder { .api }

391

392

**Description**: Custom JSON encoder for Safety-specific data types and models.

393

394

```python

395

from safety.models import SafetyEncoder

396

397

class SafetyEncoder(json.JSONEncoder):

398

"""Custom JSON encoder for Safety data structures."""

399

400

def default(self, obj: Any) -> Any:

401

"""

402

Serialize Safety-specific objects to JSON-compatible formats.

403

404

Handles:

405

- Vulnerability objects

406

- Package objects

407

- DateTime objects

408

- Custom data classes

409

410

Args:

411

obj: Object to serialize

412

413

Returns:

414

Any: JSON-serializable representation

415

"""

416

```

417

418

**Example Usage:**

419

420

```python

421

import json

422

from safety.models import SafetyEncoder

423

424

# Serialize vulnerability data with custom encoder

425

vulnerability_data = {...} # Vulnerability objects

426

json_output = json.dumps(

427

vulnerability_data,

428

cls=SafetyEncoder,

429

indent=2

430

)

431

```

432

433

## Output Utilities and Helpers

434

435

### Report Brief Information { .api }

436

437

```python

438

from safety.output_utils import get_report_brief_info, should_add_nl

439

440

def get_report_brief_info(

441

as_dict: bool = False, # Return as dictionary

442

report_type: int = 1, # Report type identifier

443

vulnerabilities_found: int = 0, # Number of vulnerabilities

444

vulnerabilities_ignored: int = 0, # Number ignored

445

remediations_recommended: Dict = None # Remediation suggestions

446

) -> Union[str, Dict[str, Any]]:

447

"""

448

Generate brief report summary information.

449

450

Args:

451

as_dict: Return structured data instead of formatted string

452

report_type: Type of report (1=vulnerability, 2=license, etc.)

453

vulnerabilities_found: Count of active vulnerabilities

454

vulnerabilities_ignored: Count of ignored vulnerabilities

455

remediations_recommended: Available remediation options

456

457

Returns:

458

Union[str, Dict]: Brief report summary

459

"""

460

461

def should_add_nl(console_output: str) -> bool:

462

"""

463

Determine if newline should be added to console output.

464

465

Args:

466

console_output (str): Console output string

467

468

Returns:

469

bool: True if newline should be added

470

"""

471

```

472

473

## Schema Versioning { .api }

474

475

### Report Schemas { .api }

476

477

Safety supports versioned report schemas for backward compatibility:

478

479

```python

480

from safety.formatters.schemas.v3_0 import ScanReportV30

481

482

class ScanReportV30(BaseModel):

483

"""Pydantic model for v3.0 scan report schema."""

484

485

report_meta: ReportMeta # Report metadata

486

vulnerabilities: List[VulnerabilityModel] # Vulnerability findings

487

ignored_vulnerabilities: List[VulnerabilityModel] # Ignored vulnerabilities

488

remediations: Dict[str, Any] # Remediation suggestions

489

packages: List[PackageModel] # Scanned packages

490

announcements: List[AnnouncementModel] # Platform announcements

491

```

492

493

## Configuration and Customization

494

495

### Formatter Configuration { .api }

496

497

Formatters can be configured through various options:

498

499

```python

500

# JSON formatter with specific version

501

json_formatter = SafetyFormatter(

502

output='json',

503

version='3.0',

504

indent=4,

505

sort_keys=True

506

)

507

508

# HTML formatter with custom templates

509

html_formatter = SafetyFormatter(

510

output='html',

511

template_dir='/path/to/custom/templates',

512

theme='dark',

513

include_css=True

514

)

515

516

# Screen formatter with custom console

517

from rich.console import Console

518

custom_console = Console(width=120, theme='github-dark')

519

520

screen_formatter = SafetyFormatter(

521

output='screen',

522

console=custom_console,

523

emoji=False

524

)

525

```

526

527

### Template Customization { .api }

528

529

HTML formatter supports custom Jinja2 templates:

530

531

```html

532

<!-- Custom vulnerability report template -->

533

<!DOCTYPE html>

534

<html>

535

<head>

536

<title>{{ report_title }} - Security Report</title>

537

<style>{{ embedded_css }}</style>

538

</head>

539

<body>

540

<h1>{{ report_title }}</h1>

541

542

{% if vulnerabilities %}

543

<table class="vulnerabilities">

544

<thead>

545

<tr>

546

<th>Package</th>

547

<th>Vulnerability</th>

548

<th>Severity</th>

549

<th>Fixed Version</th>

550

</tr>

551

</thead>

552

<tbody>

553

{% for vuln in vulnerabilities %}

554

<tr class="severity-{{ vuln.severity.lower() }}">

555

<td>{{ vuln.package_name }}</td>

556

<td>{{ vuln.vulnerability_id }}</td>

557

<td>{{ vuln.severity }}</td>

558

<td>{{ vuln.fixed_versions|join(', ') }}</td>

559

</tr>

560

{% endfor %}

561

</tbody>

562

</table>

563

{% endif %}

564

</body>

565

</html>

566

```

567

568

## Usage Examples

569

570

### Basic Report Generation

571

572

```python

573

from safety.formatter import SafetyFormatter

574

575

# Sample data

576

vulnerabilities = [...] # Vulnerability objects

577

packages = [...] # Package objects

578

announcements = [...] # Announcement objects

579

remediations = {...} # Remediation suggestions

580

581

# Generate JSON report

582

json_formatter = SafetyFormatter(output='json')

583

json_report = json_formatter.render_vulnerabilities(

584

announcements=announcements,

585

vulnerabilities=vulnerabilities,

586

remediations=remediations,

587

full=True,

588

packages=packages

589

)

590

591

# Save to file

592

with open('security-report.json', 'w') as f:

593

f.write(json_report)

594

```

595

596

### Multi-Format Reporting

597

598

```python

599

from safety.formatter import SafetyFormatter

600

601

# Generate reports in multiple formats

602

formats = ['json', 'html', 'text']

603

reports = {}

604

605

for format_type in formats:

606

formatter = SafetyFormatter(output=format_type)

607

reports[format_type] = formatter.render_vulnerabilities(

608

announcements=announcements,

609

vulnerabilities=vulnerabilities,

610

remediations=remediations,

611

full=True,

612

packages=packages

613

)

614

615

# Save each format

616

for format_type, content in reports.items():

617

filename = f'security-report.{format_type}'

618

with open(filename, 'w') as f:

619

f.write(content)

620

```

621

622

### License Reporting

623

624

```python

625

# Generate license compliance report

626

license_data = [...] # License information

627

628

formatter = SafetyFormatter(output='html')

629

license_report = formatter.render_licenses(

630

announcements=announcements,

631

licenses=license_data

632

)

633

634

# Display in terminal

635

formatter = SafetyFormatter(output='screen')

636

terminal_output = formatter.render_licenses(

637

announcements=announcements,

638

licenses=license_data

639

)

640

print(terminal_output)

641

```

642

643

### Custom JSON Processing

644

645

```python

646

from safety.formatters.json import build_json_report

647

import json

648

649

# Build structured report data

650

report_data = build_json_report(

651

announcements=announcements,

652

vulnerabilities=vulnerabilities,

653

remediations=remediations,

654

packages=packages

655

)

656

657

# Custom processing

658

report_data['custom_metadata'] = {

659

'scan_time': datetime.now().isoformat(),

660

'project_name': 'my-project',

661

'environment': 'production'

662

}

663

664

# Serialize with custom options

665

json_output = json.dumps(

666

report_data,

667

cls=SafetyEncoder,

668

indent=2,

669

sort_keys=True,

670

ensure_ascii=False

671

)

672

```

673

674

This comprehensive formatter documentation covers all aspects of Safety CLI's output and formatting system, enabling developers to generate reports in their preferred format and integrate security scanning results into their workflows and tooling.