185 lines
7.7 KiB
Markdown
185 lines
7.7 KiB
Markdown
# SkillSpector Web
|
||
|
||
Eine schlanke Web-Oberfläche für [NVIDIA SkillSpector](https://github.com/NVIDIA/SkillSpector) –
|
||
prüft AI-Agent-Skills (Claude Code, Codex, MCP) auf Sicherheitsrisiken wie
|
||
Prompt-Injection, Daten-Exfiltration, Supply-Chain-Probleme oder gefährlichen
|
||
Code, **bevor** sie installiert werden.
|
||
|
||
---
|
||
|
||
## Was macht das Tool?
|
||
|
||
1. Du gibst die URL eines Git-Repositorys (oder eine ZIP-Datei) mit einem
|
||
AI-Agent-Skill an.
|
||
2. Im Hintergrund läuft `skillspector scan` – reine statische Analyse
|
||
(Regex, Python-AST, YARA-Signaturen), optional ergänzt durch eine
|
||
LLM-Bewertung der Dateiinhalte.
|
||
3. Du bekommst einen Risk Score (0–100) mit Einstufung `SAFE` / `CAUTION` /
|
||
`DO_NOT_INSTALL` sowie eine Liste der gefundenen Probleme.
|
||
|
||
Der gescannte Skill wird dabei **zu keinem Zeitpunkt ausgeführt**.
|
||
|
||
## Nutzung
|
||
|
||
Formular öffnen → Git-URL eintragen oder ZIP hochladen → "Scan starten".
|
||
Fertig. Kein Account nötig (sofern der Betreiber den öffentlichen Modus
|
||
aktiviert hat, siehe unten).
|
||
|
||
---
|
||
|
||
## Selbst betreiben: Setup mit Gitea + Portainer
|
||
|
||
### 1. Repository klonen/forken
|
||
|
||
Dieses Repository enthält alles, was für ein eigenständiges Deployment
|
||
nötig ist: `Dockerfile`, `requirements.txt`, `app.py`, `docker-compose.yml`.
|
||
|
||
### 2. Stack in Portainer anlegen
|
||
|
||
1. **Stacks → Add stack → Build method: Repository**
|
||
- Repository URL: die URL dieses Repos
|
||
- Reference: `refs/heads/main`
|
||
- Compose path: `docker-compose.yml`
|
||
2. **Environment variables** im Portainer-UI setzen (niemals ins Repo
|
||
committen):
|
||
|
||
| Variable | Zweck | Beispiel |
|
||
|---|---|---|
|
||
| `REQUIRE_AUTH` | `true` = privat mit Login, `false` = öffentlich ohne Login | `false` |
|
||
| `WEBUI_USER` / `WEBUI_PASSWORD` | Nur relevant wenn `REQUIRE_AUTH=true` | – |
|
||
| `HOST_PORT` | Host-Port, falls der Standard (8010) belegt ist | `8011` |
|
||
| `MAX_SCANS_PER_HOUR_PER_IP` | Rate-Limit pro IP | `10` |
|
||
| `MAX_CONCURRENT_SCANS` | Wie viele Scans gleichzeitig laufen dürfen | `2` |
|
||
| `ENABLE_LLM_OPTION` | Schaltet die LLM-Checkbox für Nutzer frei | `false` |
|
||
| `OPENROUTER_API_KEY` | Nur wenn `ENABLE_LLM_OPTION=true` | `sk-or-...` |
|
||
| `OPENROUTER_MODEL` | Modell-Slug bei OpenRouter | `anthropic/claude-sonnet-4.5` |
|
||
|
||
3. **Deploy the stack**.
|
||
|
||
### 3. Port-Konflikt beheben ("bind: address already in use")
|
||
|
||
Diese Fehlermeldung heißt: Ein anderer Container/Prozess auf deinem Server
|
||
belegt den Port bereits. Zwei Wege:
|
||
|
||
- **Anderen Port wählen** (empfohlen): Umgebungsvariable `HOST_PORT` in
|
||
Portainer setzen, z. B. `8010`, `8011` … Der Compose-Datei ist das schon
|
||
vorbereitet (`127.0.0.1:${HOST_PORT:-8010}:8000`).
|
||
- **Belegenden Prozess finden**: auf dem Server `sudo ss -tlnp | grep 8000`
|
||
(oder `docker ps` – oft ist es ein anderer Stack, der ebenfalls Port 8000
|
||
nutzt).
|
||
|
||
### 4. Automatische Updates
|
||
|
||
Im `Dockerfile` ist SkillSpector **ohne Versions-Pin** installiert
|
||
(`git+https://github.com/NVIDIA/skillspector.git`). Jeder Image-Rebuild holt
|
||
also automatisch die aktuellste Version. Damit das regelmäßig passiert:
|
||
|
||
1. Stack öffnen → **GitOps updates** aktivieren
|
||
2. Mechanismus **Polling**, Intervall z. B. `24h`
|
||
3. **Force redeployment** und **Re-pull image** aktivieren
|
||
|
||
→ Portainer baut das Image alle 24 h neu, auch ohne Änderung an diesem
|
||
Repo, und zieht damit automatisch die neueste SkillSpector-Version.
|
||
|
||
Falls deine Portainer-Version das nicht anbietet: den Stack gelegentlich
|
||
manuell über "Pull and redeploy" neu bauen.
|
||
|
||
---
|
||
|
||
## LLM-Analyse über OpenRouter einrichten
|
||
|
||
SkillSpector unterstützt LLM-Analyse über jeden OpenAI-kompatiblen Endpunkt.
|
||
[OpenRouter](https://openrouter.ai) ist genau das – daher funktioniert es mit:
|
||
|
||
```
|
||
SKILLSPECTOR_PROVIDER=openai
|
||
OPENAI_API_KEY=<dein-openrouter-key>
|
||
OPENAI_BASE_URL=https://openrouter.ai/api/v1
|
||
SKILLSPECTOR_MODEL=anthropic/claude-sonnet-4.5 # oder ein anderes Modell-Slug
|
||
```
|
||
|
||
Das ist im `docker-compose.yml` bereits vorbereitet (`OPENROUTER_API_KEY` /
|
||
`OPENROUTER_MODEL` setzen, `ENABLE_LLM_OPTION=true`). Zwei Dinge zu beachten:
|
||
|
||
- **Kosten/Abuse**: Ohne `ENABLE_LLM_OPTION=true` ist die LLM-Checkbox für
|
||
Nutzer gar nicht sichtbar – dein OpenRouter-Guthaben ist also standardmäßig
|
||
nicht angreifbar, selbst im öffentlichen Modus. Das Rate-Limit
|
||
(`MAX_SCANS_PER_HOUR_PER_IP`) begrenzt zusätzlich, wie oft ein einzelner
|
||
Nutzer die LLM-Analyse überhaupt anstoßen kann.
|
||
- **Nicht jedes Modell liefert zuverlässig strukturierte JSON-Antworten.**
|
||
Falls die LLM-Analyse mit einem Fehler abbricht, zuerst ein bekanntes,
|
||
instruction-following-starkes Modell testen (z. B. ein aktuelles
|
||
Claude- oder GPT-Modell über OpenRouter); im Zweifel bleibt `--no-llm`
|
||
(Standard) immer als zuverlässiger Fallback.
|
||
|
||
---
|
||
|
||
## Sicherheitsarchitektur
|
||
|
||
**Container-Ebene** (schützt deinen Server):
|
||
|
||
- Kein Docker-Socket-Mount – der Container kann weder andere Container noch
|
||
den Host steuern.
|
||
- `read_only: true` – Root-Dateisystem unveränderlich, nur `/tmp` und das
|
||
Scan-Verzeichnis sind flüchtiger RAM-Speicher (`tmpfs`).
|
||
- `cap_drop: ALL` und `no-new-privileges` – keine erweiterten Linux-Rechte.
|
||
- Ressourcenlimits (`mem_limit`, `cpus`) – ein hängender oder böswilliger
|
||
Scan kann den restlichen Server nicht belasten.
|
||
- Port nur auf `127.0.0.1` gebunden – öffentliche Erreichbarkeit ausschließlich
|
||
über deinen Reverse Proxy (TLS, eigene Subdomain).
|
||
|
||
**Anwendungs-Ebene** (schützt vor Missbrauch durch Fremdnutzer, relevant seit
|
||
öffentlichem Betrieb):
|
||
|
||
- **SSRF-Schutz**: Ziel-URLs werden aufgelöst und abgelehnt, wenn sie auf
|
||
private/interne/Loopback-Adressen zeigen (verhindert, dass jemand über das
|
||
Formular dein internes Netzwerk abscannt).
|
||
- **Rate-Limiting**: maximal `MAX_SCANS_PER_HOUR_PER_IP` Scans pro IP und
|
||
Stunde.
|
||
- **Concurrency-Limit**: maximal `MAX_CONCURRENT_SCANS` Scans gleichzeitig,
|
||
weitere Anfragen werden abgewiesen statt den Server zu überlasten.
|
||
- **Zeitlimit** je Scan (`SCAN_TIMEOUT_SECONDS`).
|
||
- **LLM-Analyse ist ein bewusstes Opt-in** des Betreibers, nicht der Nutzer.
|
||
- SkillSpector führt den gescannten Skill nie aus – nur statische Analyse
|
||
plus optionale LLM-Bewertung von Dateiinhalten.
|
||
- Jeder Scan läuft in einem eigenen, danach gelöschten Temp-Ordner. Nichts
|
||
wird dauerhaft gespeichert.
|
||
|
||
---
|
||
|
||
## Rechtliches für den öffentlichen Betrieb
|
||
|
||
Ein öffentlich erreichbares Angebot in Deutschland braucht ein Impressum
|
||
(§ 5 DDG) und eine Datenschutzerklärung. Falls du dieses Tool wie deine
|
||
anderen Werkzeuge über `software.obraasch.de` einbindest, kannst du die dort
|
||
vorhandenen Vorlagen (`impressum.html`, `datenschutz.html` aus dem
|
||
[Software-Uebersicht](https://git.obraasch.de/olli1986/Software-Uebersicht)-Repo)
|
||
weiterverwenden und um einen Hinweis ergänzen, dass bei aktivierter
|
||
LLM-Analyse Nutzereingaben an einen externen Anbieter (OpenRouter bzw. das
|
||
dort gewählte Modell) übertragen werden. Die WebUI selbst weist Nutzer direkt
|
||
im Formular darauf hin.
|
||
|
||
Diese Angaben sind nach bestem Wissen erstellt, ersetzen aber keine
|
||
Rechtsberatung.
|
||
|
||
---
|
||
|
||
## Lizenz
|
||
|
||
Dieser Web-Wrapper (`Dockerfile`, `app.py`, `requirements.txt`,
|
||
`docker-compose.yml`, diese README) steht unter der **MIT-Lizenz**, siehe
|
||
[`LICENSE`](./LICENSE).
|
||
|
||
Er installiert beim Bauen des Images das externe Paket **SkillSpector**
|
||
(NVIDIA, Apache License 2.0) – siehe [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md).
|
||
SkillSpector selbst ist nicht Teil dieses Repositories und bleibt vollständig
|
||
unter der Lizenz des Originalprojekts.
|
||
|
||
## Haftungsausschluss
|
||
|
||
Diese Software wird "wie sie ist" bereitgestellt, ohne jegliche Garantie.
|
||
Ein niedriger Risk Score ist keine Sicherheitsgarantie – SkillSpector ist ein
|
||
Hilfsmittel zur Risikoeinschätzung, keine vollständige Sicherheitsprüfung.
|
||
Für gescannte Inhalte, die von Nutzern eingereicht werden, wird keine
|
||
Verantwortung übernommen.
|