0
# Configuration and Policies
1
2
Safety CLI provides comprehensive configuration management through policy files, environment variables, and command-line options. The policy system allows centralized security configuration and consistent vulnerability handling across teams and environments.
3
4
## Policy File System
5
6
### Policy File Structure { .api }
7
8
**Import Statements:**
9
10
```python
11
from safety.scan.main import load_policy_file, download_policy, resolve_policy
12
from safety.util import SafetyPolicyFile, initialize_config_dirs
13
from safety_schemas.models import (
14
ConfigModel, PolicyFileModel, PolicySource, Stage
15
)
16
from safety.constants import get_config_setting
17
```
18
19
#### PolicyFileModel { .api }
20
21
**Description**: Represents a Safety policy file with metadata and configuration.
22
23
```python
24
from safety_schemas.models import PolicyFileModel, PolicySource
25
26
class PolicyFileModel:
27
"""Safety policy file representation with source tracking."""
28
29
id: str # Policy identifier (UUID for cloud policies)
30
source: PolicySource # Policy source (local or cloud)
31
location: Optional[Path] # Local file path (for local policies)
32
config: ConfigModel # Parsed policy configuration
33
34
class PolicySource(Enum):
35
"""Policy file source types."""
36
LOCAL = "local" # Local filesystem policy
37
CLOUD = "cloud" # Platform-hosted policy
38
```
39
40
#### Policy File Loading { .api }
41
42
```python
43
def load_policy_file(path: Path) -> Optional[PolicyFileModel]:
44
"""
45
Load and validate a local policy file.
46
47
Args:
48
path (Path): Path to .safety-policy.yml file
49
50
Returns:
51
Optional[PolicyFileModel]: Parsed policy or None if invalid
52
53
Raises:
54
SafetyError: If policy file is malformed or unsupported version
55
"""
56
57
def download_policy(
58
session: SafetyAuthSession, # Authenticated session
59
project_id: str, # Project identifier
60
stage: Stage, # Target stage
61
branch: Optional[str] # Git branch name
62
) -> Optional[PolicyFileModel]:
63
"""
64
Download policy from Safety platform.
65
66
Args:
67
session: Authenticated Safety session
68
project_id: Project UUID from Safety platform
69
stage: Environment stage for policy
70
branch: Git branch for branch-specific policies
71
72
Returns:
73
Optional[PolicyFileModel]: Downloaded policy or None
74
75
Raises:
76
SafetyError: If download fails or policy is invalid
77
"""
78
79
def resolve_policy(
80
policy_file_path: Optional[Path], # Local policy file path
81
session: SafetyAuthSession, # Authenticated session
82
project_config: Optional[Dict] = None # Project configuration
83
) -> Optional[PolicyFileModel]:
84
"""
85
Resolve policy with precedence: platform > local > default.
86
87
Args:
88
policy_file_path: Path to local policy file
89
session: Authenticated session for platform policies
90
project_config: Project configuration with ID and stage
91
92
Returns:
93
Optional[PolicyFileModel]: Resolved policy configuration
94
"""
95
```
96
97
### Default Policy File Location { .api }
98
99
Safety CLI looks for policy files in the following order:
100
101
1. **Command-line specified**: `--policy-file path/to/policy.yml`
102
2. **Current directory**: `./.safety-policy.yml`
103
3. **Platform policy**: Downloaded based on project configuration
104
4. **Default configuration**: Built-in safe defaults
105
106
```python
107
# Default policy file locations
108
DEFAULT_POLICY_LOCATIONS = [
109
"./.safety-policy.yml", # Current directory
110
"./safety-policy.yml", # Alternative name
111
"./.safety/policy.yml" # Safety config directory
112
]
113
```
114
115
## Policy File Format
116
117
### Complete Policy File Example { .api }
118
119
```yaml
120
# .safety-policy.yml
121
# Safety Security and License Configuration
122
123
# Project association (for Safety platform integration)
124
project:
125
id: "12345678-1234-1234-1234-123456789abc" # Project UUID from Safety platform
126
127
organization:
128
id: "org-12345" # Organization identifier
129
name: "My Company" # Organization display name
130
131
# Security vulnerability configuration
132
security:
133
# Ignore unpinned requirements (like "requests" or "django>=2.2")
134
ignore-unpinned-requirements: true
135
136
# CVSS severity threshold (0-10 scale)
137
# 9 = Critical only, 7 = Critical & High, 4 = Critical, High & Medium
138
ignore-cvss-severity-below: 7
139
140
# Whether to ignore vulnerabilities with unknown CVSS scores
141
ignore-cvss-unknown-severity: false
142
143
# Continue execution even when vulnerabilities are found
144
continue-on-vulnerability-error: false
145
146
# Specific vulnerabilities to ignore (with optional expiration)
147
ignore-vulnerabilities:
148
25853: # Vulnerability ID
149
reason: "We don't use the vulnerable function"
150
expires: "2024-12-31" # ISO date when ignore expires
151
152
67890:
153
reason: "False positive - not exploitable in our use case"
154
expires: "2024-06-01"
155
156
# License compliance configuration
157
license:
158
# Ignore license issues for unpinned requirements
159
ignore-unpinned-requirements: true
160
161
# Allowed licenses (whitelist approach)
162
allowed-licenses:
163
- "MIT"
164
- "BSD-3-Clause"
165
- "Apache-2.0"
166
- "ISC"
167
168
# Prohibited licenses (blacklist approach)
169
prohibited-licenses:
170
- "GPL-3.0"
171
- "AGPL-3.0"
172
173
# Continue execution despite license issues
174
continue-on-license-error: false
175
176
# Alerting configuration (for GitHub/GitLab integration)
177
alert:
178
security:
179
github-issue:
180
# CVSS severity threshold for alerts
181
ignore-cvss-severity-below: 6
182
ignore-cvss-unknown-severity: false
183
184
# Add severity labels to issues
185
label-severity: true
186
187
# Custom labels for security issues
188
labels:
189
- "security"
190
- "vulnerability"
191
192
# Auto-assign users to security issues
193
assignees:
194
- "security-team"
195
- "dev-lead"
196
197
# Prefix for issue titles
198
issue-prefix: "[Security Alert] "
199
200
# Scan configuration
201
scan:
202
# Maximum depth for dependency tree scanning
203
max-depth: 10
204
205
# File patterns to exclude from scanning
206
exclude:
207
- "test_*"
208
- "*/tests/*"
209
- ".venv/*"
210
- "node_modules/*"
211
212
# Auto-remediation settings
213
auto-remediation:
214
enabled: true
215
max-fixes: 5 # Maximum automatic fixes to apply
216
217
# Output preferences
218
output:
219
detailed: true # Include detailed vulnerability information
220
show-source: true # Show where vulnerabilities were found
221
```
222
223
### Policy Validation { .api }
224
225
```python
226
from safety.cli import validate
227
228
def validate_policy_file(name: str, version: str, path: Path) -> bool:
229
"""
230
Validate policy file syntax and configuration.
231
232
CLI Usage:
233
safety validate policy_name 1.0 --path ./policies/
234
235
Args:
236
name (str): Policy name identifier
237
version (str): Policy version string
238
path (Path): Directory containing policy file
239
240
Returns:
241
bool: True if policy is valid
242
243
Raises:
244
ValidationError: If policy contains errors
245
SafetyError: If policy file cannot be parsed
246
"""
247
```
248
249
## Configuration Models
250
251
### ConfigModel { .api }
252
253
**Description**: Central configuration model that represents parsed policy settings.
254
255
```python
256
from safety_schemas.models import ConfigModel
257
258
class ConfigModel:
259
"""Central configuration for Safety CLI operations."""
260
261
# Core settings
262
telemetry_enabled: bool = True # Enable usage telemetry
263
264
# Vulnerability filtering
265
ignore_vulnerabilities: List[str] = [] # Vulnerability IDs to ignore
266
ignore_unpinned_requirements: bool = False # Skip unpinned dependencies
267
ignore_cvss_severity_below: Optional[float] = None # CVSS threshold
268
ignore_cvss_unknown_severity: bool = False # Ignore unknown severity
269
continue_on_vulnerability_error: bool = False # Continue on vulnerabilities
270
271
# License filtering
272
allowed_licenses: List[str] = [] # Permitted licenses
273
prohibited_licenses: List[str] = [] # Forbidden licenses
274
continue_on_license_error: bool = False # Continue on license issues
275
276
# Auto-remediation
277
auto_remediation_enabled: bool = False # Enable automatic fixes
278
auto_remediation_limit: Optional[int] = None # Maximum fixes to apply
279
280
# Scan configuration
281
max_depth: int = 10 # Dependency tree depth
282
exclude_patterns: List[str] = [] # File exclusion patterns
283
284
# Output preferences
285
detailed_output: bool = False # Include detailed information
286
show_source: bool = True # Show vulnerability sources
287
```
288
289
**Configuration Methods:**
290
291
```python
292
@classmethod
293
def parse_policy_file(cls, raw_report: Path) -> "ConfigModel":
294
"""
295
Parse YAML policy file into configuration model.
296
297
Args:
298
raw_report (Path): Path to policy YAML file
299
300
Returns:
301
ConfigModel: Parsed configuration
302
303
Raises:
304
ValidationError: If YAML is invalid
305
SafetyError: If policy version is unsupported
306
"""
307
308
def save_policy_file(self, path: Path) -> None:
309
"""
310
Save configuration as YAML policy file.
311
312
Args:
313
path (Path): Output file path
314
315
Raises:
316
IOError: If file cannot be written
317
"""
318
319
@classmethod
320
def from_v30(cls, obj) -> "ConfigModel":
321
"""
322
Create configuration from v3.0 policy format.
323
324
Args:
325
obj: v3.0 format policy object
326
327
Returns:
328
ConfigModel: Converted configuration
329
"""
330
```
331
332
## Environment Configuration
333
334
### Environment Variables { .api }
335
336
Safety CLI behavior can be configured through environment variables:
337
338
```bash
339
# Authentication and API
340
SAFETY_API_KEY # Default API key for authentication
341
SAFETY_API_BASE_URL # Override API base URL
342
SAFETY_PLATFORM_URL # Safety platform URL
343
344
# Database and caching
345
SAFETY_DB_DIR # Custom database directory
346
SAFETY_DB_MIRROR # Vulnerability database mirror URL
347
SAFETY_CACHE_DIR # Custom cache directory
348
349
# Proxy configuration
350
SAFETY_PROXY_PROTOCOL # Proxy protocol (http/https)
351
SAFETY_PROXY_HOST # Proxy hostname
352
SAFETY_PROXY_PORT # Proxy port number
353
SAFETY_PROXY_TIMEOUT # Proxy timeout in seconds
354
SAFETY_PROXY_REQUIRED # Require proxy (true/false)
355
356
# Behavior and output
357
SAFETY_OS_DESCRIPTION # Override OS detection
358
SAFETY_PURE_YAML # Use pure YAML parser
359
SAFETY_COLOR # Enable/disable color output
360
SAFETY_NO_EMOJI # Disable emoji in output
361
362
# CI/CD and automation
363
SAFETY_AUDIT_AND_MONITOR # Enable audit mode
364
SAFETY_CONTINUE_ON_ERROR # Continue on vulnerabilities
365
SAFETY_EXIT_CODE # Override exit code behavior
366
```
367
368
**Environment Variable Access:**
369
370
```python
371
from safety.constants import get_config_setting
372
373
# Get configuration setting with fallback
374
api_key = get_config_setting("SAFETY_API_KEY", default=None)
375
proxy_host = get_config_setting("SAFETY_PROXY_HOST", default="")
376
cache_dir = get_config_setting("SAFETY_CACHE_DIR", default="~/.cache/safety")
377
```
378
379
### Configuration Directories { .api }
380
381
```python
382
from safety.util import initialize_config_dirs
383
384
def initialize_config_dirs() -> None:
385
"""
386
Initialize Safety configuration directories.
387
388
Creates necessary directories for:
389
- User configuration (~/.config/safety/)
390
- System configuration (/etc/safety/)
391
- Cache directory (~/.cache/safety/)
392
- Authentication tokens
393
"""
394
```
395
396
**Default Configuration Locations:**
397
398
```bash
399
# Linux/macOS
400
~/.config/safety/ # User configuration
401
~/.cache/safety/ # User cache
402
/etc/safety/ # System configuration
403
404
# Windows
405
%APPDATA%\safety\ # User configuration
406
%LOCALAPPDATA%\safety\ # User cache
407
%PROGRAMDATA%\safety\ # System configuration
408
```
409
410
## Policy Generation
411
412
### Policy File Generation { .api }
413
414
```python
415
from safety.cli import generate_policy_file, generate_installation_policy
416
417
def generate_policy_file(name: str, path: Path) -> None:
418
"""
419
Generate default policy file template.
420
421
CLI Usage:
422
safety generate policy my-project --path ./config/
423
424
Args:
425
name (str): Project name for policy
426
path (Path): Directory to create policy file
427
428
Creates:
429
- .safety-policy.yml with default configuration
430
- Comments explaining each setting
431
- Example ignore configurations
432
"""
433
434
def generate_installation_policy(
435
name: str,
436
path: Path,
437
minimum_cvss_severity: str = "critical"
438
) -> None:
439
"""
440
Generate installation policy for package management.
441
442
CLI Usage:
443
safety generate installation_policy my-project --minimum-cvss-severity high
444
445
Args:
446
name (str): Project name
447
path (Path): Output directory
448
minimum_cvss_severity (str): Minimum severity level
449
450
Creates:
451
- Installation policy with security constraints
452
- Package source restrictions
453
- Vulnerability tolerance settings
454
"""
455
```
456
457
### Policy Templates { .api }
458
459
Safety provides policy templates for common use cases:
460
461
```python
462
# Basic security policy
463
BASIC_SECURITY_POLICY = {
464
"security": {
465
"ignore-cvss-severity-below": 7,
466
"ignore-cvss-unknown-severity": False,
467
"continue-on-vulnerability-error": False
468
}
469
}
470
471
# Strict security policy
472
STRICT_SECURITY_POLICY = {
473
"security": {
474
"ignore-cvss-severity-below": 0, # No tolerance for any severity
475
"ignore-cvss-unknown-severity": False,
476
"continue-on-vulnerability-error": False,
477
"ignore-unpinned-requirements": False
478
}
479
}
480
481
# CI/CD friendly policy
482
CICD_POLICY = {
483
"security": {
484
"ignore-cvss-severity-below": 7,
485
"continue-on-vulnerability-error": True, # Don't fail builds
486
"ignore-unpinned-requirements": True # Allow flexible deps
487
}
488
}
489
```
490
491
## Advanced Configuration
492
493
### Multi-Stage Policies { .api }
494
495
Safety supports different policies for different environments:
496
497
```yaml
498
# production.safety-policy.yml
499
security:
500
ignore-cvss-severity-below: 0 # Strict in production
501
continue-on-vulnerability-error: false
502
auto-remediation:
503
enabled: false # No auto-fixes in prod
504
505
# development.safety-policy.yml
506
security:
507
ignore-cvss-severity-below: 4 # More tolerant in dev
508
continue-on-vulnerability-error: true
509
auto-remediation:
510
enabled: true
511
max-fixes: 10
512
```
513
514
### Organization-Wide Policies { .api }
515
516
Platform-hosted policies provide centralized management:
517
518
```python
519
# Download organization policy
520
from safety.scan.main import download_policy
521
522
policy = download_policy(
523
session=authenticated_session,
524
project_id="my-project-uuid",
525
stage=Stage.PRODUCTION,
526
branch="main"
527
)
528
529
if policy:
530
print(f"Using organization policy: {policy.id}")
531
config = policy.config
532
```
533
534
### Policy Inheritance { .api }
535
536
Policy resolution follows inheritance hierarchy:
537
538
1. **Platform Organization Policy** (highest priority)
539
2. **Platform Project Policy**
540
3. **Local Policy File** (--policy-file or .safety-policy.yml)
541
4. **Default Configuration** (built-in defaults)
542
543
```python
544
# Policy resolution with inheritance
545
def resolve_effective_policy(
546
local_policy_path: Optional[Path],
547
session: SafetyAuthSession,
548
project_config: Dict
549
) -> ConfigModel:
550
"""
551
Resolve effective policy with inheritance.
552
553
Returns merged configuration considering:
554
- Organization defaults
555
- Project overrides
556
- Local customizations
557
- Command-line options
558
"""
559
```
560
561
## Configuration Validation
562
563
### Policy File Validation { .api }
564
565
```python
566
from safety.util import SafetyPolicyFile
567
568
class SafetyPolicyFile(click.ParamType):
569
"""Click parameter type for policy file validation."""
570
571
name = "policy_file"
572
573
def convert(self, value, param, ctx) -> Optional[Path]:
574
"""
575
Validate and convert policy file parameter.
576
577
Args:
578
value: Policy file path string
579
param: Click parameter context
580
ctx: Click context
581
582
Returns:
583
Optional[Path]: Validated policy file path
584
585
Raises:
586
click.BadParameter: If policy file is invalid
587
"""
588
```
589
590
### Configuration Debugging { .api }
591
592
```python
593
# Debug configuration resolution
594
import logging
595
596
logging.getLogger("safety.scan.main").setLevel(logging.DEBUG)
597
598
# Enable debug output for policy loading
599
safety scan --debug # Shows policy resolution process
600
```
601
602
## Usage Examples
603
604
### Basic Policy Setup
605
606
```bash
607
# Generate default policy file
608
safety generate policy my-project
609
610
# Validate policy file
611
safety validate my-project 1.0 --path .
612
613
# Use custom policy file
614
safety scan --policy-file ./config/security-policy.yml
615
```
616
617
### Programmatic Configuration
618
619
```python
620
from safety_schemas.models import ConfigModel
621
from pathlib import Path
622
623
# Create custom configuration
624
config = ConfigModel(
625
ignore_cvss_severity_below=7,
626
continue_on_vulnerability_error=False,
627
auto_remediation_enabled=True,
628
auto_remediation_limit=5
629
)
630
631
# Save as policy file
632
config.save_policy_file(Path(".safety-policy.yml"))
633
634
# Load and modify existing policy
635
policy_path = Path(".safety-policy.yml")
636
if policy_path.exists():
637
config = ConfigModel.parse_policy_file(policy_path)
638
config.ignore_cvss_severity_below = 4 # Make more permissive
639
config.save_policy_file(policy_path)
640
```
641
642
### Environment-Based Configuration
643
644
```python
645
import os
646
from safety.constants import get_config_setting
647
648
# Environment-specific settings
649
if os.getenv("CI"):
650
# CI/CD environment
651
os.environ["SAFETY_CONTINUE_ON_ERROR"] = "true"
652
os.environ["SAFETY_IGNORE_CVSS_SEVERITY_BELOW"] = "7"
653
else:
654
# Development environment
655
os.environ["SAFETY_AUTO_REMEDIATION_ENABLED"] = "true"
656
os.environ["SAFETY_DETAILED_OUTPUT"] = "true"
657
658
# Apply configuration
659
config = ConfigModel(
660
continue_on_vulnerability_error=get_config_setting("SAFETY_CONTINUE_ON_ERROR", False),
661
ignore_cvss_severity_below=float(get_config_setting("SAFETY_IGNORE_CVSS_SEVERITY_BELOW", 0)),
662
detailed_output=get_config_setting("SAFETY_DETAILED_OUTPUT", False)
663
)
664
```
665
666
### Organization Policy Management
667
668
```python
669
from safety.auth.cli_utils import build_client_session
670
from safety.scan.main import download_policy
671
from safety_schemas.models import Stage
672
673
# Authenticate and download organization policy
674
session = build_client_session()
675
676
# Download production policy
677
prod_policy = download_policy(
678
session=session,
679
project_id="project-uuid",
680
stage=Stage.PRODUCTION,
681
branch="main"
682
)
683
684
# Download development policy
685
dev_policy = download_policy(
686
session=session,
687
project_id="project-uuid",
688
stage=Stage.DEVELOPMENT,
689
branch="develop"
690
)
691
692
# Compare policies
693
if prod_policy and dev_policy:
694
prod_config = prod_policy.config
695
dev_config = dev_policy.config
696
697
print(f"Production CVSS threshold: {prod_config.ignore_cvss_severity_below}")
698
print(f"Development CVSS threshold: {dev_config.ignore_cvss_severity_below}")
699
```
700
701
This comprehensive configuration and policy documentation covers all aspects of Safety CLI's configuration system, enabling organizations to implement consistent security policies across their development lifecycle and deployment environments.