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;
|
||||
receivedChain: string[];
|
||||
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 {
|
||||
|
|
@ -101,6 +101,28 @@ function authBadge(value: string | null | undefined) {
|
|||
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) {
|
||||
switch (status) {
|
||||
case 'delivered':
|
||||
|
|
@ -136,6 +158,8 @@ export function EvidenceCard({ messages, blastRadius }: EvidenceCardProps) {
|
|||
[messages, selectedId],
|
||||
);
|
||||
|
||||
const authResults = useMemo(() => effectiveAuthResults(message?.headers), [message]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
|
@ -210,13 +234,20 @@ export function EvidenceCard({ messages, blastRadius }: EvidenceCardProps) {
|
|||
<span className="font-mono text-xs truncate">{message.headers.messageId ?? '—'}</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>{authBadge(message.headers.authResults.dkim)}</span>
|
||||
<span>{authBadge(authResults.result.dkim)}</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>
|
||||
|
||||
{message.headers.receivedChain.length > 0 && (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue