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
# Ecosystem Rules Configuration for sbom-tools
#
# This file configures how package names are normalized and matched
# across different ecosystems (npm, PyPI, Cargo, Maven, Go, etc.)
#
# File locations (in order of precedence):
# 1. CLI argument: --ecosystem-rules <path>
# 2. Environment variable: SBOM_TOOLS_ECOSYSTEM_RULES
# 3. Project local: .sbom-tools/ecosystem-rules.yaml
# 4. User config: ~/.config/sbom-tools/ecosystem-rules.yaml
version: "1.0"
# Global settings
settings:
# Default case sensitivity for ecosystems without explicit setting
case_sensitive_default: false
# Normalize unicode characters (e.g., fancy quotes to ASCII)
normalize_unicode: true
# Enable security checks (typosquat detection, suspicious patterns)
enable_security_checks: true
# Per-ecosystem configuration
ecosystems:
# Python Package Index
pypi:
normalization:
case_sensitive: false
# Characters that are considered equivalent: foo-bar == foo_bar == foo.bar
equivalent_chars:
-
collapse_separators: true
# Prefixes to strip for fuzzy matching
strip_prefixes:
- "python-"
- "py-"
- "lib"
# Suffixes to strip for fuzzy matching
strip_suffixes:
- "-python"
- "-py"
- "-py3"
- "-lib"
# Known package aliases (distribution vs import name)
aliases:
pillow:
scikit-learn:
beautifulsoup4:
pyyaml:
opencv-python:
# Version handling
versioning:
spec: pep440
prerelease_tags:
# Security checks
security:
known_typosquats:
- malicious: "python-dateutils"
legitimate: "python-dateutil"
description: "Common typosquat"
- malicious: "request"
legitimate: "requests"
description: "Missing 's' typosquat"
# npm (Node.js)
npm:
normalization:
case_sensitive: false
# Preserve scope case: @Angular/Core -> @angular/core
scope_handling: preserve_scope_case
strip_prefixes:
- "node-"
- "@types/"
strip_suffixes:
- "-js"
- ".js"
- "-node"
# Package groups for monorepos
package_groups:
lodash:
canonical: "lodash"
members:
- "lodash-es"
- "lodash.merge"
- "lodash.get"
- "lodash.set"
babel:
canonical: "@babel/core"
members:
- "@babel/*"
react:
canonical: "react"
members:
- "react-dom"
- "react-router"
versioning:
spec: semver
prerelease_tags:
security:
suspicious_patterns:
# Very short package names are often typosquats
- "^[a-z]{1,2}$"
# Rust (crates.io)
cargo:
normalization:
case_sensitive: false
# Hyphens and underscores are equivalent: serde-json == serde_json
equivalent_chars:
-
strip_prefixes:
- "rust-"
- "lib"
strip_suffixes:
- "-rs"
- "-rust"
versioning:
spec: semver
# Maven (Java)
maven:
normalization:
case_sensitive: true
# Use full coordinate (groupId:artifactId)
use_full_coordinate: true
# Group ID migrations (e.g., javax -> jakarta)
group_migrations:
- from: "javax.*"
to: "jakarta.*"
after_version: "9"
versioning:
spec: maven
qualifier_order:
# Go modules
golang:
normalization:
case_sensitive: true
# Strip /v2, /v3 version suffixes
strip_version_suffix: true
import_mappings:
- pattern: "github.com/*/*"
type: github
- pattern: "golang.org/x/*"
type: stdlib_extension
versioning:
spec: gomod
# Cross-ecosystem package mappings
# Map equivalent packages across different ecosystems
cross_ecosystem:
yaml_parsing:
pypi: "pyyaml"
npm: "js-yaml"
cargo: "serde_yaml"
golang: "gopkg.in/yaml.v3"
rubygems: "psych"
http_client:
pypi: "requests"
npm: "axios"
cargo: "reqwest"
rubygems: "faraday"
testing:
pypi: "pytest"
npm: "jest"
rubygems: "rspec"
# Organization-specific custom rules
custom_rules:
# Internal package prefixes (for private packages)
internal_prefixes:
- "@mycompany/"
- "mycompany-"
- "com.mycompany:"
# Custom equivalences (treat these packages as the same)
equivalences:
- canonical: "pkg:npm/@mycompany/logger"
aliases:
- "pkg:npm/mycompany-logger"
- "pkg:pypi/mycompany-logger"
version_sensitive: false
# Packages to always ignore in diffs
ignored_packages:
- "internal-test-utils"
- "dev-tools"