fix: show pre-forward auth verdict (authResultsOriginal) instead of misleading post-forward SPF/DKIM/DMARC in evidence card
This commit is contained in:
parent
cff57a414e
commit
952b63c8a4
1 changed files with 35 additions and 4 deletions
|
|
@ -38,7 +38,7 @@ export interface EvidenceMessageHeaders {
|
||||||
messageId: string | null;
|
messageId: string | null;
|
||||||
receivedChain: string[];
|
receivedChain: string[];
|
||||||
authResults: { spf?: string | null; dkim?: string | null; dmarc?: string | null };
|
authResults: { spf?: string | null; dkim?: string | null; dmarc?: string | null };
|
||||||
authResultsOriginal?: Record<string, unknown> | null;
|
authResultsOriginal?: { spf?: string | null; dkim?: string | null; dmarc?: string | null } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EvidenceAttachment {
|
export interface EvidenceAttachment {
|
||||||
|
|
@ -101,6 +101,28 @@ function authBadge(value: string | null | undefined) {
|
||||||
return <StatusBadge variantClass="bg-slate-500/15 text-slate-600">{normalized || 'none'}</StatusBadge>;
|
return <StatusBadge variantClass="bg-slate-500/15 text-slate-600">{normalized || 'none'}</StatusBadge>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mirrors campaign-classifier.ts's effectiveAuthResults(): the outer
|
||||||
|
* Authentication-Results header reflects the reporting/forwarding hop, not
|
||||||
|
* the reported message's real delivery — it's near-universally broken for
|
||||||
|
* tickets that came through Outlook's Report Message add-in. Prefer the
|
||||||
|
* pre-forward authResultsOriginal when captured; only fall back to the
|
||||||
|
* outer header when no original was recorded (e.g. a manually-forwarded or
|
||||||
|
* KnowBe4 PhishER-sourced ticket).
|
||||||
|
*/
|
||||||
|
function effectiveAuthResults(headers: EvidenceMessageHeaders | undefined): {
|
||||||
|
result: EvidenceMessageHeaders['authResults'];
|
||||||
|
isOriginal: boolean;
|
||||||
|
} {
|
||||||
|
if (!headers) {
|
||||||
|
return { result: {}, isOriginal: false };
|
||||||
|
}
|
||||||
|
if (headers.authResultsOriginal) {
|
||||||
|
return { result: headers.authResultsOriginal, isOriginal: true };
|
||||||
|
}
|
||||||
|
return { result: headers.authResults, isOriginal: false };
|
||||||
|
}
|
||||||
|
|
||||||
function recipientStatusBadge(status: string) {
|
function recipientStatusBadge(status: string) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'delivered':
|
case 'delivered':
|
||||||
|
|
@ -136,6 +158,8 @@ export function EvidenceCard({ messages, blastRadius }: EvidenceCardProps) {
|
||||||
[messages, selectedId],
|
[messages, selectedId],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const authResults = useMemo(() => effectiveAuthResults(message?.headers), [message]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|
@ -210,13 +234,20 @@ export function EvidenceCard({ messages, blastRadius }: EvidenceCardProps) {
|
||||||
<span className="font-mono text-xs truncate">{message.headers.messageId ?? '—'}</span>
|
<span className="font-mono text-xs truncate">{message.headers.messageId ?? '—'}</span>
|
||||||
|
|
||||||
<span className="text-muted-foreground">SPF</span>
|
<span className="text-muted-foreground">SPF</span>
|
||||||
<span>{authBadge(message.headers.authResults.spf)}</span>
|
<span>{authBadge(authResults.result.spf)}</span>
|
||||||
|
|
||||||
<span className="text-muted-foreground">DKIM</span>
|
<span className="text-muted-foreground">DKIM</span>
|
||||||
<span>{authBadge(message.headers.authResults.dkim)}</span>
|
<span>{authBadge(authResults.result.dkim)}</span>
|
||||||
|
|
||||||
<span className="text-muted-foreground">DMARC</span>
|
<span className="text-muted-foreground">DMARC</span>
|
||||||
<span>{authBadge(message.headers.authResults.dmarc)}</span>
|
<span>{authBadge(authResults.result.dmarc)}</span>
|
||||||
|
|
||||||
|
<span />
|
||||||
|
<span className="text-xs text-muted-foreground">
|
||||||
|
{authResults.isOriginal
|
||||||
|
? 'as verified at original delivery'
|
||||||
|
: 'as received (no pre-forward record)'}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{message.headers.receivedChain.length > 0 && (
|
{message.headers.receivedChain.length > 0 && (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue