ossuary-risk 0.1.0__py3-none-any.whl
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.
- ossuary/__init__.py +7 -0
- ossuary/api/__init__.py +1 -0
- ossuary/api/main.py +173 -0
- ossuary/cli.py +309 -0
- ossuary/collectors/__init__.py +8 -0
- ossuary/collectors/base.py +26 -0
- ossuary/collectors/git.py +231 -0
- ossuary/collectors/github.py +495 -0
- ossuary/collectors/npm.py +113 -0
- ossuary/collectors/pypi.py +118 -0
- ossuary/db/__init__.py +15 -0
- ossuary/db/models.py +197 -0
- ossuary/db/session.py +49 -0
- ossuary/scoring/__init__.py +16 -0
- ossuary/scoring/engine.py +318 -0
- ossuary/scoring/factors.py +175 -0
- ossuary/scoring/reputation.py +326 -0
- ossuary/sentiment/__init__.py +5 -0
- ossuary/sentiment/analyzer.py +232 -0
- ossuary_risk-0.1.0.dist-info/METADATA +241 -0
- ossuary_risk-0.1.0.dist-info/RECORD +23 -0
- ossuary_risk-0.1.0.dist-info/WHEEL +4 -0
- ossuary_risk-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ossuary-risk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: OSS Supply Chain Risk Scoring - Where abandoned packages come to rest
|
|
5
|
+
Project-URL: Homepage, https://github.com/anicka-net/ossuary
|
|
6
|
+
Project-URL: Repository, https://github.com/anicka-net/ossuary
|
|
7
|
+
Project-URL: Documentation, https://github.com/anicka-net/ossuary/blob/main/docs/methodology.md
|
|
8
|
+
Author: Anicka
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: oss,risk,scoring,security,supply-chain
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Requires-Dist: alembic>=1.13.0
|
|
20
|
+
Requires-Dist: fastapi>=0.109.0
|
|
21
|
+
Requires-Dist: gitpython>=3.1.0
|
|
22
|
+
Requires-Dist: httpx>=0.26.0
|
|
23
|
+
Requires-Dist: psycopg2-binary>=2.9.0
|
|
24
|
+
Requires-Dist: pydantic-settings>=2.1.0
|
|
25
|
+
Requires-Dist: pydantic>=2.5.0
|
|
26
|
+
Requires-Dist: rich>=13.0.0
|
|
27
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
28
|
+
Requires-Dist: textblob>=0.18.0
|
|
29
|
+
Requires-Dist: typer>=0.9.0
|
|
30
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
31
|
+
Requires-Dist: vadersentiment>=3.3.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: httpx>=0.26.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Ossuary
|
|
42
|
+
|
|
43
|
+
**OSS Supply Chain Risk Scoring** - Where abandoned packages come to rest.
|
|
44
|
+
|
|
45
|
+
Ossuary analyzes open source packages to identify governance-based supply chain risks before incidents occur. It calculates a risk score based on maintainer concentration, activity levels, and protective factors.
|
|
46
|
+
|
|
47
|
+
## What It Detects
|
|
48
|
+
|
|
49
|
+
Ossuary focuses on **governance failures** - the type of vulnerability that enabled attacks like:
|
|
50
|
+
|
|
51
|
+
- **event-stream** (2018) - Abandoned package handed off to malicious maintainer
|
|
52
|
+
- **colors/faker** (2022) - Frustrated maintainer intentionally sabotaged packages
|
|
53
|
+
|
|
54
|
+
### Detection Capabilities
|
|
55
|
+
|
|
56
|
+
| Can Detect | Cannot Detect |
|
|
57
|
+
|------------|---------------|
|
|
58
|
+
| Maintainer abandonment | Account compromise (like ua-parser-js) |
|
|
59
|
+
| High concentration risk | Dependency confusion attacks |
|
|
60
|
+
| Economic frustration signals | Typosquatting |
|
|
61
|
+
| Declining activity trends | Malicious code injection |
|
|
62
|
+
| Governance centralization | |
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Install
|
|
68
|
+
pip install ossuary
|
|
69
|
+
|
|
70
|
+
# Initialize database (optional, for caching)
|
|
71
|
+
ossuary init
|
|
72
|
+
|
|
73
|
+
# Score a package
|
|
74
|
+
ossuary score event-stream --ecosystem npm
|
|
75
|
+
|
|
76
|
+
# Score with historical cutoff (T-1 analysis)
|
|
77
|
+
ossuary score event-stream --ecosystem npm --cutoff 2018-09-01
|
|
78
|
+
|
|
79
|
+
# Output as JSON
|
|
80
|
+
ossuary score requests --ecosystem pypi --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Risk Levels
|
|
84
|
+
|
|
85
|
+
| Score | Level | Semaphore | Action |
|
|
86
|
+
|-------|-------|-----------|--------|
|
|
87
|
+
| 0-20 | Very Low | π’ | Routine monitoring |
|
|
88
|
+
| 21-40 | Low | π’ | Quarterly review |
|
|
89
|
+
| 41-60 | Moderate | π‘ | Monthly review |
|
|
90
|
+
| 61-80 | High | π | Weekly review + contingency plan |
|
|
91
|
+
| 81-100 | Critical | π΄ | Immediate action required |
|
|
92
|
+
|
|
93
|
+
## Scoring Methodology
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Final Score = Base Risk + Activity Modifier + Protective Factors
|
|
97
|
+
(20-100) (-30 to +20) (-100 to +20)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Base Risk (Maintainer Concentration)
|
|
101
|
+
|
|
102
|
+
| Concentration | Points |
|
|
103
|
+
|---------------|--------|
|
|
104
|
+
| <30% | 20 |
|
|
105
|
+
| 30-50% | 40 |
|
|
106
|
+
| 50-70% | 60 |
|
|
107
|
+
| 70-90% | 80 |
|
|
108
|
+
| >90% | 100 |
|
|
109
|
+
|
|
110
|
+
### Activity Modifier
|
|
111
|
+
|
|
112
|
+
| Commits/Year | Points |
|
|
113
|
+
|--------------|--------|
|
|
114
|
+
| >50 | -30 |
|
|
115
|
+
| 12-50 | -15 |
|
|
116
|
+
| 4-11 | 0 |
|
|
117
|
+
| <4 | +20 |
|
|
118
|
+
|
|
119
|
+
### Protective Factors
|
|
120
|
+
|
|
121
|
+
| Factor | Points |
|
|
122
|
+
|--------|--------|
|
|
123
|
+
| Tier-1 maintainer (500+ repos or 100K+ stars) | -25 |
|
|
124
|
+
| GitHub Sponsors enabled | -15 |
|
|
125
|
+
| Organization with 3+ admins | -15 |
|
|
126
|
+
| >50M weekly downloads | -20 |
|
|
127
|
+
| >10M weekly downloads | -10 |
|
|
128
|
+
| <40% concentration | -10 |
|
|
129
|
+
| >20 contributors | -10 |
|
|
130
|
+
| CII Best Practices badge | -10 |
|
|
131
|
+
| **Frustration signals detected** | **+20** |
|
|
132
|
+
|
|
133
|
+
## API Usage
|
|
134
|
+
|
|
135
|
+
Start the API server:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
uvicorn ossuary.api.main:app --host 0.0.0.0 --port 8000
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Query a package:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
curl "http://localhost:8000/score/npm/event-stream"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Response:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"package": "event-stream",
|
|
152
|
+
"ecosystem": "npm",
|
|
153
|
+
"score": 100,
|
|
154
|
+
"risk_level": "CRITICAL",
|
|
155
|
+
"semaphore": "π΄",
|
|
156
|
+
"explanation": "π΄ CRITICAL (100). Critical concentration (90%): single person controls nearly all commits. Project appears abandoned (<4 commits/year).",
|
|
157
|
+
"recommendations": [
|
|
158
|
+
"IMMEDIATE: Identify alternative packages or prepare to fork",
|
|
159
|
+
"Do not accept new versions without manual code review"
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Development
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Clone
|
|
168
|
+
git clone https://github.com/anicka/ossuary.git
|
|
169
|
+
cd ossuary
|
|
170
|
+
|
|
171
|
+
# Install with dev dependencies
|
|
172
|
+
pip install -e ".[dev]"
|
|
173
|
+
|
|
174
|
+
# Run tests
|
|
175
|
+
pytest
|
|
176
|
+
|
|
177
|
+
# Run linter
|
|
178
|
+
ruff check src/
|
|
179
|
+
|
|
180
|
+
# Type check
|
|
181
|
+
mypy src/
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Configuration
|
|
185
|
+
|
|
186
|
+
Environment variables:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Required for higher GitHub API rate limits
|
|
190
|
+
GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
|
|
191
|
+
|
|
192
|
+
# Database (defaults to SQLite)
|
|
193
|
+
DATABASE_URL=postgresql://user:pass@localhost/ossuary
|
|
194
|
+
|
|
195
|
+
# Repository storage
|
|
196
|
+
REPOS_PATH=./repos
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Architecture
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
203
|
+
β API / CLI β
|
|
204
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
205
|
+
β
|
|
206
|
+
βΌ
|
|
207
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
208
|
+
β Scoring Engine β
|
|
209
|
+
β - Base risk (concentration) β
|
|
210
|
+
β - Activity modifier β
|
|
211
|
+
β - Protective factors β
|
|
212
|
+
β - Sentiment analysis β
|
|
213
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
214
|
+
β
|
|
215
|
+
βΌ
|
|
216
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
217
|
+
β Data Collectors β
|
|
218
|
+
β GitCollector | GitHubCollector | NpmCollector | PyPICollectorβ
|
|
219
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Validation
|
|
223
|
+
|
|
224
|
+
Validated on 93 packages (20 incidents + 73 controls):
|
|
225
|
+
|
|
226
|
+
- **Accuracy**: 91.4%
|
|
227
|
+
- **Precision**: 92.9%
|
|
228
|
+
- **Recall**: 65.0%
|
|
229
|
+
- **F1 Score**: 0.76
|
|
230
|
+
|
|
231
|
+
T-1 analysis confirms **100% predictive detection** of governance-detectable incidents before they occurred.
|
|
232
|
+
|
|
233
|
+
See [methodology documentation](docs/methodology.md) for details.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|
|
238
|
+
|
|
239
|
+
## Academic Context
|
|
240
|
+
|
|
241
|
+
This project supports MBA thesis research on OSS supply chain risk. Key contribution: demonstrating that meaningful risk indicators are observable in public metadata before incidents occur.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
ossuary/__init__.py,sha256=LBPIxjvA1VQ68JIe5jEHLM3k4olf6F-egSzmBwyl6gc,111
|
|
2
|
+
ossuary/cli.py,sha256=aK8C0caQExM2RZktx7wKruMqpsvsi2JRMxsGe6uL0ns,12016
|
|
3
|
+
ossuary/api/__init__.py,sha256=ZeoSK1LsObUCJjTBPuYIz9wPcsNdjcNyXjwV9Cm3nGo,30
|
|
4
|
+
ossuary/api/main.py,sha256=LCOnxh8XYBI5z9O-fTuczV5IP84LNCz0KKcZ18EBdDg,6094
|
|
5
|
+
ossuary/collectors/__init__.py,sha256=4RwxUTTH8GbEXIUYCxjl1RjkWcb748D-BO3jdiW_btM,324
|
|
6
|
+
ossuary/collectors/base.py,sha256=XiQ8qlrJOdDBbNt8yl7M0dMf5KDbDcpBAmzxaLdyCyo,637
|
|
7
|
+
ossuary/collectors/git.py,sha256=Ljy8i1lmLDz5KhCIYtczGM5AiRgs0tm-zPbhxdZ5RCo,7553
|
|
8
|
+
ossuary/collectors/github.py,sha256=D1abhZVuMAOWgHhnkpIWJ7rdrdIQ5Vwg64Ihq9yNdy4,16977
|
|
9
|
+
ossuary/collectors/npm.py,sha256=wBufJBrq52NGxjqHOInEtvlmw8NvwG39r3vuKGIHqgw,3586
|
|
10
|
+
ossuary/collectors/pypi.py,sha256=mwBbK5VFDGo3b6uKlr2dUqKwJoj-d11jiHSxEKYU91Y,3625
|
|
11
|
+
ossuary/db/__init__.py,sha256=kLmKsHlKXXsDHB7-gnV3BYJx5bkHc2qxQBJBt023gGI,321
|
|
12
|
+
ossuary/db/models.py,sha256=6n1XlYFG6Hud41FCZUFk54ZH2xAyu5gvDNAyInxL8uc,6919
|
|
13
|
+
ossuary/db/session.py,sha256=sUzk271Q0UrFHccu4m2Y1rGXcPC5Zgno0feT5j9Yrlg,1267
|
|
14
|
+
ossuary/scoring/__init__.py,sha256=IzcbPV5NugIa1luLg6YVoy8TPEcFjlKyvgqX16vKHds,454
|
|
15
|
+
ossuary/scoring/engine.py,sha256=jhWHkQ4V24osoNxhdWKUdptjLXCMZaIAPX2g3A_lC8E,11924
|
|
16
|
+
ossuary/scoring/factors.py,sha256=DSQBQyUeVgl9pX1pDysRChBPW_j7XUW-ZDRXx58IRvs,5921
|
|
17
|
+
ossuary/scoring/reputation.py,sha256=PABfHfZiRWGJxv-4q19qHIY0WmtTWQE-oIYTkffyiKE,9741
|
|
18
|
+
ossuary/sentiment/__init__.py,sha256=ouOTyAh9Z_GW2UBMH0h-qD-jYUJVyyZfP7rK3KlJu58,147
|
|
19
|
+
ossuary/sentiment/analyzer.py,sha256=ndlqVaKiM23P4yeFcOrRtOP7K0UCVY99Nqk9cvKVIro,7383
|
|
20
|
+
ossuary_risk-0.1.0.dist-info/METADATA,sha256=iw9KDkUbV6R629mjb8CJIVXosbFSFWZhpk3Im-ZxXmg,7608
|
|
21
|
+
ossuary_risk-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
22
|
+
ossuary_risk-0.1.0.dist-info/entry_points.txt,sha256=PorJvPUnbx9MTUHWHpypRK6N1Hra5Xcisk1aOtj443k,44
|
|
23
|
+
ossuary_risk-0.1.0.dist-info/RECORD,,
|