[GH-ISSUE #135] EvidenceLedger.export() returns mutable internal objects #83

Closed
opened 2026-10-15 18:20:57 +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/135

Problem

EvidenceLedger.export() currently returns a bundle backed by internal ledger object references, so callers can mutate returned evidence records/unknowns and corrupt future ledger reads.

EvidenceLedger.listUnknowns and lookup APIs are already covered by #130; this issue is specifically about export/import bundle surfaces.

Reproduction

import { EvidenceLedger } from './dist/application/EvidenceLedger.js';
import { createEvidence } from './dist/domain/evidence.js';

const TARGET = {
  path: '/tmp/fixture',
  sha256: 'a'.repeat(64),
  kind: 'executable',
  format: 'mach-o',
  architecture: 'arm64',
  availableArchitectures: ['arm64'],
  loaderArgs: ['-l', 'Mach-O'],
};
const PROVIDER = { id: 'fixture', name: 'Fixture', version: '1' };

const ledger = new EvidenceLedger({ maxRecords: 10, maxBytes: 1024 * 1024 });
const evidence = createEvidence(TARGET, PROVIDER, {
  operation: 'health',
  parameters: { hello: 'world' },
  result: true,
});
console.log('record', ledger.record(evidence));

const before = ledger.export();
before.records[0].operation = 'forged';
before.records[0].normalized_result = { tampered: true };

const after = ledger.export().records[0];
console.log(after.operation, after.normalized_result); // forged + tampered

Expected

ledger.export() should return detached, immutable data, so caller mutation cannot affect internal state.

Actual

Mutating the returned bundle directly mutates the in-memory ledger state and future exports.

Impact

A caller with access to export output can forge evidence fields after they were recorded.

File

  • src/application/EvidenceLedger.ts
Originally created by @morluto on GitHub (Jul 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/135 ### Problem `EvidenceLedger.export()` currently returns a bundle backed by internal ledger object references, so callers can mutate returned evidence records/unknowns and corrupt future ledger reads. `EvidenceLedger.listUnknowns` and lookup APIs are already covered by #130; this issue is specifically about export/import bundle surfaces. ### Reproduction ```ts import { EvidenceLedger } from './dist/application/EvidenceLedger.js'; import { createEvidence } from './dist/domain/evidence.js'; const TARGET = { path: '/tmp/fixture', sha256: 'a'.repeat(64), kind: 'executable', format: 'mach-o', architecture: 'arm64', availableArchitectures: ['arm64'], loaderArgs: ['-l', 'Mach-O'], }; const PROVIDER = { id: 'fixture', name: 'Fixture', version: '1' }; const ledger = new EvidenceLedger({ maxRecords: 10, maxBytes: 1024 * 1024 }); const evidence = createEvidence(TARGET, PROVIDER, { operation: 'health', parameters: { hello: 'world' }, result: true, }); console.log('record', ledger.record(evidence)); const before = ledger.export(); before.records[0].operation = 'forged'; before.records[0].normalized_result = { tampered: true }; const after = ledger.export().records[0]; console.log(after.operation, after.normalized_result); // forged + tampered ``` ### Expected `ledger.export()` should return detached, immutable data, so caller mutation cannot affect internal state. ### Actual Mutating the returned bundle directly mutates the in-memory ledger state and future exports. ### Impact A caller with access to export output can forge evidence fields after they were recorded. ### File - src/application/EvidenceLedger.ts
bsakaguchi 2026-10-15 18:20:57 +00:00
  • closed this issue
  • added the
    bug
    label
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#83
No description provided.