Dateien nach "/" hochladen

This commit is contained in:
Oliver Braasch committed 2026-09-22 12:07:20 +02:00
1 parent 74087727ad
commit 0d53c9a3e2
5 files changed
+330 -103

No files matched your search

+177 -72
View File
@@ -1,81 +1,186 @@
# SkillSpector Web – Setup-Anleitung
# SkillSpector Web
Web-Oberfläche für [SkillSpector](https://github.com/NVIDIA/SkillSpector), gehärtet für
den Betrieb auf einem eigenen Server via Portainer.
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.
## 1. Repository in Gitea anlegen
**Live:** _(hier deine Subdomain eintragen, z. B. https://skillspector.obraasch.de/)_
1. Neues Repo z. B. unter `git.obraasch.de/olli1986/skillspector-web` anlegen.
2. Diese vier Dateien hochladen/pushen: `Dockerfile`, `requirements.txt`, `app.py`,
`docker-compose.yml`.
3. **Nicht committen:** Passwörter oder API-Keys – die kommen später als
Umgebungsvariablen in Portainer, nie ins Repo.
---
## 2. Stack in Portainer anlegen
## Was macht das Tool?
1. **Stacks → Add stack**
2. **Build method: Repository**
- Repository URL: `https://git.obraasch.de/olli1986/skillspector-web`
- Reference: `refs/heads/main`
- Compose path: `docker-compose.yml`
3. **Environment variables** (im Portainer-UI, nicht im Repo):
- `WEBUI_USER` = z. B. `admin`
- `WEBUI_PASSWORD` = ein starkes Passwort
- optional `ANTHROPIC_API_KEY`, falls du später LLM-Analyse willst
4. **Deploy the stack**
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.
Ohne gesetztes `WEBUI_PASSWORD` verweigert die WebUI jeden Zugriff (Absicherung
gegen offen erreichbare Instanzen).
## 3. Automatische Updates einrichten
Der Trick: Im `Dockerfile` ist SkillSpector **ohne Versions-Pin** installiert
(`git+https://github.com/NVIDIA/skillspector.git`). Jeder Rebuild des Images holt
also automatisch den aktuellen `main`-Branch. Damit das regelmäßig passiert, ohne
dass du selbst etwas anfassen musst:
1. Stack öffnen → Abschnitt **GitOps updates**
2. **Enable GitOps updates** aktivieren
3. Mechanismus: **Polling**, Intervall z. B. `24h`
4. **Force redeployment** UND **Re-pull image / rebuild** aktivieren
→ Auch wenn sich in *deinem* Repo nichts ändert, baut Portainer das Image alle
24h neu und zieht damit automatisch die neueste SkillSpector-Version.
5. Speichern.
Falls deine Portainer-Version "Force redeployment" beim reinen Repository-Build
nicht anbietet: alternativ einfach den Stack alle paar Wochen manuell über
**"Pull and redeploy"** neu bauen – dauert 10 Sekunden und holt ebenfalls die
neueste Version.
## 4. Öffentlich erreichbar machen (optional)
Der Container bindet bewusst nur an `127.0.0.1:8000`, ist also von außen gar nicht
erreichbar. Wenn du ihn z. B. unter `skillspector.obraasch.de` nutzen willst,
richte in CloudPanel einen Reverse Proxy auf `127.0.0.1:8000` ein – mit TLS
(Let's Encrypt) und idealerweise IP-Beschränkung, da die App zusätzlich zur
Basic-Auth Angriffsfläche für einen Web-Client darstellt (auch wenn sie selbst
sehr klein ist).
## 5. Warum das deinen Server nicht gefährden kann
- **Kein Docker-Socket-Mount** – der Container kann keine anderen Container
oder den Host steuern.
- **`read_only: true`** – das Root-Dateisystem im Container ist 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 in die Knie zwingen.
- **SkillSpector führt den gescannten Skill nie aus** – nur statische Analyse
(Regex/AST/YARA) plus optionale LLM-Bewertung von Dateiinhalten.
- **`--no-llm` ist Standard** – ohne dein explizites Häkchen verlässt kein
gescannter Dateiinhalt den Container.
- Jeder Scan läuft in einem eigenen Temp-Ordner, der danach gelöscht wird.
Der gescannte Skill wird dabei **zu keinem Zeitpunkt ausgeführt**.
## Nutzung
WebUI öffnen (z. B. `http://<server>:8000` lokal oder deine Subdomain), Basic-Auth
eingeben, Git-URL des Skills eintragen oder ZIP hochladen, "Scan starten" klicken.
Das Ergebnis zeigt Risk Score, Severity und Empfehlung (`SAFE` / `CAUTION` /
`DO_NOT_INSTALL`) sowie den vollständigen JSON-Report.
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.