Überblick über die secscan-API
Mit der secscan-API automatisieren Sie alles, was die Weboberfläche kann: Dateien, Repositorys und Links einreichen, die Analyse live verfolgen und den vollständigen forensischen Bericht als JSON abrufen, aus Skripten, CI-Pipelines und Ihren eigenen Werkzeugen.
- REST über HTTPS, JSON hin und zurück, Basis-URL
https://one.heimdall-security.net/api/v1 - Jede Einreichung wird in derselben isolierten Sandbox ohne Netzwerk analysiert wie Uploads über die Website
- Große Dateien werden in fortsetzbaren Blöcken zu 16 MB gesendet
- Verfügbar mit secscan Pro; Schlüssel erstellen Sie unter API & CLI
Authentifizierung
Senden Sie Ihren API-Schlüssel bei jeder Anfrage im Header X-Secscan-Token. Schlüssel beginnen mit hsk_, werden beim Erstellen einmal angezeigt und können jederzeit widerrufen werden. Behandeln Sie sie wie Passwörter: niemals in öffentliche Repositorys oder clientseitigen Code.
curl -H "X-Secscan-Token: $SECSCAN_TOKEN" https://one.heimdall-security.net/api/v1/me
Tarife & Kontingente
| Tarif | Prüfungen | Dateigröße | API |
|---|---|---|---|
| Gast | 3 pro Woche | 10 MB | – |
| Free | 10 pro Woche | 100 MB | – |
| Pro | unbegrenzt | 3.0 GB | ✓ |
Jeder Schlüssel darf 120 Anfragen pro Minute stellen und 2 Prüfungen gleichzeitig ausführen.
Fehler
Fehler verwenden die üblichen HTTP-Statuscodes mit einem JSON-Body {"error": "...", "message": "..."}.
400 | ungültige Anfrage oder Kontingent erreicht (siehe error) |
401 | missing_token oder invalid_token (unbekannt oder widerrufen) |
403 | pro_required: Das Konto hat keinen aktiven Pro-Tarif |
404 | nicht gefunden (auch bei Prüfungen anderer Benutzer) |
409 | Block in falscher Reihenfolge: beim zurückgegebenen Offset received fortfahren |
429 | rate_limited: bitte langsamer |
Konto
GET /me liefert Ihre E-Mail-Adresse, Ihren Tarif, das Pro-Enddatum, die maximale Dateigröße und die Blockgröße.
Uploads
Uploads sind fortsetzbar. Starten Sie einen Upload, senden Sie die Datei in Blöcken und schließen Sie ihn ab, um die Prüfung zu starten. Jede Datei wird angenommen: zip-, tar-, tar.gz/.tgz-, tar.bz2-, tar.xz-, gz-, bz2-, xz-, 7z- und RAR-Archive werden in der Sandbox entpackt (am Inhalt erkannt, nicht am Namen); jede andere Datei wird so geprüft, wie sie ist. Um mehrere einzelne Dateien zu prüfen, packen Sie sie in ein Archiv.
POST /uploads mit {"name": "site.zip", "size": 123456} → {"id", "chunk_size", "received"}
PUT /uploads/{id}?offset=N mit den Rohdaten des nächsten Blocks → {"received"}. Nach einem Netzwerkfehler zeigt GET /uploads/{id}, wo Sie fortfahren.
POST /uploads/{id}/finish → {"scan_id"}
Repository- & URL-Importe
POST /imports mit {"kind": "github", "source": "owner/repo", "ref": "main"} oder {"kind": "url", "source": "https://…"} → {"scan_id"}. Downloads laufen in einem eigenen Container, der nur öffentliche Internetadressen erreicht.
Website-Prüfungen (OWASP ZAP)
POST /website-scans mit {"url": "https://www.example.com/", "mode": "light"} → {"scan_id"}. light durchsucht die Website und führt passive Prüfungen ohne Angriffe aus. full ergänzt die aktive Prüfung und wird nur für Domains angenommen, die Sie auf der Seite Websites bestätigt haben. Der Bericht (/scans/{id}/report) enthält alerts mit Beschreibung, Lösung, Quellen, CWE und den betroffenen Adressen.
GET /domains listet Ihre Domains und ob ihre Inhaberschaft bestätigt ist.
Plattform-Integration (Service-API)
Für die eigenen Plattformen des Betreibers (Heimdall-Security.net, Netcore.Digital, Webservice.Digital, US24.net) gibt es Service-Tokens (hss_…), die ein Administrator unter Admin › Platform integrations erstellt. Ein Service-Client hat Scopes (scans, users, export, stats), eine optionale Liste erlaubter Quell-IPs (zum Beispiel den VPN-Bereich) und einen optionalen Webhook. Er nutzt denselben Header, X-Secscan-Token, und alle Endpunkte oben.
- Handelnder Benutzer. Ohne weitere Header handelt ein Service-Token als eigenes Servicekonto des Clients (Pro). Mit
X-Secscan-On-Behalf: <external id>(Scopeusers) handelt er als verknüpfter Plattform-Benutzer, mit dessen Tarif und Limits, sodass die Prüfungen in dessen Verlauf erscheinen. - GET
/service/info: Client, Plattform, Scopes und handelnder Benutzer. - PUT
/service/users/{external_id}mit{"email", "name", "plan": "free"|"pro", "pro_until": "YYYY-MM-DD"}legt einen Plattform-Benutzer an oder aktualisiert ihn und verknüpft ihn (ein bestehendes Konto mit derselben E-Mail-Adresse wird verknüpft, nicht dupliziert). GET liest ihn, DELETE löst die Verknüpfung (?delete_account=1löscht das Konto und seine Prüfungen). - GET
/service/users?after=&limit=und/service/scans?since=&cursor=&limit=(Scopeexport) blättern für eine Migration durch alle Konten und Prüfungen; fahren Sie mitnext_after/next_cursorfort, bis der Wertnullist./service/scans/{id}/reportliefert jeden vollständigen Bericht. - GET
/service/stats(Scopestats): Summen, Warteschlangenlänge und Benutzer. GET/healthbraucht keinen Token.
Webhooks
Wenn eine Prüfung des Servicekontos oder eines verknüpften Benutzers fertig ist, sendet secscan POST mit {"event": "scan.finished", "external_id", "scan": {…}, "report"} an die Webhook-Adresse des Clients (nur die eigenen Domains des Betreibers werden akzeptiert). Header: X-Secscan-Event, X-Secscan-Delivery (eindeutige ID: Wiederholungen ignorieren) und X-Secscan-Signature: t=<unix time>,v1=<hex>, der HMAC-SHA256 von "<t>.<raw body>" mit dem Webhook-Geheimnis. Antworten Sie innerhalb von 15 Sekunden mit einem beliebigen 2xx; andere Antworten werden nach 1, 5 und 15 Minuten wiederholt, danach stündlich bis zu 12 Stunden. POST /service/webhooks/test sendet ein ping.
// PHP: verify a webhook before trusting it
[$t, $v1] = sscanf($_SERVER['HTTP_X_SECSCAN_SIGNATURE'], 't=%d,v1=%64s');
$body = file_get_contents('php://input');
$ok = abs(time() - $t) < 300 && hash_equals(hash_hmac('sha256', "$t.$body", $secret), (string) $v1);
Prüfungen & Berichte
GET /scans listet Ihre Prüfungen.
GET /scans/{id} liefert den Status. Solange status den Wert queued hat, zeigt progress die aktuelle Phase, Zähler und neue Funde (übergeben Sie mit ?since= die zuletzt gesehene seq).
GET /scans/{id}/report liefert den vollständigen forensischen Bericht: Ergebnis, Funde mit Codeauszügen, Dateiverzeichnis mit Hashes, Engine-Versionen und Laufzeiten.
Erkennungsdaten
GET /data/manifest, /data/osv (Schwachstellendatenbank, SQLite) und /data/yara (YARA-Regelquellen mit ihren Lizenzen) nutzt die selbst gehostete CLI für lokale Prüfungen.
Selbst gehostete CLI
Pro-Nutzer können den secscan-Scanner auf eigenen Rechnern ausführen (Python 3.8+, ohne Abhängigkeiten). Er braucht einen API-Schlüssel und prüft ihn mindestens alle 7 Tage.
python3 secscan.py login # paste your API key (input hidden) python3 secscan.py update # download the detection data python3 secscan.py all ./project # scan locally python3 secscan.py remote scan ./project # scan on secscan servers and print the report
Beispiele
Eine Datei in einem Block hochladen (Dateien bis zur Blockgröße) und auf das Ergebnis warten:
ID=$(curl -s -H "X-Secscan-Token: $SECSCAN_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"site.zip","size":'$(stat -c%s site.zip)'}' https://one.heimdall-security.net/api/v1/uploads | jq -r .id)
curl -s -X PUT -H "X-Secscan-Token: $SECSCAN_TOKEN" --data-binary @site.zip "https://one.heimdall-security.net/api/v1/uploads/$ID?offset=0"
SCAN=$(curl -s -X POST -H "X-Secscan-Token: $SECSCAN_TOKEN" https://one.heimdall-security.net/api/v1/uploads/$ID/finish | jq -r .scan_id)
curl -s -H "X-Secscan-Token: $SECSCAN_TOKEN" https://one.heimdall-security.net/api/v1/scans/$SCAN | jq .status,.verdict
Python (Standardbibliothek):
import json, os, urllib.request
def api(method, path, body=None):
req = urllib.request.Request("https://one.heimdall-security.net/api/v1" + path, method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"X-Secscan-Token": os.environ["SECSCAN_TOKEN"], "Content-Type": "application/json"})
with urllib.request.urlopen(req) as r:
return json.load(r)
scan = api("POST", "/imports", {"kind": "github", "source": "octocat/Hello-World"})
print(api("GET", f"/scans/{scan['scan_id']}")["status"])