Dateien nach "/" hochladen
This commit is contained in:
1 parent
978527baaa
commit
c53a1b86c5
1 file changed
+110
-41
@@ -93,7 +93,6 @@ def requires_auth(f):
|
||||
# Rate-Limiting (pro Client-IP, in-memory – reicht für einen einzelnen Prozess)
|
||||
# --------------------------------------------------------------------------- #
|
||||
def client_ip() -> str:
|
||||
# Wenn hinter einem Reverse Proxy: X-Forwarded-For des Proxys vertrauen.
|
||||
fwd = request.headers.get("X-Forwarded-For")
|
||||
return fwd.split(",")[0].strip() if fwd else request.remote_addr or "unknown"
|
||||
|
||||
@@ -139,57 +138,127 @@ def is_public_target(url: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Design im Stil von software.obraasch.de: dunkler Header, orange Akzente,
|
||||
# helle Cards.
|
||||
# --------------------------------------------------------------------------- #
|
||||
PAGE = """
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>SkillSpector</title>
|
||||
<style>
|
||||
body{font-family:sans-serif;max-width:820px;margin:40px auto;padding:0 16px;background:#111;color:#eee}
|
||||
input,button{width:100%;padding:9px;margin:6px 0;box-sizing:border-box;font-size:1em}
|
||||
input[type=checkbox]{width:auto;display:inline}
|
||||
button{background:#2ecc71;color:#000;border:none;cursor:pointer;font-weight:bold;padding:10px}
|
||||
pre{background:#000;padding:12px;overflow-x:auto;white-space:pre-wrap;border-radius:6px}
|
||||
.score{font-size:1.8em;font-weight:bold;margin:12px 0}
|
||||
.SAFE{color:#4caf50}.CAUTION{color:#ffb300}.DO_NOT_INSTALL{color:#f44336}
|
||||
label{display:block;margin-top:14px;font-size:.9em;color:#bbb}
|
||||
.err{color:#f44336;font-weight:bold}
|
||||
.notice{font-size:.85em;color:#999;margin-top:24px;border-top:1px solid #333;padding-top:12px}
|
||||
hr{border-color:#333}
|
||||
a{color:#6cf}
|
||||
:root{
|
||||
--orange:#f2731e;
|
||||
--orange-dark:#d9601a;
|
||||
--bg:#eef1f4;
|
||||
--card:#ffffff;
|
||||
--ink:#1a1d21;
|
||||
--ink-soft:#5b6470;
|
||||
--border:#e2e6ea;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0;font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
|
||||
background:var(--bg);color:var(--ink);
|
||||
}
|
||||
header{
|
||||
background:#0d0e10;padding:28px 24px;
|
||||
}
|
||||
.header-inner{max-width:760px;margin:0 auto}
|
||||
.logo{font-size:1.9em;font-weight:800;letter-spacing:.5px;margin:0}
|
||||
.logo .accent{color:var(--orange)}
|
||||
.subtitle{color:#9aa2ab;margin:6px 0 0;font-size:.95em}
|
||||
main{max-width:760px;margin:32px auto;padding:0 24px 48px}
|
||||
.card{
|
||||
background:var(--card);border:1px solid var(--border);border-radius:14px;
|
||||
padding:28px;margin-bottom:24px;box-shadow:0 1px 2px rgba(0,0,0,.03);
|
||||
}
|
||||
label{display:block;margin-top:16px;font-size:.85em;color:var(--ink-soft);font-weight:600}
|
||||
input[type=text],input[type=file]{
|
||||
width:100%;padding:11px 12px;margin-top:6px;border:1px solid var(--border);
|
||||
border-radius:9px;font-size:.95em;background:#fbfcfd;
|
||||
}
|
||||
input[type=text]:focus{outline:2px solid var(--orange);border-color:var(--orange)}
|
||||
.checkbox-row{display:flex;align-items:flex-start;gap:8px;margin-top:16px}
|
||||
.checkbox-row input{width:auto;margin-top:2px}
|
||||
.checkbox-row label{margin:0;font-weight:400;color:var(--ink-soft)}
|
||||
button{
|
||||
margin-top:20px;padding:12px 20px;border:none;border-radius:9px;
|
||||
background:var(--orange);color:#fff;font-weight:700;font-size:.95em;
|
||||
cursor:pointer;transition:background .15s;
|
||||
}
|
||||
button:hover{background:var(--orange-dark)}
|
||||
.badge{
|
||||
display:inline-block;padding:4px 12px;border-radius:999px;font-size:.8em;
|
||||
font-weight:700;border:1px solid transparent;
|
||||
}
|
||||
.badge.SAFE{background:#e8f7ee;color:#1e8e4a;border-color:#c6ebd3}
|
||||
.badge.CAUTION{background:#fff4e0;color:#b5720a;border-color:#ffe3ad}
|
||||
.badge.DO_NOT_INSTALL{background:#fdecec;color:#c62828;border-color:#f9cccc}
|
||||
.score-row{display:flex;align-items:center;gap:12px;margin-bottom:16px}
|
||||
.score-num{font-size:1.9em;font-weight:800}
|
||||
pre{
|
||||
background:#14161a;color:#d7dbe0;padding:16px;border-radius:10px;
|
||||
overflow-x:auto;white-space:pre-wrap;font-size:.82em;line-height:1.5;
|
||||
}
|
||||
.err{
|
||||
background:#fdecec;color:#c62828;border:1px solid #f9cccc;border-radius:10px;
|
||||
padding:14px 16px;font-weight:600;
|
||||
}
|
||||
.notice{color:var(--ink-soft);font-size:.85em;margin-top:8px}
|
||||
footer{
|
||||
max-width:760px;margin:0 auto;padding:0 24px 40px;color:#9aa2ab;font-size:.85em;
|
||||
}
|
||||
a{color:var(--orange)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔍 SkillSpector</h1>
|
||||
<p>Scannt einen Skill (Git-Repo oder ZIP) auf Sicherheitsrisiken, <strong>bevor</strong> er installiert wird.
|
||||
Basiert auf <a href="https://github.com/NVIDIA/SkillSpector" target="_blank">NVIDIA SkillSpector</a> (Apache-2.0).</p>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<label>Git-Repository-URL (nur öffentlich erreichbares http/https)</label>
|
||||
<input type="text" name="git_url" placeholder="https://git.obraasch.de/olli1986/mein-skill">
|
||||
<label>...oder ZIP-Datei hochladen (max. 50 MB)</label>
|
||||
<input type="file" name="zip_file" accept=".zip">
|
||||
{% if allow_llm %}
|
||||
<label><input type="checkbox" name="use_llm"> LLM-Analyse aktivieren (sendet Dateiinhalte des Skills an den konfigurierten KI-Anbieter – genauer, aber nicht mehr rein lokal)</label>
|
||||
<header>
|
||||
<div class="header-inner">
|
||||
<p class="logo">SKILL<span class="accent">SPECTOR</span></p>
|
||||
<p class="subtitle">Sicherheits-Scanner für AI-Agent-Skills – vor dem Installieren prüfen</p>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="card">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<label>Git-Repository-URL</label>
|
||||
<input type="text" name="git_url" placeholder="https://git.obraasch.de/olli1986/mein-skill">
|
||||
<label>...oder ZIP-Datei hochladen (max. 50 MB)</label>
|
||||
<input type="file" name="zip_file" accept=".zip">
|
||||
{% if allow_llm %}
|
||||
<div class="checkbox-row">
|
||||
<input type="checkbox" name="use_llm" id="use_llm">
|
||||
<label for="use_llm">LLM-Analyse aktivieren (sendet Dateiinhalte an den konfigurierten KI-Anbieter)</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Scan starten</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if result %}
|
||||
<div class="card">
|
||||
<div class="score-row">
|
||||
<span class="score-num">{{ result.risk_assessment.score }}/100</span>
|
||||
<span class="badge {{ result.risk_assessment.recommendation }}">{{ result.risk_assessment.recommendation }}</span>
|
||||
</div>
|
||||
<pre>{{ result_json }}</pre>
|
||||
</div>
|
||||
{% elif error %}
|
||||
<div class="card">
|
||||
<p class="err">{{ error }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Scan starten</button>
|
||||
</form>
|
||||
<hr>
|
||||
{% if result %}
|
||||
<h2>Ergebnis</h2>
|
||||
<p class="score {{ result.risk_assessment.recommendation }}">
|
||||
{{ result.risk_assessment.score }}/100 — {{ result.risk_assessment.severity }} — {{ result.risk_assessment.recommendation }}
|
||||
</p>
|
||||
<pre>{{ result_json }}</pre>
|
||||
{% elif error %}
|
||||
<p class="err">{{ error }}</p>
|
||||
{% endif %}
|
||||
<p class="notice">
|
||||
Statische Analyse läuft immer lokal. {% if allow_llm %}Bei aktivierter LLM-Analyse werden
|
||||
Dateiinhalte an einen externen KI-Anbieter übertragen.{% endif %}
|
||||
Der gescannte Skill wird zu keinem Zeitpunkt ausgeführt. Kein Ergebnis wird dauerhaft
|
||||
gespeichert – es erscheint nur auf dieser Seite.
|
||||
</p>
|
||||
</main>
|
||||
<footer>
|
||||
Läuft auf <a href="https://github.com/NVIDIA/SkillSpector" target="_blank">NVIDIA SkillSpector</a>
|
||||
(Apache-2.0). Statische Analyse läuft immer lokal
|
||||
{% if allow_llm %}– bei aktivierter LLM-Analyse werden Dateiinhalte extern übertragen{% endif %}.
|
||||
Der gescannte Skill wird nie ausgeführt, kein Ergebnis wird dauerhaft gespeichert.
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
Reference in new issue
Block a user