import React, { useState } from 'react'; import { X, Key, Package, Copy, Send, Ban, FileText, Mail, Download, AlertTriangle } from '../icons'; import { useToast } from './Toasts/useToast'; import api from '../utils/api'; interface BountyEntry { id: number; timestamp: string; decky: string; service: string; attacker_ip: string; bounty_type: string; payload: any; } interface Props { bounty: BountyEntry; onClose: () => void; onSelectAttacker: (ip: string) => void; } const BountyInspector: React.FC = ({ bounty, onClose, onSelectAttacker }) => { const { push } = useToast(); const isCred = bounty.bounty_type === 'credential'; const isArt = bounty.bounty_type === 'artifact'; const p = bounty.payload || {}; const isMail = isArt && p.kind === 'mail'; const Icon = isCred ? Key : isMail ? Mail : isArt ? FileText : Package; const storedAs: string | undefined = isArt ? p.stored_as : undefined; const [downloading, setDownloading] = useState(false); const [dlError, setDlError] = useState(null); const copyJson = async () => { try { await navigator.clipboard.writeText(JSON.stringify(bounty, null, 2)); push({ text: 'JSON COPIED', tone: 'matrix', icon: 'copy' }); } catch { push({ text: 'CLIPBOARD BLOCKED', tone: 'alert', icon: 'alert-triangle' }); } }; const downloadArtifact = async () => { if (!storedAs) return; setDownloading(true); setDlError(null); try { const res = await api.get( `/artifacts/${encodeURIComponent(bounty.decky)}/${encodeURIComponent(storedAs)}?service=${encodeURIComponent(bounty.service)}`, { responseType: 'blob' }, ); const blobUrl = URL.createObjectURL(res.data); const a = document.createElement('a'); a.href = blobUrl; a.download = storedAs; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(blobUrl); } catch (err: any) { const status = err?.response?.status; setDlError( status === 403 ? 'Admin role required to download artifacts.' : status === 404 ? 'Artifact not found on disk (may have been purged).' : status === 400 ? 'Server rejected the request (invalid parameters).' : 'Download failed — see console.' ); console.error('artifact download failed', err); } finally { setDownloading(false); } }; const stubMisp = () => push({ text: 'MISP NOT CONFIGURED', tone: 'violet', icon: 'info' }); const stubBlocklist = () => push({ text: 'BLOCKLIST NOT WIRED', tone: 'violet', icon: 'info' }); return (
e.stopPropagation()}>

ARTIFACT #{bounty.id}

TYPE
{bounty.bounty_type.toUpperCase()}{isMail ? ' · MAIL' : ''}
TIMESTAMP
{new Date(bounty.timestamp).toLocaleString()}
DECKY
{bounty.decky}
SERVICE
{bounty.service}
ATTACKER
onSelectAttacker(bounty.attacker_ip)} > {bounty.attacker_ip}
{isCred ? 'CAPTURED CREDENTIAL' : isMail ? 'CAPTURED MESSAGE' : isArt ? 'CAPTURED FILE' : 'CAPTURED PAYLOAD'}
{isCred ? (
                username: {p.username}{'\n'}
                password: {p.password}
              
) : (
{JSON.stringify(p, null, 2)}
)}
{isArt && storedAs && (
RAW BYTES
Attacker-controlled content. Download at your own risk.
{dlError && (
{dlError}
)}
)}
EXPORT
); }; export default BountyInspector;