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

scanning.mddocs/

0

# Scanning and Analysis

1

2

Safety CLI provides comprehensive vulnerability scanning and analysis capabilities for Python projects. The scanning system supports multiple ecosystems, file types, and analysis modes.

3

4

## Core Scanning Architecture

5

6

### File Discovery and Processing { .api }

7

8

The scanning system uses a modular architecture to discover and process dependency files:

9

10

**Import Statements:**

11

12

```python

13

from safety.scan.main import process_files, download_policy, load_policy_file

14

from safety.scan.finder import FileFinder

15

from safety.scan.ecosystems.base import InspectableFile, Inspectable, Remediable

16

from safety.scan.models import ScanExport

17

from safety_schemas.models import (

18

ConfigModel, FileType, PolicyFileModel,

19

ScanType, Stage, Ecosystem

20

)

21

```

22

23

#### FileFinder Class { .api }

24

25

**Description**: Discovers dependency files in project directories based on ecosystem and file type patterns.

26

27

**Constructor:**

28

29

```python

30

FileFinder(

31

max_level: int, # Maximum directory depth

32

ecosystems: List[Ecosystem], # Target ecosystems

33

target: Path, # Root directory to scan

34

live_status=None, # Progress status object

35

exclude: Optional[List[str]] = None, # Exclusion patterns

36

include_files: Optional[Dict[FileType, List[Path]]] = None, # Specific files

37

handlers: Optional[Set[FileHandler]] = None # Custom file handlers

38

)

39

```

40

41

**Methods:**

42

43

```python

44

def process_directory(

45

self,

46

dir_path: str,

47

max_deep: Optional[int] = None

48

) -> Tuple[str, Dict[str, Set[Path]]]

49

"""

50

Process directory and discover dependency files.

51

52

Args:

53

dir_path (str): Directory path to process

54

max_deep (Optional[int]): Maximum depth override

55

56

Returns:

57

Tuple[str, Dict[str, Set[Path]]]: Directory info and discovered files

58

"""

59

60

def should_exclude(

61

excludes: Set[Path],

62

to_analyze: Path

63

) -> bool

64

"""

65

Determine if path should be excluded from analysis.

66

67

Args:

68

excludes (Set[Path]): Set of exclusion paths

69

to_analyze (Path): Path to check

70

71

Returns:

72

bool: True if path should be excluded

73

"""

74

```

75

76

**Example Usage:**

77

78

```python

79

from safety.scan.finder import FileFinder

80

from safety_schemas.models import Ecosystem

81

from pathlib import Path

82

83

# Initialize file finder

84

finder = FileFinder(

85

max_level=10,

86

ecosystems=[Ecosystem.PYTHON],

87

target=Path("."),

88

exclude=["node_modules", ".git", "__pycache__"]

89

)

90

91

# Process directory

92

project_info, discovered_files = finder.process_directory("./my_project")

93

```

94

95

### File Processing Engine { .api }

96

97

#### process_files Function { .api }

98

99

**Description**: Main processing function that analyzes discovered dependency files and generates inspectable file objects.

100

101

**Signature:**

102

103

```python

104

def process_files(

105

paths: Dict[str, Set[Path]], # Discovered file paths by type

106

config: Optional[ConfigModel] = None, # Scan configuration

107

use_server_matching: bool = False, # Use server-side analysis

108

obj=None, # Context object

109

target: Path = Path(".") # Project root path

110

) -> Generator[Tuple[Path, InspectableFile], None, None]

111

"""

112

Process dependency files and yield inspectable file objects.

113

114

Args:

115

paths: Dictionary of file paths organized by file type

116

config: Configuration model for analysis settings

117

use_server_matching: Enable server-side vulnerability matching

118

obj: Context object with authentication and settings

119

target: Root directory path

120

121

Yields:

122

Tuple[Path, InspectableFile]: File path and corresponding inspectable file

123

"""

124

```

125

126

**Processing Modes:**

127

128

1. **Local Processing** (`use_server_matching=False`):

129

- Files processed locally using built-in analyzers

130

- Immediate dependency extraction and vulnerability matching

131

- Offline capability with cached vulnerability database

132

133

2. **Server Processing** (`use_server_matching=True`):

134

- Files uploaded to Safety platform for analysis

135

