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 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
+ [![CI](https://github.com/sadayamuthu/oebc/actions/workflows/develop.yml/badge.svg)](https://github.com/sadayamuthu/oebc/actions/workflows/develop.yml)
43
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)
44
+ [![License](https://img.shields.io/github/license/sadayamuthu/oebc)](LICENSE)
45
+ [![Catalog](https://img.shields.io/badge/catalog-latest-green)](https://openastra.org/oebc/catalog/v0.1/latest.json.gz)
46
+ [![Schema](https://img.shields.io/badge/schema-v0.1-blue)](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>