Dateien nach "/" hochladen
This commit is contained in:
1 parent
2e525989f7
commit
929c3f8c95
1 file changed
+121
-1
@@ -138,6 +138,68 @@ def is_public_target(url: str) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Rohreport lesbar aufbereiten: nach Severity gruppieren, Feldnamen
|
||||||
|
# vereinheitlichen (SkillSpector nennt Detail-Felder je Version leicht anders).
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]
|
||||||
|
SEVERITY_LABELS_DE = {
|
||||||
|
"CRITICAL": "Kritisch",
|
||||||
|
"HIGH": "Hoch",
|
||||||
|
"MEDIUM": "Mittel",
|
||||||
|
"LOW": "Niedrig",
|
||||||
|
"INFO": "Info",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_issues(raw_issues: list) -> dict:
|
||||||
|
grouped: dict[str, list] = {}
|
||||||
|
for issue in raw_issues or []:
|
||||||
|
severity = str(issue.get("severity", "INFO")).upper()
|
||||||
|
location = issue.get("location") or {}
|
||||||
|
confidence = issue.get("confidence")
|
||||||
|
if isinstance(confidence, (int, float)) and confidence <= 1:
|
||||||
|
confidence_display = f"{round(confidence * 100)}%"
|
||||||
|
else:
|
||||||
|
confidence_display = confidence
|
||||||
|
grouped.setdefault(severity, []).append(
|
||||||
|
{
|
||||||
|
"id": issue.get("id") or issue.get("rule_id") or "?",
|
||||||
|
"category": issue.get("category") or issue.get("type") or "",
|
||||||
|
"message": (
|
||||||
|
issue.get("finding")
|
||||||
|
or issue.get("message")
|
||||||
|
or issue.get("description")
|
||||||
|
or issue.get("title")
|
||||||
|
or ""
|
||||||
|
),
|
||||||
|
"explanation": issue.get("explanation") or issue.get("rationale") or "",
|
||||||
|
"file": location.get("file") or location.get("path") or "",
|
||||||
|
"line": location.get("start_line") or location.get("line") or "",
|
||||||
|
"confidence": confidence_display,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
ordered = {lvl: grouped[lvl] for lvl in SEVERITY_ORDER if lvl in grouped}
|
||||||
|
for lvl, items in grouped.items():
|
||||||
|
if lvl not in ordered:
|
||||||
|
ordered[lvl] = items
|
||||||
|
return ordered
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_components(raw_components: list) -> list:
|
||||||
|
normalized = []
|
||||||
|
for c in raw_components or []:
|
||||||
|
normalized.append(
|
||||||
|
{
|
||||||
|
"file": c.get("path") or c.get("file") or c.get("name") or "-",
|
||||||
|
"type": c.get("type") or c.get("kind") or "-",
|
||||||
|
"lines": c.get("lines") or c.get("line_count") or "-",
|
||||||
|
"executable": bool(c.get("executable")),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return normalized
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# Design im Stil von software.obraasch.de: dunkler Header, orange Akzente,
|
# Design im Stil von software.obraasch.de: dunkler Header, orange Akzente,
|
||||||
# helle Cards.
|
# helle Cards.
|
||||||
@@ -209,6 +271,19 @@ pre{
|
|||||||
padding:14px 16px;font-weight:600;
|
padding:14px 16px;font-weight:600;
|
||||||
}
|
}
|
||||||
.notice{color:var(--ink-soft);font-size:.85em;margin-top:8px}
|
.notice{color:var(--ink-soft);font-size:.85em;margin-top:8px}
|
||||||
|
.sev-heading{margin:0 0 14px;font-size:1.05em;font-weight:800;padding-bottom:8px;border-bottom:1px solid var(--border)}
|
||||||
|
.sev-CRITICAL{color:#c62828}.sev-HIGH{color:#d9601a}.sev-MEDIUM{color:#b5720a}.sev-LOW{color:#5b6470}.sev-INFO{color:#5b6470}
|
||||||
|
.issue{padding:14px 0;border-bottom:1px solid var(--border)}
|
||||||
|
.issue:last-child{border-bottom:none;padding-bottom:0}
|
||||||
|
.issue-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:.8em;color:var(--ink-soft);font-weight:700;text-transform:uppercase;letter-spacing:.3px}
|
||||||
|
.issue-msg{margin:6px 0 4px;font-weight:600}
|
||||||
|
.issue-loc{margin:0 0 4px;font-family:monospace;font-size:.85em;color:var(--ink-soft)}
|
||||||
|
.issue-expl{margin:4px 0 0;font-size:.9em;color:var(--ink-soft)}
|
||||||
|
.comp-table{width:100%;border-collapse:collapse;font-size:.88em}
|
||||||
|
.comp-table th{text-align:left;color:var(--ink-soft);font-weight:700;padding:6px 8px;border-bottom:1px solid var(--border)}
|
||||||
|
.comp-table td{padding:6px 8px;border-bottom:1px solid var(--border);font-family:monospace}
|
||||||
|
details summary{cursor:pointer;font-weight:700;color:var(--ink-soft)}
|
||||||
|
details pre{margin-top:14px}
|
||||||
footer{
|
footer{
|
||||||
max-width:760px;margin:0 auto;padding:0 24px 40px;color:#9aa2ab;font-size:.85em;
|
max-width:760px;margin:0 auto;padding:0 24px 40px;color:#9aa2ab;font-size:.85em;
|
||||||
}
|
}
|
||||||
@@ -245,8 +320,49 @@ a{color:var(--orange)}
|
|||||||
<span class="score-num">{{ result.risk_assessment.score }}/100</span>
|
<span class="score-num">{{ result.risk_assessment.score }}/100</span>
|
||||||
<span class="badge {{ result.risk_assessment.recommendation }}">{{ result.risk_assessment.recommendation }}</span>
|
<span class="badge {{ result.risk_assessment.recommendation }}">{{ result.risk_assessment.recommendation }}</span>
|
||||||
</div>
|
</div>
|
||||||
<pre>{{ result_json }}</pre>
|
{% if not issues_by_severity %}
|
||||||
|
<p class="notice">Keine Funde – das Ergebnis unten (Rohdaten) bestätigt das im Detail.</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% for severity, items in issues_by_severity.items() %}
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="sev-heading sev-{{ severity }}">{{ severity_labels.get(severity, severity) }} ({{ items|length }})</h3>
|
||||||
|
{% for issue in items %}
|
||||||
|
<div class="issue">
|
||||||
|
<div class="issue-head">
|
||||||
|
<span>{{ issue.category }}</span>
|
||||||
|
{% if issue.confidence %}<span>Konfidenz: {{ issue.confidence }}</span>{% endif %}
|
||||||
|
</div>
|
||||||
|
<p class="issue-msg">{{ issue.message }}</p>
|
||||||
|
{% if issue.file %}<p class="issue-loc">{{ issue.file }}{% if issue.line %}:{{ issue.line }}{% endif %}</p>{% endif %}
|
||||||
|
{% if issue.explanation %}<p class="issue-expl">{{ issue.explanation }}</p>{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if components %}
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="sev-heading">Gescannte Komponenten ({{ components|length }})</h3>
|
||||||
|
<table class="comp-table">
|
||||||
|
<tr><th>Datei</th><th>Typ</th><th>Zeilen</th><th>Ausführbar</th></tr>
|
||||||
|
{% for c in components %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ c.file }}</td>
|
||||||
|
<td>{{ c.type }}</td>
|
||||||
|
<td>{{ c.lines }}</td>
|
||||||
|
<td>{{ 'ja' if c.executable else 'nein' }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<details class="card">
|
||||||
|
<summary>Rohdaten (vollständiges JSON)</summary>
|
||||||
|
<pre>{{ result_json }}</pre>
|
||||||
|
</details>
|
||||||
{% elif error %}
|
{% elif error %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<p class="err">{{ error }}</p>
|
<p class="err">{{ error }}</p>
|
||||||
@@ -329,10 +445,14 @@ def index():
|
|||||||
|
|
||||||
if report_path.exists():
|
if report_path.exists():
|
||||||
result = json.loads(report_path.read_text())
|
result = json.loads(report_path.read_text())
|
||||||
|
raw_issues = result.get("issues") or result.get("findings") or []
|
||||||
return render_template_string(
|
return render_template_string(
|
||||||
PAGE,
|
PAGE,
|
||||||
allow_llm=ALLOW_LLM,
|
allow_llm=ALLOW_LLM,
|
||||||
result=result,
|
result=result,
|
||||||
|
issues_by_severity=normalize_issues(raw_issues),
|
||||||
|
components=normalize_components(result.get("components", [])),
|
||||||
|
severity_labels=SEVERITY_LABELS_DE,
|
||||||
result_json=json.dumps(result, indent=2, ensure_ascii=False),
|
result_json=json.dumps(result, indent=2, ensure_ascii=False),
|
||||||
error=None,
|
error=None,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in new issue
Block a user