- Enhanced vulnerability intelligence and matching

136

- Requires authentication with Safety platform

137

138

**Example Usage:**

139

140

```python

141

from safety.scan.main import process_files

142

from safety_schemas.models import ConfigModel

143

144

# Configure scan settings

145

config = ConfigModel(

146

telemetry_enabled=True

147

)

148

149

# Process discovered files

150

for file_path, inspectable_file in process_files(

151

paths=discovered_files,

152

config=config,

153

use_server_matching=True,

154

target=Path(".")

155

):

156

# Access vulnerability results

157

results = inspectable_file.inspect(config=config)

158

print(f"File: {file_path}")

159

print(f"Dependencies: {len(results.dependencies)}")

160

print(f"Vulnerabilities: {len(results.vulnerabilities)}")

161

```

162

163

### Inspectable Files Interface { .api }

164

165

#### InspectableFile Class { .api }

166

167

**Description**: Represents a dependency file that can be analyzed for vulnerabilities and remediated.

168

169

**Base Classes:**

170

171

```python

172

class Inspectable(ABC):

173

@abstractmethod

174

def inspect(self, config: ConfigModel) -> DependencyResultModel:

175

"""Analyze file for dependencies and vulnerabilities."""

176

177

class Remediable(ABC):

178

@abstractmethod

179

def remediate(self):

180

"""Apply automatic fixes to detected vulnerabilities."""

181

```

182

183

**InspectableFile Interface:**

184

185

```python

186

class InspectableFile(Inspectable):

187

file_type: FileType # Type of dependency file

188

ecosystem: Ecosystem # Target ecosystem (Python, etc.)

189

190

def inspect(self, config: ConfigModel) -> DependencyResultModel:

191

"""

192

Analyze file for dependencies and vulnerabilities.

193

194

Args:

195

config: Configuration model with scan settings

196

197

Returns:

198

DependencyResultModel: Analysis results with dependencies and vulnerabilities

199

"""

200

201

def remediate(self) -> None:

202

"""

203

Apply automatic remediation to fix detected vulnerabilities.

204

Modifies dependency specifications to use secure versions.

205

"""

206

```

207

208

## Policy Management { .api }

209

210

### Policy File Loading

211

212

#### load_policy_file Function { .api }

213

214

**Description**: Load and validate Safety policy files from local filesystem.

215

216

**Signature:**

217

218

```python

219

def load_policy_file(path: Path) -> Optional[PolicyFileModel]:

220

"""

221

Load policy file from specified path.

222

223

Args:

224

path (Path): Path to policy file (.safety-policy.yml)

225

226

Returns:

227

Optional[PolicyFileModel]: Parsed policy model or None if invalid

228

229

Raises:

230

SafetyError: If policy file is invalid or unsupported version

231

"""

232

```

233

234

#### download_policy Function { .api }

235

236

**Description**: Download policy files from Safety platform for authenticated users.

237

238

**Signature:**

239

240

```python

241

def download_policy(

242

session: SafetyAuthSession, # Authenticated session

243

project_id: str, # Project identifier

244

stage: Stage, # Environment stage

245

branch: Optional[str] # Git branch name

246

) -> Optional[PolicyFileModel]:

247

"""

248

Download policy file from Safety platform.

249

250

Args:

251

session: Authenticated Safety session

252

project_id: Unique project identifier

253

stage: Development stage (development, production, etc.)

254

branch: Git branch for branch-specific policies

255

256

Returns:

257

Optional[PolicyFileModel]: Downloaded policy model

258

259

Raises:

260

SafetyError: If download fails or policy is invalid

261

"""

262

```

263

264

### Policy Models { .api }

265

266

```python

267

from safety_schemas.models import PolicyFileModel, PolicySource, Stage

268

269

class PolicyFileModel:

270

id: str # Policy identifier

271

source: PolicySource # Source (local, cloud)

272

location: Optional[Path] # Local file path

273

config: ConfigModel # Policy configuration

274

275

class PolicySource(Enum):

276

LOCAL = "local" # Local policy file

277

CLOUD = "cloud" # Platform policy

278

279

class Stage(Enum):

280

DEVELOPMENT = "development"

281

TESTING = "testing"

282

STAGING = "staging"

283

PRODUCTION = "production"

284

```

285

286

