From fbe09f84dfab440f02b8f598a2653dceb3fb4680 Mon Sep 17 00:00:00 2001 From: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com> Date: Wed, 11 Nov 2026 00:45:50 +0000 Subject: [PATCH] fix(artifacts): verify MFT source before publishing metadata Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> --- src/artifacts/NtfsMftArtifactReader.test.ts | 27 ++++++++++++++++++++- src/artifacts/NtfsMftArtifactReader.ts | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/artifacts/NtfsMftArtifactReader.test.ts b/src/artifacts/NtfsMftArtifactReader.test.ts index 4f53a31e0c..ba08231d99 100644 --- a/src/artifacts/NtfsMftArtifactReader.test.ts +++ b/src/artifacts/NtfsMftArtifactReader.test.ts @@ -1,7 +1,10 @@ import { writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { expect, it } from "vitest"; +import { expect, it, vi } from "vitest"; + +import { ArtifactFileSource } from "./ArtifactFileSource.js"; +import { NtfsMftArtifactReader } from "./NtfsMftArtifactReader.js"; import { MFT_DEFAULT_RECORD_BYTES } from "../domain/windows/ntfsMft.js"; import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js"; @@ -98,3 +101,25 @@ it("reports incomplete coverage when FILE extents contradict the record slots", fixup_unverified_record_count: 0, }); }); + +it("does not publish metadata when final source verification fails", async () => { + const reader = new NtfsMftArtifactReader( + await writeMft("$MFT", recordBytes({})), + ); + const read = ArtifactFileSource.prototype.read; + const spy = vi + .spyOn(ArtifactFileSource.prototype, "read") + .mockImplementationOnce(function (this: ArtifactFileSource, signal) { + return read.call(this, signal); + }) + .mockRejectedValueOnce(new Error("final source verification failed")); + try { + await expect(reader.entries().next()).rejects.toThrow( + "final source verification failed", + ); + expect(reader.formatMetadata()).toBeUndefined(); + } finally { + spy.mockRestore(); + await reader.close(); + } +}); diff --git a/src/artifacts/NtfsMftArtifactReader.ts b/src/artifacts/NtfsMftArtifactReader.ts index d69df419ec..3b4bf97a82 100644 --- a/src/artifacts/NtfsMftArtifactReader.ts +++ b/src/artifacts/NtfsMftArtifactReader.ts @@ -93,9 +93,9 @@ export class NtfsMftArtifactReader implements ArtifactReader { async #prepare(signal?: AbortSignal): Promise { const image = await this.#decode(signal); + await this.#source.read(signal); this.#metadata = image.metadata; this.#limitations = image.limitations; - await this.#source.read(signal); } async #decode(signal?: AbortSignal): Promise {