fix(evaluations): bypass Cloudflare 403 with browser headers + hardcoded fallback rounds

- Add browser User-Agent and Referer headers to all evals.mitre.org requests
- fetch_rounds_with_status() returns api_reachable flag + rounds list
- Fallback to 5 known public CrowdStrike rounds (APT29/R2 through OilRig/R6)
  when live API is blocked, so UI always shows something actionable
- Router returns {rounds, api_reachable, api_error} instead of plain array
- Frontend shows orange warning banner when using fallback data
- Remove 502 HTTPException - rounds are always returned (live or fallback)
This commit is contained in:
kitos
2026-06-05 16:10:27 +02:00
parent b037500b7c
commit 8515b8de17
4 changed files with 145 additions and 23 deletions
+25 -5
View File
@@ -39,6 +39,7 @@ import {
type SyncMitreResponse,
type IntelScanResponse,
type EvaluationRound,
type EvaluationRoundsResponse,
type EvaluationImportResult,
type NewRoundCheckResult,
} from "../api/system";
@@ -164,14 +165,18 @@ export default function SystemPage() {
// ── ATT&CK Evaluations queries & mutations ───────────────────────
const {
data: evalRounds,
data: evalRoundsData,
isLoading: evalRoundsLoading,
refetch: refetchEvalRounds,
} = useQuery<EvaluationRound[]>({
} = useQuery<EvaluationRoundsResponse>({
queryKey: ["eval-rounds"],
queryFn: listEvaluationRounds,
});
const evalRounds = evalRoundsData?.rounds;
const evalApiReachable = evalRoundsData?.api_reachable ?? true;
const evalApiError = evalRoundsData?.api_error ?? null;
const checkNewRoundMutation = useMutation({
mutationFn: checkNewEvaluationRound,
onSuccess: (data) => {
@@ -433,6 +438,19 @@ export default function SystemPage() {
</div>
</div>
{/* API fallback warning */}
{!evalApiReachable && evalApiError && (
<div className="mb-4 flex items-start gap-3 rounded-lg border border-orange-500/30 bg-orange-900/10 p-3">
<AlertCircle className="h-4 w-4 text-orange-400 flex-shrink-0 mt-0.5" />
<div className="text-xs text-orange-300">
<span className="font-medium">Live API unavailable</span>
{" — "}showing known public rounds (hardcoded). Importing will attempt to fetch
live results and may also fail if the API remains unreachable.
<span className="block mt-1 text-orange-400/70 font-mono truncate">{evalApiError}</span>
</div>
</div>
)}
{/* New round check result */}
{evalCheckResult && (
<div className={`mb-4 rounded-lg border p-3 ${
@@ -608,9 +626,11 @@ export default function SystemPage() {
</table>
</div>
) : (
<div className="flex items-center justify-center gap-2 py-8 text-gray-500 text-sm">
<AlertCircle className="h-4 w-4" />
<span>Unable to load evaluation rounds. Check network connectivity to evals.mitre.org.</span>
<div className="py-8 text-center">
<p className="text-sm text-gray-500">No evaluation rounds available.</p>
{evalApiError && (
<p className="mt-1 text-xs text-orange-400/70 font-mono">{evalApiError}</p>
)}
</div>
)}
</div>