## Scan Configuration { .api }

287

288

### ConfigModel { .api }

289

290

**Description**: Central configuration model for scan behavior and policies.

291

292

```python

293

from safety_schemas.models import ConfigModel

294

295

class ConfigModel:

296

telemetry_enabled: bool = True # Enable usage telemetry

297

298

# Vulnerability filtering

299

ignore_vulnerabilities: List[str] = [] # Vulnerability IDs to ignore

300

ignore_unpinned_requirements: bool = False # Ignore unpinned dependencies

301

302

# Severity filtering

303

minimum_severity: Optional[str] = None # Minimum severity level

304

305

# Output configuration

306

output_format: str = "screen" # Output format preference

307

detailed_output: bool = False # Include detailed information

308

309

# Auto-remediation settings

310

auto_remediation_limit: Optional[int] = None # Max automatic fixes

311

continue_on_error: bool = False # Continue despite errors

312

313

@classmethod

314

def parse_policy_file(cls, raw_report: Path) -> "ConfigModel":

315

"""

316

Parse policy file and create configuration model.

317

318

Args:

319

raw_report (Path): Path to policy YAML file

320

321

Returns:

322

ConfigModel: Parsed configuration

323

324

Raises:

325

ValidationError: If policy file is invalid

326

"""

327

328

@classmethod

329

def from_v30(cls, obj) -> "ConfigModel":

330

"""

331

Create ConfigModel from v3.0 policy format.

332

333

Args:

334

obj: v3.0 format policy object

335

336

Returns:

337

ConfigModel: Converted configuration

338

"""

339

```

340

341

## Ecosystem Support { .api }

342

343

### Supported Ecosystems

344

345

```python

346

from safety_schemas.models import Ecosystem, FileType

347

348

class Ecosystem(Enum):

349

PYTHON = "python" # Python packages and requirements

350

# Additional ecosystems may be added in future versions

351

352

class FileType(Enum):

353

# Python ecosystem file types

354

REQUIREMENTS_TXT = "requirements.txt" # pip requirements files

355

PIPFILE = "Pipfile" # Pipenv files

356

PIPFILE_LOCK = "Pipfile.lock" # Pipenv lock files

357

PYPROJECT_TOML = "pyproject.toml" # PEP 518 project files

358

POETRY_LOCK = "poetry.lock" # Poetry lock files

359

SETUP_PY = "setup.py" # setuptools setup files

360

SETUP_CFG = "setup.cfg" # setuptools configuration

361

362

@property

363

def ecosystem(self) -> Optional[Ecosystem]:

364

"""Get the ecosystem associated with this file type."""

365

```

366

367

### File Handler Architecture { .api }

368

369

```python

370

from safety.scan.finder.handlers import FileHandler, ECOSYSTEM_HANDLER_MAPPING

371

372

class FileHandler(ABC):

373

"""Abstract base class for ecosystem-specific file handlers."""

374

375

@abstractmethod

376

def can_handle(self, file_path: Path) -> bool:

377

"""Determine if handler can process the given file."""

378

379

@abstractmethod

380

def process(self, file_path: Path) -> Set[FileType]:

381

"""Process file and return supported file types."""

382

383

# Handler mapping

384

ECOSYSTEM_HANDLER_MAPPING: Dict[Ecosystem, Type[FileHandler]] = {

385

Ecosystem.PYTHON: PythonHandler,

386

# Additional handlers for future ecosystems

387

}

388

```

389

390

## Scan Export and Results { .api }

391

392

### ScanExport Types { .api }

393

394

```python

395

from safety.scan.models import ScanExport

396

397

class ScanExport(Enum):

398

JSON = "json" # JSON format export

399

HTML = "html" # HTML report export

400

TEXT = "text" # Plain text export

401

SPDX = "spdx" # SPDX format (with spdx extra)

402

```

403

404

### Result Data Models { .api }

405

406

