[GH-ISSUE #138] MachOSliceArtifactReader.provenance() returns mutable internal command state #86

Closed
opened 2026-10-15 18:20:59 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Jul 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/138

Problem

MachOSliceArtifactReader.provenance() returns an array and command object that aliases internal state. Mutating that array/object changes the internal provenance record for the reader.

Reproduction

import { MachOSliceArtifactReader } from "./dist/artifacts/MachOSliceArtifactReader.js";
import { ok } from "./dist/domain/result.js";

const output = `\narchitecture x86_64\noffset 0\nsize 12\n`;
const reader = new MachOSliceArtifactReader("/bin/sample", {
  run: async () => ok({
    tool: "lipo",
    executable: "/usr/bin/lipo",
    executableSha256: "sha256",
    toolVersion: null,
    versionReason: null,
    arguments: ["lipo"],
    stdout: output,
    stderr: "",
    stdoutBytes: output.length,
    stderrBytes: 0,
    stdoutTruncated: false,
    stderrTruncated: false,
    exitCode: 0,
    signal: null,
  }),
});

for await (const _ of reader.entries()) {
  break;
}

const provenance = reader.provenance();
provenance[0].tool = "/tmp/fake-lipo";
provenance.push({
  tool: "/tmp/added",
  arguments: ["spoofed"],
  tool_version: null,
  executable_sha256: null,
  exit_code: 0,
  effects: ["read"],
});

console.log(reader.provenance());

Impact

A caller can replace and append provenance commands after slice inspection, which can corrupt evidence provenance metadata and downstream trust decisions.

Expected behavior

Return cloned provenance entries (and cloned command objects) from provenance().

Originally created by @morluto on GitHub (Jul 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/138 ## Problem `MachOSliceArtifactReader.provenance()` returns an array and command object that aliases internal state. Mutating that array/object changes the internal provenance record for the reader. ## Reproduction ```ts import { MachOSliceArtifactReader } from "./dist/artifacts/MachOSliceArtifactReader.js"; import { ok } from "./dist/domain/result.js"; const output = `\narchitecture x86_64\noffset 0\nsize 12\n`; const reader = new MachOSliceArtifactReader("/bin/sample", { run: async () => ok({ tool: "lipo", executable: "/usr/bin/lipo", executableSha256: "sha256", toolVersion: null, versionReason: null, arguments: ["lipo"], stdout: output, stderr: "", stdoutBytes: output.length, stderrBytes: 0, stdoutTruncated: false, stderrTruncated: false, exitCode: 0, signal: null, }), }); for await (const _ of reader.entries()) { break; } const provenance = reader.provenance(); provenance[0].tool = "/tmp/fake-lipo"; provenance.push({ tool: "/tmp/added", arguments: ["spoofed"], tool_version: null, executable_sha256: null, exit_code: 0, effects: ["read"], }); console.log(reader.provenance()); ``` ## Impact A caller can replace and append provenance commands after slice inspection, which can corrupt evidence provenance metadata and downstream trust decisions. ## Expected behavior Return cloned provenance entries (and cloned command objects) from `provenance()`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#86
No description provided.