mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 18:22:42 +00:00
feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts * feat(analysis): expose ASAR and Ghidra runtime admission controls * feat(artifacts): expose reader admission and preserve limited recognition * feat(javascript): expose recoverable semantic precision budgets * feat(web): add recoverable source-map budgets and compact retained views * feat(web): make historical capture decoding budgets recoverable * fix(desktop): enforce selected view policies across capture and export * feat(runtime): make Frida and LLDB retention budgets selectable * feat(native): expose diagnostic budgets and preserve exhaustion causes * feat(managed): expose recoverable snapshot and representation budgets * feat(metadata): make Go and Rust inspection budgets recoverable * feat(wasm): expose representation and producer admissions * feat(evm): expose per-call worker resource budgets * feat(android): make resource and string-pool omissions recoverable * feat(producers): expose command and recorded-capture budgets * docs(analysis): record recovery contracts and integrated validation * fix(docs): link calibration oracle from published verification pages * fix(docs): restore desktop task anchors and receipt links * test(analysis): align fixtures with selectable budget contracts * fix(analysis): remove source-location projector dependency cycle * test(analysis): refresh budget recovery and verifier regressions * test(analysis): preserve format and publication recovery expectations * test(windows): align conformance with owned runtime admission * fix(desktop): preserve selected alias kinds in exported state * test(analysis): align provider fixtures with recoverable budgets * test(desktop): validate emitted alias metadata structurally * fix(ghidra): classify bounded Windows endpoint refusals * test(cli): assert selectable artifact admission recovery * fix(cli): preserve capture provenance in environment builds
This commit is contained in:
1 parent
55b6d2ca20
commit
cb4e5cfbff
515 files changed
+21066
-3637
No files matched your search
@@ -93,6 +93,9 @@ export class BinaryLayoutService {
|
||||
operation: OPERATION,
|
||||
parameters: {
|
||||
path: input.value.path,
|
||||
...(input.value.producer_limits === undefined
|
||||
? {}
|
||||
: { producer_limits: input.value.producer_limits }),
|
||||
...(input.value.pwntools_timeout_ms === undefined
|
||||
? {}
|
||||
: { pwntools_timeout_ms: input.value.pwntools_timeout_ms }),
|
||||
|
||||
@@ -67,7 +67,7 @@ const report: KernelModule = {
|
||||
limitations: ["Kernel module metadata was not executed."],
|
||||
};
|
||||
|
||||
it("rejects a relative path and extra arguments before reading", async () => {
|
||||
it("rejects relative paths, extra arguments and invalid field budgets before reading", async () => {
|
||||
let calls = 0;
|
||||
const service = new KernelModuleService({
|
||||
identity,
|
||||
@@ -85,6 +85,20 @@ it("rejects a relative path and extra arguments before reading", async () => {
|
||||
expect(extra.ok).toBe(false);
|
||||
if (!relative.ok) expect(relative.error).toBeInstanceOf(AnalysisInputError);
|
||||
if (!extra.ok) expect(extra.error).toBeInstanceOf(AnalysisInputError);
|
||||
for (const budget of ["max_modinfo_key_bytes", "max_modinfo_value_bytes"]) {
|
||||
for (const value of [0, 536870913]) {
|
||||
const invalid = await service.inspect({
|
||||
path: report.artifact.path,
|
||||
[budget]: value,
|
||||
});
|
||||
expect(invalid.ok).toBe(false);
|
||||
if (!invalid.ok)
|
||||
expect(invalid.error).toMatchObject({
|
||||
_tag: "AnalysisInputError",
|
||||
issues: [expect.objectContaining({ path: [budget] })],
|
||||
});
|
||||
}
|
||||
}
|
||||
expect(calls).toBe(0);
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
MODULE_SIGNATURE_MAGIC,
|
||||
MODULE_SIGNATURE_PKCS7_ID_TYPE,
|
||||
type KernelModule,
|
||||
type InspectKernelModuleInput,
|
||||
} from "../../domain/native/kernelModule.js";
|
||||
import { BINARY_ARCHITECTURES } from "../../domain/binaryTargetTypes.js";
|
||||
import { elfArchitecture } from "../../domain/elfFixedHeader.js";
|
||||
@@ -49,11 +50,7 @@ export class KernelModuleService {
|
||||
if (
|
||||
!report.success ||
|
||||
report.data.artifact.path !== input.value.path ||
|
||||
!validReport(
|
||||
report.data,
|
||||
input.value.max_entries,
|
||||
input.value.max_file_bytes,
|
||||
)
|
||||
!validReport(report.data, input.value)
|
||||
)
|
||||
return err(
|
||||
new AnalysisOutputError(
|
||||
@@ -124,6 +121,7 @@ const rangesOf = (report: KernelModule): Range[] => {
|
||||
|
||||
const modinfoConsistent = (
|
||||
modinfo: NonNullable<KernelModule["modinfo"]>,
|
||||
input: InspectKernelModuleInput,
|
||||
): boolean => {
|
||||
const closed =
|
||||
modinfo.status === "malformed" || modinfo.status === "unsupported";
|
||||
@@ -145,6 +143,17 @@ const modinfoConsistent = (
|
||||
return false;
|
||||
return modinfo.entries.every((entry, index) => {
|
||||
if (entry.index !== index) return false;
|
||||
if (new Set(entry.omitted_fields).size !== entry.omitted_fields.length)
|
||||
return false;
|
||||
for (const field of ["key", "value"] as const) {
|
||||
const text = entry[field];
|
||||
if (entry.omitted_fields.includes(field) && text !== null) return false;
|
||||
const maximum =
|
||||
field === "key"
|
||||
? input.max_modinfo_key_bytes
|
||||
: input.max_modinfo_value_bytes;
|
||||
if (text !== null && text.length > maximum) return false;
|
||||
}
|
||||
const rawFits = entry.location.bytes <= MAX_KERNEL_MODULE_RAW_BYTES;
|
||||
if (rawFits) {
|
||||
if (
|
||||
@@ -155,7 +164,9 @@ const modinfoConsistent = (
|
||||
} else if (entry.raw_hex !== null) return false;
|
||||
if (entry.status === "observed")
|
||||
return (
|
||||
entry.reason === null && entry.key !== null && entry.value !== null
|
||||
entry.reason === null &&
|
||||
(entry.key !== null || entry.omitted_fields.includes("key")) &&
|
||||
(entry.value !== null || entry.omitted_fields.includes("value"))
|
||||
);
|
||||
return entry.reason !== null;
|
||||
});
|
||||
@@ -274,12 +285,11 @@ const metadataAbsent = (report: KernelModule): boolean =>
|
||||
|
||||
const validReport = (
|
||||
report: KernelModule,
|
||||
maxEntries: number,
|
||||
maxBytes: number,
|
||||
input: InspectKernelModuleInput,
|
||||
): boolean => {
|
||||
if (
|
||||
report.artifact.bytes > maxBytes ||
|
||||
report.coverage.examined_entries > maxEntries ||
|
||||
report.artifact.bytes > input.max_file_bytes ||
|
||||
report.coverage.examined_entries > input.max_entries ||
|
||||
!rangesOf(report).every(inside(report.artifact.bytes))
|
||||
)
|
||||
return false;
|
||||
@@ -342,7 +352,7 @@ const validReport = (
|
||||
return false;
|
||||
if (report.type !== 1) return false;
|
||||
return (
|
||||
modinfoConsistent(report.modinfo) &&
|
||||
modinfoConsistent(report.modinfo, input) &&
|
||||
versionsConsistent(report.versions) &&
|
||||
signatureConsistent(report.signature) &&
|
||||
sizedConsistent(report.init_text) &&
|
||||
|
||||
@@ -95,6 +95,9 @@ export class RecordedCrashService {
|
||||
parameters: {
|
||||
path: input.value.path,
|
||||
include_debugger_context: input.value.include_debugger_context,
|
||||
...(input.value.producer_limits === undefined
|
||||
? {}
|
||||
: { producer_limits: input.value.producer_limits }),
|
||||
...(input.value.pwntools_timeout_ms === undefined
|
||||
? {}
|
||||
: { pwntools_timeout_ms: input.value.pwntools_timeout_ms }),
|
||||
|
||||
Reference in new issue
Block a user