```python

407

from safety_schemas.models import DependencyResultModel

408

409

class DependencyResultModel:

410

"""Results from dependency analysis and vulnerability scanning."""

411

412

dependencies: List[DependencyModel] # Discovered dependencies

413

vulnerabilities: List[VulnerabilityModel] # Found vulnerabilities

414

metadata: Dict[str, Any] # Additional metadata

415

416

class DependencyModel:

417

"""Individual dependency information."""

418

419

name: str # Package name

420

version: str # Package version

421

ecosystem: Ecosystem # Package ecosystem

422

file_path: Path # Source file path

423

424

class VulnerabilityModel:

425

"""Vulnerability information for dependencies."""

426

427

vulnerability_id: str # Unique vulnerability ID

428

package_name: str # Affected package

429

severity: str # Vulnerability severity

430

advisory: str # Vulnerability description

431

fixed_versions: List[str] # Versions with fixes

432

```

433

434

## Advanced Scanning Features

435

436

### Git Integration { .api }

437

438

```python

439

from safety.scan.util import GIT

440

441

# Git metadata extraction for enhanced reporting

442

def build_meta(target: Path) -> Dict[str, Any]:

443

"""

444

Build metadata for scan context including Git information.

445

446

Args:

447

target (Path): Project root directory

448

449

Returns:

450

Dict[str, Any]: Metadata including Git branch, commit, etc.

451

"""

452

```

453

454

### Encoding Detection { .api }

455

456

```python

457

from safety.encoding import detect_encoding

458

459

def detect_encoding(file_path: Path) -> str:

460

"""

461

Detect file encoding for proper text processing.

462

463

Args:

464

file_path (Path): Path to file for encoding detection

465

466

Returns:

467

str: Detected encoding (e.g., 'utf-8', 'latin-1')

468

"""

469

```

470

471

## Usage Examples

472

473

### Basic Project Scan

474

475

```python

476

from safety.scan.finder import FileFinder

477

from safety.scan.main import process_files

478

from safety_schemas.models import Ecosystem, ConfigModel

479

from pathlib import Path

480

481

# Configure scan

482

config = ConfigModel(

483

telemetry_enabled=False,

484

detailed_output=True,

485

auto_remediation_limit=5

486

)

487

488

# Discover files

489

finder = FileFinder(

490

max_level=5,

491

ecosystems=[Ecosystem.PYTHON],

492

target=Path("./my_project"),

493

exclude=[".venv", ".git", "node_modules"]

494

)

495

496

_, discovered_files = finder.process_directory("./my_project")

497

498

# Process and analyze

499

vulnerabilities_found = []

500

for file_path, inspectable_file in process_files(

501

paths=discovered_files,

502

config=config,

503

target=Path("./my_project")

504

):

505

results = inspectable_file.inspect(config=config)

506

if results.vulnerabilities:

507

vulnerabilities_found.extend(results.vulnerabilities)

508

509

# Apply automatic remediation

510

inspectable_file.remediate()

511

512

print(f"Found {len(vulnerabilities_found)} vulnerabilities")

513

```

514

515

### Policy-Based Scanning

516

517

```python

518

from safety.scan.main import load_policy_file, download_policy

519

from safety.auth.utils import SafetyAuthSession

520

521

# Load local policy

522

policy = load_policy_file(Path("./.safety-policy.yml"))

523

524

if policy:

525

config = policy.config

526

else:

527

# Download from platform (requires authentication)

528

session = SafetyAuthSession()

529

policy = download_policy(

530

session=session,

531

project_id="my-project-id",

532

stage=Stage.PRODUCTION,

533

branch="main"

534

)

535

config = policy.config if policy else ConfigModel()

536

537

# Use policy configuration for scanning

538

for file_path, inspectable_file in process_files(

539

paths=discovered_files,

540

config=config

541

):

542

results = inspectable_file.inspect(config=config)

543

# Process results according to policy

544

```

545

546

### Custom File Inclusion

547

548

```python

549

from safety_schemas.models import FileType

550

551

# Include specific files in scan

552

include_files = {

553

FileType.REQUIREMENTS_TXT: [

554

Path("./requirements.txt"),

555

Path("./requirements-dev.txt")

556

],

557

FileType.PYPROJECT_TOML: [

558

Path("./pyproject.toml")

559

]

560

}

561

562

finder = FileFinder(

563

max_level=1,

564

ecosystems=[Ecosystem.PYTHON],

565

target=Path("."),

566

include_files=include_files

567

)

568

```

569

570

This comprehensive scanning documentation covers all aspects of Safety CLI's vulnerability scanning and analysis capabilities, enabling developers to integrate sophisticated dependency security checks into their development workflows.