oebc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oebc-0.1.0/LICENSE +21 -0
- oebc-0.1.0/PKG-INFO +451 -0
- oebc-0.1.0/README.md +416 -0
- oebc-0.1.0/pyproject.toml +80 -0
- oebc-0.1.0/setup.cfg +4 -0
- oebc-0.1.0/src/oebc/__init__.py +6 -0
- oebc-0.1.0/src/oebc/__main__.py +4 -0
- oebc-0.1.0/src/oebc/cli.py +48 -0
- oebc-0.1.0/src/oebc/fetch.py +24 -0
- oebc-0.1.0/src/oebc/generate.py +305 -0
- oebc-0.1.0/src/oebc/urls.py +17 -0
- oebc-0.1.0/src/oebc.egg-info/PKG-INFO +451 -0
- oebc-0.1.0/src/oebc.egg-info/SOURCES.txt +20 -0
- oebc-0.1.0/src/oebc.egg-info/dependency_links.txt +1 -0
- oebc-0.1.0/src/oebc.egg-info/entry_points.txt +2 -0
- oebc-0.1.0/src/oebc.egg-info/requires.txt +9 -0
- oebc-0.1.0/src/oebc.egg-info/top_level.txt +1 -0
- oebc-0.1.0/tests/test_cli.py +77 -0
- oebc-0.1.0/tests/test_fetch.py +73 -0
- oebc-0.1.0/tests/test_generate.py +511 -0
- oebc-0.1.0/tests/test_schema_validation.py +127 -0
- oebc-0.1.0/tests/test_version.py +8 -0
oebc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Karthikeyan Sadayamuthu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
oebc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oebc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Open Exposure Baseline Catalog — daily CVE exposure baseline enriched with EPSS, KEV, and derived exposure tiers.
|
|
5
|
+
Author: Karthikeyan Sadayamuthu
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://openastra.org
|
|
8
|
+
Project-URL: Source, https://github.com/sadayamuthu/oebc
|
|
9
|
+
Project-URL: Issues, https://github.com/sadayamuthu/oebc/issues
|
|
10
|
+
Project-URL: Catalog, https://openastra.org/oebc/catalog/v0.1/latest.json.gz
|
|
11
|
+
Keywords: cve,epss,kev,vulnerability,exposure,security,nvd
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Security
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: requests>=2.31
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=6.0; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
31
|
+
Requires-Dist: pre-commit>=4.0; extra == "dev"
|
|
32
|
+
Requires-Dist: jsonschema>=4.0; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
|
|
38
|
+
# Open Exposure Baseline Catalog (OEBC)
|
|
39
|
+
|
|
40
|
+
**Machine-Readable CVE Exposure Baseline enriched with EPSS, KEV, and Derived Exposure Tiers**
|
|
41
|
+
|
|
42
|
+
[](https://github.com/sadayamuthu/oebc/actions/workflows/develop.yml)
|
|
43
|
+
[](https://www.python.org/)
|
|
44
|
+
[](LICENSE)
|
|
45
|
+
[](https://openastra.org/oebc/catalog/v0.1/latest.json.gz)
|
|
46
|
+
[](https://openastra.org/oebc/schema/v0.1/oebc.json)
|
|
47
|
+
|
|
48
|
+
[Catalog](#catalog) · [Quick Start](#quick-start) · [CLI](#cli-usage) · [Schema](#output-schema) · [Automation](#automation)
|
|
49
|
+
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## What is OEBC?
|
|
55
|
+
|
|
56
|
+
OEBC is a daily, machine-readable, cloud-agnostic **exposure baseline catalog** derived from three authoritative sources:
|
|
57
|
+
|
|
58
|
+
- **[NVD](https://nvd.nist.gov/)** — CVE descriptions, CVSS scores, CWE IDs, published/modified dates
|
|
59
|
+
- **[FIRST.org EPSS](https://www.first.org/epss/)** — Exploitation probability score and percentile per CVE
|
|
60
|
+
- **[CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)** — Known Exploited Vulnerabilities with ransomware use flags
|
|
61
|
+
|
|
62
|
+
Every CVE is enriched with derived fields (`exposure_tier`, `actionable`) and published as a gzip-compressed JSON catalog at:
|
|
63
|
+
|
|
64
|
+
**`https://openastra.org/oebc/catalog/v0.1/latest.json.gz`**
|
|
65
|
+
|
|
66
|
+
OEBC is consumed by **ExposureGate**, a CTEM (Continuous Threat Exposure Management) platform built on exposure baselines.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## How It Works
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
NVD CVE API FIRST.org EPSS CISA KEV
|
|
74
|
+
(250k+ CVEs) (EPSS scores) (Known exploited)
|
|
75
|
+
│ │ │
|
|
76
|
+
└────────────────────┴────────────────────┘
|
|
77
|
+
│
|
|
78
|
+
oebc generate
|
|
79
|
+
│
|
|
80
|
+
Join by CVE ID
|
|
81
|
+
│
|
|
82
|
+
Enrich: exposure_tier + actionable
|
|
83
|
+
│
|
|
84
|
+
┌────────────────┴──────────────────┐
|
|
85
|
+
│ │
|
|
86
|
+
latest.json.gz GitHub Release asset
|
|
87
|
+
(openastra.org repo) oebc-catalog-YYYY-MM-DD.json.gz
|
|
88
|
+
│
|
|
89
|
+
openastra.org/oebc/catalog/v0.1/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Catalog
|
|
95
|
+
|
|
96
|
+
| Artifact | URL |
|
|
97
|
+
|----------|-----|
|
|
98
|
+
| Latest catalog (gzip) | `https://openastra.org/oebc/catalog/v0.1/latest.json.gz` |
|
|
99
|
+
| Historical snapshots | GitHub Release assets on each `baseline-YYYY-MM-DD` release |
|
|
100
|
+
| JSON Schema | `https://openastra.org/oebc/schema/v0.1/oebc.json` |
|
|
101
|
+
| YAML Schema | `https://openastra.org/oebc/schema/v0.1/oebc.yaml` |
|
|
102
|
+
|
|
103
|
+
> The catalog is gzip-compressed to stay under GitHub's 100 MB file size limit (raw JSON is ~290 MB; compressed is ~25–30 MB). Historical daily snapshots are attached as release assets rather than committed to the repo, keeping repo size stable.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Quick Start
|
|
108
|
+
|
|
109
|
+
**Download the pre-built catalog (fastest):**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Download and decompress in one step
|
|
113
|
+
curl -L https://openastra.org/oebc/catalog/v0.1/latest.json.gz | gunzip > oebc_catalog.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Or use the CLI:**
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pip install oebc
|
|
120
|
+
|
|
121
|
+
# Download pre-built catalog from openastra.org
|
|
122
|
+
oebc fetch
|
|
123
|
+
|
|
124
|
+
# Generate catalog from scratch (fetches all live sources)
|
|
125
|
+
oebc generate
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Or run from source:**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git clone https://github.com/sadayamuthu/oebc.git
|
|
132
|
+
cd oebc
|
|
133
|
+
make install-dev
|
|
134
|
+
make generate
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Features
|
|
140
|
+
|
|
141
|
+
- **250k+ CVEs** — full NVD catalog, updated daily
|
|
142
|
+
- **Three authoritative sources** — NVD, EPSS, CISA KEV joined by CVE ID
|
|
143
|
+
- **Derived exposure tiers** — CRITICAL / HIGH / MEDIUM / LOW from KEV, EPSS and CVSS
|
|
144
|
+
- **Actionable flag** — boolean shortcut for tiers at or above a configurable minimum
|
|
145
|
+
- **Null-safe enrichment** — missing CVSS or EPSS scores handled gracefully
|
|
146
|
+
- **Configurable thresholds** — EPSS cutoffs exposed as CLI flags (CVSS bands are fixed at 9.0 and 7.0)
|
|
147
|
+
- **Retry-resilient** — exponential backoff on NVD / EPSS / KEV HTTP failures
|
|
148
|
+
- **Versioned schema** — JSON Schema Draft 2020-12 with `additionalProperties: false`, checked by the test suite
|
|
149
|
+
- **PyPI package** — `pip install oebc`
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## CLI Usage
|
|
154
|
+
|
|
155
|
+
### `oebc fetch`
|
|
156
|
+
|
|
157
|
+
Download the pre-built catalog from openastra.org (fast, no live API calls).
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
oebc fetch
|
|
161
|
+
oebc fetch --out my-catalog.json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
| Flag | Default | Description |
|
|
165
|
+
|------|---------|-------------|
|
|
166
|
+
| `--out` | `oebc_full_catalog_enriched.json` | Output file path |
|
|
167
|
+
|
|
168
|
+
### `oebc generate`
|
|
169
|
+
|
|
170
|
+
Fetch NVD + EPSS + CISA KEV live and generate the full enriched catalog.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
oebc generate
|
|
174
|
+
oebc generate --out catalog.json \
|
|
175
|
+
--actionable_min_tier high \
|
|
176
|
+
--epss_high_threshold 0.10 \
|
|
177
|
+
--epss_medium_threshold 0.01 \
|
|
178
|
+
--nvd_api_key YOUR_KEY
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
| Flag | Default | Description |
|
|
182
|
+
|------|---------|-------------|
|
|
183
|
+
| `--out` | `oebc_full_catalog_enriched.json` | Output file path |
|
|
184
|
+
| `--actionable_min_tier` | `medium` | Minimum tier for `actionable=true` (`low`, `medium`, `high`, `critical`) |
|
|
185
|
+
| `--epss_high_threshold` | `0.10` | EPSS score threshold for HIGH tier |
|
|
186
|
+
| `--epss_medium_threshold` | `0.01` | EPSS score threshold for MEDIUM tier |
|
|
187
|
+
| `--nvd_url` | NVD API URL | Override NVD source URL |
|
|
188
|
+
| `--epss_url` | FIRST.org EPSS URL | Override EPSS source URL |
|
|
189
|
+
| `--kev_url` | CISA KEV JSON URL | Override KEV source URL |
|
|
190
|
+
| `--nvd_api_key` | *(none)* | NVD API key for higher rate limits (optional) |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Output Schema
|
|
195
|
+
|
|
196
|
+
### Top-Level Structure
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"project": "Open Exposure Baseline Catalog (OEBC)",
|
|
201
|
+
"project_version": "0.1.0",
|
|
202
|
+
"generated_at_utc": "2026-03-16T06:00:00Z",
|
|
203
|
+
"sources": {
|
|
204
|
+
"nvd": "https://services.nvd.nist.gov/rest/json/cves/2.0",
|
|
205
|
+
"epss": "https://api.first.org/data/v1/epss",
|
|
206
|
+
"kev": "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
|
|
207
|
+
},
|
|
208
|
+
"rules": { ... },
|
|
209
|
+
"count": 250000,
|
|
210
|
+
"vulnerabilities": [ ... ]
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Per-CVE Record
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"cve_id": "CVE-2021-44228",
|
|
219
|
+
"description": "Apache Log4j2 JNDI...",
|
|
220
|
+
"published_date": "2021-12-10",
|
|
221
|
+
"last_modified_date": "2023-03-17",
|
|
222
|
+
"cwe_ids": ["CWE-917", "CWE-20"],
|
|
223
|
+
"cvss_score": 10.0,
|
|
224
|
+
"cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
|
|
225
|
+
"cvss_version": "3.1",
|
|
226
|
+
"cvss_severity": "CRITICAL",
|
|
227
|
+
"epss_score": 0.97566,
|
|
228
|
+
"epss_percentile": 0.99983,
|
|
229
|
+
"kev_listed": true,
|
|
230
|
+
"kev_date_added": "2021-12-10",
|
|
231
|
+
"kev_due_date": "2021-12-24",
|
|
232
|
+
"kev_ransomware_use": "Known",
|
|
233
|
+
"exposure_tier": "CRITICAL",
|
|
234
|
+
"actionable": true
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Field Reference
|
|
239
|
+
|
|
240
|
+
| Field | Type | Description |
|
|
241
|
+
|-------|------|-------------|
|
|
242
|
+
| `cve_id` | string | CVE identifier (e.g., `CVE-2021-44228`) |
|
|
243
|
+
| `description` | string | English description from NVD |
|
|
244
|
+
| `published_date` | string | ISO 8601 date first published |
|
|
245
|
+
| `last_modified_date` | string | ISO 8601 date last modified |
|
|
246
|
+
| `cwe_ids` | array | CWE identifiers (empty array if none) |
|
|
247
|
+
| `cvss_score` | number \| null | CVSS base score (prefers v3.1 > v3.0) |
|
|
248
|
+
| `cvss_vector` | string \| null | CVSS vector string |
|
|
249
|
+
| `cvss_version` | string \| null | CVSS version (`3.1`, `3.0`) |
|
|
250
|
+
| `cvss_severity` | string \| null | CVSS severity label |
|
|
251
|
+
| `epss_score` | number \| null | EPSS probability (0–1); null if not yet scored |
|
|
252
|
+
| `epss_percentile` | number \| null | EPSS percentile (0–1); null if not yet scored |
|
|
253
|
+
| `kev_listed` | boolean | `true` if in CISA KEV |
|
|
254
|
+
| `kev_date_added` | string \| null | Date added to KEV; null if not listed |
|
|
255
|
+
| `kev_due_date` | string \| null | CISA remediation due date; null if not listed |
|
|
256
|
+
| `kev_ransomware_use` | string \| null | Ransomware use flag from KEV; null if not listed |
|
|
257
|
+
| `exposure_tier` | string | Derived tier: `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` |
|
|
258
|
+
| `actionable` | boolean | `true` if tier ≥ `actionable_min_tier` |
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Exposure Tier Rules
|
|
263
|
+
|
|
264
|
+
Tiers are evaluated in priority order; first match wins.
|
|
265
|
+
|
|
266
|
+
| Tier | Condition |
|
|
267
|
+
|------|-----------|
|
|
268
|
+
| `CRITICAL` | `kev_listed = true` |
|
|
269
|
+
| `HIGH` | `epss_score >= 0.10` OR `cvss_score >= 9.0` |
|
|
270
|
+
| `MEDIUM` | `epss_score >= 0.01` OR `cvss_score >= 7.0` |
|
|
271
|
+
| `LOW` | everything else |
|
|
272
|
+
|
|
273
|
+
**Null handling:** null CVSS or EPSS scores evaluate as `false` in threshold comparisons — they never qualify for a higher tier.
|
|
274
|
+
|
|
275
|
+
**`actionable`:** `true` when `exposure_tier` ≥ `actionable_min_tier` (default: `medium`), so tiers `{MEDIUM, HIGH, CRITICAL}` are actionable by default.
|
|
276
|
+
|
|
277
|
+
**Threshold ordering:** `LOW < MEDIUM < HIGH < CRITICAL`
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Code Flow
|
|
282
|
+
|
|
283
|
+
```mermaid
|
|
284
|
+
flowchart TD
|
|
285
|
+
A[oebc generate] --> B[fetch_nvd_cves\nPaginated NVD API]
|
|
286
|
+
A --> C[fetch_epss_scores\nPaginated EPSS API]
|
|
287
|
+
A --> D[fetch_kev\nCISA KEV JSON]
|
|
288
|
+
B --> E[build_catalog\nJoin by CVE ID]
|
|
289
|
+
C --> E
|
|
290
|
+
D --> E
|
|
291
|
+
E --> F[compute_exposure_tier\nKEV → CRITICAL\nEPSS/CVSS → HIGH/MEDIUM\nelse → LOW]
|
|
292
|
+
F --> G[compute_actionable\ntier >= actionable_min_tier]
|
|
293
|
+
G --> H[Write JSON\nindent=2]
|
|
294
|
+
H --> I[oebc_full_catalog_enriched.json]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Project Structure
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
oebc/
|
|
303
|
+
├── .github/
|
|
304
|
+
│ ├── dependabot.yml # Weekly grouped pip and Actions updates
|
|
305
|
+
│ └── workflows/
|
|
306
|
+
│ ├── main-release.yml # Daily catalog generation → publish to openastra.org
|
|
307
|
+
│ ├── schema-release.yml # Schema versioning → publish schema to openastra.org
|
|
308
|
+
│ ├── pypi-publish.yml # Publish to PyPI on v*.*.* tags
|
|
309
|
+
│ └── develop.yml # CI on PRs and pushes to develop branch
|
|
310
|
+
├── spec/
|
|
311
|
+
│ ├── VERSION # Semver schema version (e.g., 0.1.0)
|
|
312
|
+
│ └── schemas/
|
|
313
|
+
│ ├── oebc-v0.1.json # JSON Schema Draft 2020-12
|
|
314
|
+
│ └── oebc-v0.1.yaml # YAML equivalent
|
|
315
|
+
├── src/oebc/
|
|
316
|
+
│ ├── __init__.py # Package version
|
|
317
|
+
│ ├── __main__.py # Entry point
|
|
318
|
+
│ ├── cli.py # CLI dispatcher (fetch/generate)
|
|
319
|
+
│ ├── fetch.py # Download pre-built catalog from openastra.org
|
|
320
|
+
│ ├── generate.py # Core: fetch NVD+EPSS+KEV, join, enrich, output
|
|
321
|
+
│ └── urls.py # Default source URLs
|
|
322
|
+
├── tests/
|
|
323
|
+
│ ├── test_cli.py
|
|
324
|
+
│ ├── test_fetch.py
|
|
325
|
+
│ ├── test_generate.py
|
|
326
|
+
│ ├── test_schema_validation.py
|
|
327
|
+
│ └── test_version.py
|
|
328
|
+
├── CITATION.cff
|
|
329
|
+
├── CONTRIBUTING.md
|
|
330
|
+
├── LICENSE
|
|
331
|
+
├── Makefile
|
|
332
|
+
├── pyproject.toml
|
|
333
|
+
├── README.md
|
|
334
|
+
└── SECURITY.md
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
> **Note:** No `baseline/` or `historical/` directory. Catalog artifacts are generated ephemerally in CI and pushed directly to openastra.org — the repo stays clean.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Automation
|
|
342
|
+
|
|
343
|
+
OEBC ships four GitHub Actions workflows:
|
|
344
|
+
|
|
345
|
+
### `develop.yml` — Development CI
|
|
346
|
+
|
|
347
|
+
Triggered on push to `develop` and pull requests targeting `develop` or `main`.
|
|
348
|
+
|
|
349
|
+
- `make check`: lint with ruff, then the full test suite with 100% coverage enforced
|
|
350
|
+
- Runs on Python 3.11, 3.12, 3.13
|
|
351
|
+
|
|
352
|
+
### `main-release.yml` — Daily Catalog Generation
|
|
353
|
+
|
|
354
|
+
Triggered on schedule (daily 06:00 UTC), push to `main`, and manual dispatch.
|
|
355
|
+
|
|
356
|
+
1. Test across Python 3.11, 3.12, 3.13
|
|
357
|
+
2. `oebc generate --out oebc_full_catalog_enriched.json` (ephemeral)
|
|
358
|
+
3. gzip the catalog and push it as `public/oebc/catalog/v0.1/latest.json.gz` to the openastra.org site repository (served at `openastra.org/oebc/catalog/v0.1/latest.json.gz`)
|
|
359
|
+
4. If the catalog changed, create a GitHub Release tagged `baseline-YYYY-MM-DD` with the snapshot attached as `oebc-catalog-YYYY-MM-DD.json.gz`
|
|
360
|
+
|
|
361
|
+
Requires secret: `OEBC_DEPLOY_TOKEN`
|
|
362
|
+
|
|
363
|
+
### `schema-release.yml` — Schema Publishing
|
|
364
|
+
|
|
365
|
+
Triggered on push to `main` affecting `spec/**`.
|
|
366
|
+
|
|
367
|
+
1. Validate `spec/VERSION` (semver); abort if tag already exists
|
|
368
|
+
2. Publish schema files to `openastra.org/oebc/schema/v{MAJOR.MINOR}/`
|
|
369
|
+
3. Create GitHub Release tagged `spec-v{VERSION}` with schema files attached
|
|
370
|
+
|
|
371
|
+
Requires secret: `OEBC_DEPLOY_TOKEN`
|
|
372
|
+
|
|
373
|
+
### `pypi-publish.yml` — PyPI Publishing
|
|
374
|
+
|
|
375
|
+
Triggered on push of any `v*.*.*` tag.
|
|
376
|
+
|
|
377
|
+
1. Build Python package
|
|
378
|
+
2. Publish to PyPI via OIDC Trusted Publishing (no API token required)
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Development
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
# Install with dev dependencies + pre-commit hooks
|
|
386
|
+
make install-dev
|
|
387
|
+
|
|
388
|
+
# Run tests
|
|
389
|
+
make test
|
|
390
|
+
|
|
391
|
+
# Run tests with 100% coverage report
|
|
392
|
+
make test-cov
|
|
393
|
+
|
|
394
|
+
# Lint
|
|
395
|
+
make lint
|
|
396
|
+
|
|
397
|
+
# Auto-format
|
|
398
|
+
make format
|
|
399
|
+
|
|
400
|
+
# Lint + test-cov
|
|
401
|
+
make check
|
|
402
|
+
|
|
403
|
+
# Generate catalog locally
|
|
404
|
+
make generate
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Data Sources
|
|
410
|
+
|
|
411
|
+
| Source | URL | What it provides |
|
|
412
|
+
|--------|-----|-----------------|
|
|
413
|
+
| NVD CVE API | `https://services.nvd.nist.gov/rest/json/cves/2.0` | All CVEs: description, CVSS score/vector/version/severity, CWE IDs, dates |
|
|
414
|
+
| EPSS API | `https://api.first.org/data/v1/epss` | Exploitation probability score (0–1) + percentile per CVE |
|
|
415
|
+
| CISA KEV | `https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json` | Known exploited CVEs with `dateAdded`, `dueDate`, ransomware use |
|
|
416
|
+
|
|
417
|
+
All sources are fetched live at generation time. No local data files committed to the repo.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Contributing
|
|
422
|
+
|
|
423
|
+
To report a wrong tier, a wrong EPSS or KEV join or a missing CVE, or to send
|
|
424
|
+
a change, see **[CONTRIBUTING.md](CONTRIBUTING.md)**. It covers the dev setup,
|
|
425
|
+
the 100% coverage rule, how tier rules change and how the schema is versioned.
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Security
|
|
430
|
+
|
|
431
|
+
Please don't report security problems in a public issue. Use
|
|
432
|
+
[**Report a vulnerability**](https://github.com/sadayamuthu/oebc/security/advisories/new)
|
|
433
|
+
on the Security tab; see **[SECURITY.md](SECURITY.md)** for what's in scope.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## License
|
|
438
|
+
|
|
439
|
+
[MIT License](LICENSE)
|
|
440
|
+
|
|
441
|
+
The license covers the code in this repository. The catalog republishes NVD,
|
|
442
|
+
FIRST EPSS and CISA KEV data, which stays under its providers' terms; see
|
|
443
|
+
[Upstream data](CONTRIBUTING.md#upstream-data).
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
<div align="center">
|
|
448
|
+
|
|
449
|
+
[Catalog](https://openastra.org/oebc/catalog/v0.1/latest.json.gz) · [Schema](https://openastra.org/oebc/schema/v0.1/oebc.json) · [PyPI](https://pypi.org/project/oebc/) · [openastra.org](https://openastra.org)
|
|
450
|
+
|
|
451
|
+
</div>
|