Files
reverse-engineering-anything/src/domain/explicitSensitiveFailure.test.ts
T
a0214e0e0e fix(javascript): name heap and semantic ceilings (#6022)
* fix(javascript): name heap and semantic ceilings

Refs #5910. Heap exhaustion names max_heap_mb with its effective value,
range, and next-analysis worker restart. Semantic ceiling coverage names
the four max_semantic_* arguments. Wakaru and transfer ceilings say this
release has no runtime override.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): distinguish adjustable ceilings from fixed limits

The effective transfer file ceiling and the parent result budget follow
the CLI/MCP process heap, so recovery names NODE_OPTIONS instead of
denying an override. A provenance report over 8 MiB keeps the fixed
allowance guidance, and the Wakaru deadline says an unchanged retry may
hit it again.

Refs #5910

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): keep Bun OOM and checkpoint heap controls distinct

Bun heap-exhaustion exits no longer claim the ignored max_heap_mb V8
old-space limit. Checkpoint decode names the parent heap and Node
NODE_OPTIONS, the same control as the parent result budget.

Refs #5910

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): name semantic ceilings without claiming both were reached

Truncated semantic retention names the total and per-file controls as
effective ceilings. Callers only know that retention was truncated, so
the limitation no longer says both ceilings were reached.

Refs #5910

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): name only the semantic ceiling that stopped retention

Semantic ceiling limitations claimed both the application total and the
per-file control whenever either one truncated the graph. Record which
offered budget stopped node and unknown retention, and name only those
controls. Coverage limits still list both effective values.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): require a value in the NODE_OPTIONS heap example

A bare --max-old-space-size is an illegal V8 flag and prevents Node from
starting. Parent-heap and transfer-ceiling recovery now share
--max-old-space-size=<MiB>, and the Kuna heap remediation uses the same
complete form.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(javascript): limit the old-space placeholder to NODE_OPTIONS recovery

The review covers the CLI/MCP NODE_OPTIONS example and the transfer-ceiling
copy. The Kuna heap-headroom sentence stays unchanged.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 02:44:14 +08:00

287 lines
10 KiB
TypeScript

