Files
rea/tests/acceptance/localPathAdmissionCli.test.ts
dba8a31978 feat(elf): inspect Linux kernel module metadata (#7010)
* feat(elf): inspect Linux kernel module metadata

Adds inspect-kernel-module and inspect_kernel_module for ELF32/ELF64
ET_REL Linux kernel modules, read statically without executing them.
Reports ordered .modinfo entries with duplicates preserved, __versions
symbol CRCs, the presence of .gnu.linkonce.this_module and __ksymtab,
.init.text and .exit.text sizes, and an appended module signature
trailer with its PKCS#7 byte range and SHA-256. gzip, xz and zstd
containers are reported unsupported with external decompression as the
next probe. Malformed headers and exhausted entry budgets return no
partial success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix(elf): bound kernel module ksymtab listing and tighten contracts

Charge listed __ksymtab* sections against max_entries, omit section names
longer than 256 bytes with ksymtab_name_exceeds_limit, and aggregate the
non-file-backed limitation so repeated huge names cannot inflate Evidence.
Use fixedTupleSchema for the signature pad bytes with projection parity
tests, and assert the late-cancellation reason and retained observation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix: resolve merge integration errors

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-24 22:35:20 +08:00

143 lines
4.2 KiB
TypeScript

import { createHash } from "node:crypto";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { parseEvidence } from "../../src/domain/evidence.js";
import { pythonPycFixture } from "../../src/python/PythonPyc.fixture.js";
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
import { cliTest, runFileCli } from "../support/cli/cliFixture.js";
const fileCommands = [
"inspect-sqlite-database",
"inspect-python-pyc",
"inspect-apk-signature",
"inspect-packet-capture",
"decode-signal-recording",
"inspect-model-artifact",
"inspect-elf-notes",
"inspect-kernel-module",
"inspect-byte-entropy",
"inspect-pe-resources",
"inspect-pe-certificates",
"inspect-native-exports",
"inspect-binary-layout",
"inspect-recorded-crash",
"inspect-go-binary",
"inspect-rust-binary",
"inspect-gpu-code-objects",
"inspect-il2cpp-metadata",
] as const;
cliTest(
"rejects empty file selections before they can become the working directory",
async ({ cli }) => {
const cwd = await createTestTempDirectory("rea-empty-local-path-");
const selections = [
...fileCommands.map((command) => ({
arguments: [command, ""],
field: "path",
})),
{ arguments: ["inspect-evm-interface", "", "hex"], field: "path" },
{
arguments: ["inspect-web-network-capture", "", "har"],
field: "capturePath",
},
];
for (const selection of selections) {
const result = await runFileCli(cli, {
arguments: [...selection.arguments, "--json"],
cwd,
});
expect(result.exitCode, selection.arguments[0]).toBe(1);
expect(result.json, selection.arguments[0]).toMatchObject({
code: "VALIDATION_ERROR",
fieldErrors: expect.arrayContaining([
expect.objectContaining({
path: selection.field,
code: "too_small",
missing: false,
}),
]),
});
}
},
);
cliTest(
"rejects empty auxiliary selections and output destinations before reading inputs",
async ({ cli }) => {
const cwd = await createTestTempDirectory("rea-empty-auxiliary-path-");
const selections = [
{
arguments: ["inspect-il2cpp-metadata", "unread", "--binary", ""],
field: "binary",
},
{
arguments: ["inspect-il2cpp-metadata", "unread", "--ghidra-seeds", ""],
field: "ghidraSeeds",
},
{
arguments: [
"inspect-web-network-capture",
"unread",
"har",
"--protobuf-schema",
"",
],
field: "protobufSchema",
},
{
arguments: ["decompile-all", "unread", "--output", ""],
field: "output",
},
{ arguments: ["environment-export", "unread", ""], field: "directory" },
{
arguments: [
"environment-export",
"unread",
"output",
"--package-tarball",
"",
],
field: "packageTarball",
},
];
for (const selection of selections) {
const result = await runFileCli(cli, {
arguments: [...selection.arguments, "--json"],
cwd,
});
expect(result.exitCode, selection.field).toBe(1);
expect(result.json, selection.field).toMatchObject({
code: "VALIDATION_ERROR",
fieldErrors: expect.arrayContaining([
expect.objectContaining({ path: selection.field, code: "too_small" }),
]),
});
}
},
);
cliTest(
"still inspects an explicit relative file with its exact digest",
async ({ cli }) => {
const cwd = await createTestTempDirectory("rea-relative-local-path-");
const bytes = pythonPycFixture();
const path = join(cwd, "selected.pyc");
await writeFile(path, bytes);
const result = await runFileCli(cli, {
arguments: ["inspect-python-pyc", "./selected.pyc", "--json"],
cwd,
});
expect(result.exitCode, result.stderr).toBe(0);
expect(parseEvidence(result.json)).toMatchObject({
operation: "inspect_python_pyc",
subject: {
local_path: path,
digest: { sha256: createHash("sha256").update(bytes).digest("hex") },
},
});
},
);