119 lines
4.4 KiB
Markdown
119 lines
4.4 KiB
Markdown
# Umsetzungsplan: Hugging Face Hub Scanner
|
||
|
||
## Zusammenfassung
|
||
Scan von öffentlichen Hugging Face Spaces, Models und Datasets nach geleakten API-Keys.
|
||
AI/ML-Entwickler nutzen häufig Anthropic-Keys in ihren Projekten – besonders in Spaces (Gradio-Apps) und Notebooks.
|
||
|
||
## Warum Hugging Face?
|
||
- **2M+ Models, 500k+ Datasets, 1M+ Spaces** auf der Plattform
|
||
- ML/AI-Entwickler sind die Hauptnutzer von Anthropic-Keys
|
||
- Viele Anfänger hardcoden Keys in `app.py`, `.env`, Notebooks
|
||
- Hugging Face Full-Text-Suche indexiert Model Cards, Dataset Cards und `app.py`-Dateien
|
||
- Öffentliche REST API ohne Authentifizierung nutzbar
|
||
|
||
## API-Analyse
|
||
|
||
### Ansatz 1: Full-Text Search (Web-Scraping)
|
||
- **URL:** `https://huggingface.co/search/full-text?q=sk-ant-oat01&type=space`
|
||
- Indexiert: Model Cards, Dataset Cards, Spaces `app.py`
|
||
- **Problem:** Kein offizieller API-Endpoint, HTML-Scraping nötig → fragil
|
||
- **Fazit:** ❌ Nicht empfohlen
|
||
|
||
### Ansatz 2: Hub REST API + Datei-Download ✅ (Empfohlen)
|
||
Die HF Hub API erlaubt:
|
||
1. **Spaces auflisten** mit Suchfilter: `GET https://huggingface.co/api/spaces?search=anthropic&limit=100`
|
||
2. **Dateien eines Repos auflisten:** `GET https://huggingface.co/api/spaces/{repo_id}/tree/main`
|
||
3. **Datei-Inhalt herunterladen:** `GET https://huggingface.co/spaces/{repo_id}/resolve/main/{path}`
|
||
|
||
**Strategie:**
|
||
- Spaces die "anthropic", "claude", "sk-ant" im Namen/Description haben → Dateien scannen
|
||
- Gezielt nach `.env`, `app.py`, `*.py`, `config.*`, `.streamlit/secrets.toml` suchen
|
||
- Datei-Inhalt mit Regex auf Key-Patterns prüfen
|
||
|
||
### Rate Limits
|
||
- Unauthentifiziert: ~100 Requests/Minute (geschätzt)
|
||
- Authentifiziert (HF Token): Höhere Limits
|
||
- Kein offizielles Rate-Limit-Dokument, aber großzügig
|
||
|
||
## Implementierungsplan
|
||
|
||
### Phase 1: Neue Scan-Methode `ScanHuggingFace`
|
||
|
||
```
|
||
private async Task<List<(string Key, string Url)>> ScanHuggingFace(CancellationToken ct)
|
||
```
|
||
|
||
**Ablauf:**
|
||
1. Spaces suchen mit relevanten Keywords:
|
||
- `GET /api/spaces?search=anthropic&sort=modified&direction=-1&limit=100`
|
||
- `GET /api/spaces?search=claude&sort=modified&direction=-1&limit=100`
|
||
- `GET /api/spaces?search=sk-ant&sort=modified&direction=-1&limit=100`
|
||
- `GET /api/spaces?search=api+key&sort=modified&direction=-1&limit=100`
|
||
2. Für jeden gefundenen Space:
|
||
- Dateiliste abrufen: `GET /api/spaces/{id}/tree/main`
|
||
- Relevante Dateien filtern (`.env`, `*.py`, `*.yaml`, `*.toml`, `*.json`, `*.md`, `*.txt`, `*.ipynb`)
|
||
- Datei-Inhalt herunterladen und mit Regex scannen
|
||
3. Gleiche Prozedur für Models (viele haben Python-Inferenz-Scripts):
|
||
- `GET /api/models?search=anthropic&sort=modified&direction=-1&limit=100`
|
||
4. Gefundene Keys mit Source-URL zurückgeben
|
||
|
||
### Phase 2: Integration in RunScan
|
||
|
||
```csharp
|
||
// In RunScan(), nach Serper-Scan:
|
||
if (mode != "quick" && !string.IsNullOrWhiteSpace(_huggingFaceEnabled))
|
||
{
|
||
var hfKeys = await ScanHuggingFace(ct);
|
||
allFoundKeys.AddRange(hfKeys.Select(k => (k.Key, k.Url, "huggingface")));
|
||
}
|
||
```
|
||
|
||
- **Mode `quick`:** Kein HF-Scan (zu langsam)
|
||
- **Mode `web`:** HF-Scan aktiv (gehört zu "Web"-Quellen)
|
||
- **Mode `full`:** HF-Scan aktiv
|
||
|
||
### Phase 3: Config
|
||
|
||
```json
|
||
{
|
||
"HuggingFaceToken": "hf_xxx" // Optional, erhöht Rate-Limits
|
||
}
|
||
```
|
||
|
||
Ein HF-Token ist **nicht zwingend nötig** – die API funktioniert auch ohne Auth.
|
||
Mit Token aber höhere Rate-Limits und Zugriff auf gated Repos.
|
||
|
||
## Scan-Targets (Dateien die gescannt werden)
|
||
|
||
| Datei-Pattern | Wahrscheinlichkeit für Keys |
|
||
|---|---|
|
||
| `.env`, `.env.*` | 🔥 Sehr hoch |
|
||
| `app.py` | 🔥 Hoch (Gradio Spaces) |
|
||
| `*.py` | 🔥 Hoch |
|
||
| `*.ipynb` | 🔥 Hoch (Notebooks) |
|
||
| `config.*`, `*.yaml`, `*.toml` | 🟡 Mittel |
|
||
| `*.json` | 🟡 Mittel |
|
||
| `*.md` (README) | 🟡 Niedrig |
|
||
| `*.txt` | 🟡 Niedrig |
|
||
|
||
**Dateigröße-Limit:** Nur Dateien < 500 KB herunterladen (keine Model-Weights etc.)
|
||
|
||
## Suchbegriffe
|
||
|
||
```csharp
|
||
private static readonly string[] HuggingFaceSearchTerms = {
|
||
"anthropic", "claude", "sk-ant", "api key anthropic",
|
||
"claude api", "anthropic key"
|
||
};
|
||
```
|
||
|
||
## Aufwandsschätzung
|
||
- **Implementierung:** ~200 Zeilen Code (neue Methode + Config)
|
||
- **Komplexität:** Niedrig (einfache REST API, kein Auth nötig)
|
||
- **Erwarteter Ertrag:** Mittel-Hoch (AI/ML-Entwickler = Hauptnutzer von Anthropic)
|
||
|
||
## Risiken
|
||
- Kein offizielles Rate-Limit-Dokument → könnte throttlen
|
||
- Spaces die nur im Runtime env-Vars setzen → Keys nicht in Dateien sichtbar
|
||
- Große Repos mit vielen Dateien → Timeout-Gefahr → Max 50 Dateien pro Repo scannen
|