import { AnalysisAccessDeniedError } from "./analysisErrorCore.js";
import { expect, it } from "vitest";
import {
AnalysisInputError,
AnalysisCapabilityUnavailableError,
AnalysisCancelledError,
AnalysisTimeoutError,
AnalysisArtifactChangedError,
AnalysisOutputError,
AnalysisResourceConstraintError,
} from "./analysisErrorCore.js";
import { projectAnalysisError } from "./analysisErrorProjection.js";
import { ProviderCleanupError } from "./providerCleanupError.js";
import { ProviderAdapterError } from "./providerAdapterError.js";
import { analysisErrorWithCleanupFailure } from "./analysisErrorCleanup.js";
import { resolvedAnalysisError } from "./analysisErrorBase.js";
import { createEvidence } from "./evidence.js";
import {
redactExplicitFailure,
redactExplicitPointer,
} from "./explicitSensitiveFailure.js";
const context = {
diagnostics: {
note: "explicit-secret warning",
nested: { "explicit-secret-key": 5, observed: 7 },
caller_path: "/tmp/password-fixture?token=public-value",
},
capturedOutput: {
stdout: "explicit-secret output",
stderr: "public stderr",
stdout_bytes: 22,
truncated: false,
},
};
it.each([
new AnalysisCancelledError("inspect", context),
new AnalysisTimeoutError("inspect", 250, context),
new AnalysisInputError("inspect", context),
new AnalysisAccessDeniedError("inspect", "/public", "EACCES", context),
new AnalysisArtifactChangedError("inspect", "/public", "changed", context),
new AnalysisOutputError("inspect", "invalid", context),
new AnalysisCapabilityUnavailableError(
"provider",
"inspect",
"unsupported",
context,
),
new AnalysisResourceConstraintError(
"inspect",
"memory",
"capacity",
null,
context,
),
new ProviderAdapterError("provider", "inspect", context),
])("preserves sanitized common context for $._tag", (error) => {
const observation = createEvidence(
undefined,
{ id: "fixture", name: "Owner facts", version: "1" },
{
operation: "inspect",
parameters: {},
result: { source: "already sanitized owner facts" },
confidence: "observed",
authority: "historical-reference",
},
);
error.retainPartialObservation(observation);
const sanitized = redactExplicitFailure(error, ["explicit-secret"]);
expect(sanitized.partialObservation).toBe(observation);
expect(sanitized._tag).toBe(error._tag);
const projected = projectAnalysisError(sanitized);
expect(projected.details).toMatchObject({
diagnostics: {
note: "[REDACTED] warning",
nested: { observed: 7 },
caller_path: context.diagnostics.caller_path,
},
captured_output: {
stdout: "[REDACTED] output",
stdout_bytes: 22,
stderr: "public stderr",
},
});
expect(JSON.stringify(projected)).not.toContain("explicit-secret");
});
it.each([
["/metadata/private~1~0/numeric", ["private/~"], "/metadata"],
["/metadata/private/child", ["private"], "/metadata"],
["/ordinary/path", [], "/ordinary/path"],
])(
"preserves a real parent for excluded pointer identities: %s",
(pointer, values, expected) => {
expect(redactExplicitPointer(pointer, values)).toBe(expected);
},
);
it("preserves cleanup failure authority and resources while excluding diagnostics", () => {
const error = new ProviderCleanupError(
"har",
["/root/private/capture", "pid:123"],
{
capture_path: "/root/private/capture",
nested: { "private-key": 5, ordinary: "private ordinary" },
exit_code: 2,
},
{ operation: "inspect_web_network_capture" },
);
const projected = projectAnalysisError(
redactExplicitFailure(error, ["private", "REDACTED"]),
);
expect(projected.code).toBe("cleanup_incomplete");
expect(JSON.stringify(projected)).not.toContain("private");
expect(JSON.stringify(projected)).not.toContain("REDACTED");
expect(JSON.stringify(projected)).toContain("pid:123");
expect(JSON.stringify(projected)).toContain('"exit_code":2');
});
it("redacts cleanup primaries and mirrors the source error's live status", () => {
const primary = new AnalysisInputError(
"inspect_web_network_capture",
undefined,
[
{
path: ["capture_path", "/root/private-marker/capture.har"],
reason: "invalid_value",
message: "Selected private-marker capture was invalid",
},
],
);
const cleanup = new ProviderCleanupError(
"har",
["/tmp/private-marker-runtime"],
{ reason: "private-marker runtime close failed" },
{ operation: "inspect_web_network_capture" },
);
const original = analysisErrorWithCleanupFailure(
primary,
cleanup,
"inspect_web_network_capture",
);
const redacted = redactExplicitFailure(original, ["private-marker"]);
expect(redacted.cleanupIncomplete).toBe(true);
expect(redacted.cleanupResources).toEqual(["/tmp/[REDACTED]-runtime"]);
expect(JSON.stringify(projectAnalysisError(redacted))).not.toContain(
"private-marker",
);
original.resolveCleanup();
expect(redacted.cleanupIncomplete).toBe(false);
const resolved = resolvedAnalysisError(redacted);
expect(JSON.stringify(projectAnalysisError(resolved))).not.toContain(
"private-marker",
);
expect(projectAnalysisError(resolved).details).toMatchObject({
issues: [
{
path: ["capture_path", "/root"],
reason: "invalid_value",
},
],
});
});
it("keeps a named timeout control through explicit-value redaction", () => {
const error = new AnalysisTimeoutError(
"analyze_javascript_application",
300000,
{
userMessage:
"JavaScript source analysis reached its 300000ms per-source server/provider deadline (analysis_timeout_ms) for explicit-secret, not the MCP client deadline.",
remediationAction:
"Increase analysis_timeout_ms through MCP for explicit-secret, or use rea analyze-javascript-application <input_path> --analysis-timeout-ms <milliseconds> on the CLI.",
},
);
const redacted = redactExplicitFailure(error, ["explicit-secret"]);
const projected = projectAnalysisError(redacted);
expect(projected.message).toContain("analysis_timeout_ms");
expect(projected.message).toContain("300000");
expect(projected.remediation.action).toContain("analysis_timeout_ms");
expect(projected.remediation.action).toContain("--analysis-timeout-ms");
expect(JSON.stringify(projected)).not.toContain("explicit-secret");
});
it("keeps unsupported profile reasons distinct from malformed input", () => {
const error = new AnalysisCapabilityUnavailableError(
"mitmproxy",
"inspect_web_network_capture",
"Unsupported private profile",
{ userMessage: "Select private-compatible profile" },
);
const result = redactExplicitFailure(error, ["private"]);
expect(result).toBeInstanceOf(AnalysisCapabilityUnavailableError);
expect(projectAnalysisError(result).code).toBe("capability_unavailable");
expect(JSON.stringify(projectAnalysisError(result))).not.toContain("private");
});
it("preserves a retryable capability failure through explicit-value redaction", () => {
// Retryability is a semantic field of the error, not presentation: dropping
// it turns a transient admission failure into a permanent one and changes
// the remediation the caller is shown.
const error = new AnalysisCapabilityUnavailableError(
"mitmproxy",
"inspect_web_network_capture",
"Runtime admission for /targets/private/capture failed transiently",
{ retryable: true },
);
expect(projectAnalysisError(error).retryable).toBe(true);
const result = redactExplicitFailure(error, ["private"]);
expect(result).toBeInstanceOf(AnalysisCapabilityUnavailableError);
expect((result as AnalysisCapabilityUnavailableError).retryable).toBe(true);
expect(projectAnalysisError(result).retryable).toBe(true);
expect(JSON.stringify(projectAnalysisError(result))).not.toContain("private");
});
it("coarsens format issue pointers without creating replacement coordinates", () => {
const error = new AnalysisInputError(
"inspect_web_network_capture",
undefined,
[
{
path: ["capture_path", "/metadata/private~1~0/nested"],
reason: "invalid_format",
message: "Malformed private field",
},
],
);
const result = redactExplicitFailure(error, ["private/~", "private"]);
if (!(result instanceof AnalysisInputError))
throw new Error("Input error required");
expect(result.issues[0]?.path).toEqual(["capture_path", "/metadata"]);
});
it("excludes a marked permission-denied path without losing its host error code", () => {
const error = redactExplicitFailure(
new AnalysisAccessDeniedError(
"inspect_web_network_capture",
"/declared-path-value/capture.har",
"EACCES",
),
["declared-path-value"],
);
expect(error._tag).toBe("AnalysisAccessDeniedError");
const projected = projectAnalysisError(error);
expect(projected).toMatchObject({
code: "access_denied",
category: "unavailable",
details: { system_code: "EACCES" },
});
expect(JSON.stringify(projected)).not.toContain("declared-path-value");
});
it("coarsens ordinary sensitive issue-path segments to their real parent", () => {
const input = new AnalysisInputError(
"inspect_web_network_capture",
undefined,
[
{
path: ["input", "mysecret", "child"],
reason: "unknown_argument",
message: "Unrecognized mysecret",
},
],
);
const result = redactExplicitFailure(input, ["secret"]);
if (!(result instanceof AnalysisInputError))
throw new Error("Input error required");
expect(result.issues[0]?.path).toEqual(["input"]);
expect(JSON.stringify(projectAnalysisError(result))).not.toContain("secret");
});
it("does not reinterpret an unknown argument name as a JSON pointer", () => {
const input = new AnalysisInputError(
"inspect_web_network_capture",
undefined,
[{ path: ["/ordinary/secret"], reason: "unknown_argument" }],
);
const result = redactExplicitFailure(input, ["secret"]);
if (!(result instanceof AnalysisInputError))
throw new Error("Input error required");
expect(result.issues[0]?.path).toEqual([]);
});