mirror of
https://github.com/morluto/rea.git
synced 2026-11-02 21:06:04 +00:00
fix(javascript): retain selected-root access and filesystem failure facts
This commit is contained in:
1 parent
b2cb9b6596
commit
77ed32fabc
5 files changed
+189
-23
No files matched your search
@@ -12,7 +12,10 @@ import {
|
||||
type JavaScriptApplicationAnalysisResult,
|
||||
parseOwnedJavaScriptApplicationAnalysisSteps,
|
||||
} from "../../domain/javascript/javascriptApplicationAnalysis.js";
|
||||
import { AnalysisOutputError } from "../../domain/analysisErrorCore.js";
|
||||
import {
|
||||
AnalysisAccessDeniedError,
|
||||
AnalysisOutputError,
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { ArtifactOperationError } from "../../domain/artifactOperationError.js";
|
||||
import { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
@@ -170,8 +173,32 @@ export const analyzeJavaScriptApplicationValidated = async (
|
||||
"code" in cause &&
|
||||
typeof cause.code === "string" &&
|
||||
FILESYSTEM_ERROR_CODES.has(cause.code)
|
||||
)
|
||||
return err(new ArtifactOperationError(OPERATION, "io"));
|
||||
) {
|
||||
const path: unknown = Reflect.get(cause, "path");
|
||||
const syscall: unknown = Reflect.get(cause, "syscall");
|
||||
const diagnostics = {
|
||||
input_path: input.input_path,
|
||||
system_code: cause.code,
|
||||
...(typeof path === "string" ? { path } : {}),
|
||||
...(typeof syscall === "string" ? { syscall } : {}),
|
||||
};
|
||||
return err(
|
||||
cause.code === "EACCES" || cause.code === "EPERM"
|
||||
? new AnalysisAccessDeniedError(
|
||||
OPERATION,
|
||||
input.input_path,
|
||||
cause.code,
|
||||
{ cause, diagnostics },
|
||||
)
|
||||
: new ArtifactOperationError(
|
||||
OPERATION,
|
||||
"io",
|
||||
undefined,
|
||||
cause.message,
|
||||
{ cause, diagnostics },
|
||||
),
|
||||
);
|
||||
}
|
||||
return err(
|
||||
new ProviderAdapterError(JAVASCRIPT_APPLICATION_PROVIDER.id, OPERATION, {
|
||||
cause,
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
DEFAULT_ASAR_HEADER_ADMISSION,
|
||||
type AsarHeaderAdmission,
|
||||
} from "../../config/asarHeaderAdmission.js";
|
||||
import { constants } from "node:fs";
|
||||
import { constants, type Stats } from "node:fs";
|
||||
import {
|
||||
buildJavaScriptRouteInventorySteps,
|
||||
type JavaScriptRouteInventory,
|
||||
@@ -102,8 +102,8 @@ export const reconstructJavaScriptArtifact = async (
|
||||
};
|
||||
const input = javascriptArtifactReconstructionInputSchema.parse(rawInput);
|
||||
abortIfNeeded(signal);
|
||||
const path = await resolveSelectedInput(input.input_path);
|
||||
const format = await resolveFormat(path, input);
|
||||
const { path, metadata } = await resolveSelectedInput(input.input_path);
|
||||
const format = resolveFormat(path, metadata, input);
|
||||
const snapshot = await scanCanonicalArtifactInventoryInScope(path, {
|
||||
resourceScope: scope,
|
||||
signal,
|
||||
@@ -425,11 +425,18 @@ const OPERATION = "analyze_javascript_application";
|
||||
* unreadable selection is a caller or host-resolution failure, not a damaged
|
||||
* artifact.
|
||||
*/
|
||||
const resolveSelectedInput = async (inputPath: string): Promise<string> => {
|
||||
const resolveSelectedInput = async (
|
||||
inputPath: string,
|
||||
): Promise<{ readonly path: string; readonly metadata: Stats }> => {
|
||||
try {
|
||||
const path = await realpath(inputPath);
|
||||
await access(path, constants.R_OK);
|
||||
return path;
|
||||
const metadata = await lstat(path);
|
||||
// Directory enumeration needs read access; resolving its entries also needs search access.
|
||||
await access(
|
||||
path,
|
||||
metadata.isDirectory() ? constants.R_OK | constants.X_OK : constants.R_OK,
|
||||
);
|
||||
return { path, metadata };
|
||||
} catch (cause: unknown) {
|
||||
const code =
|
||||
cause instanceof Error && "code" in cause ? String(cause.code) : "";
|
||||
@@ -466,11 +473,11 @@ const selectedInputResolutionMessage = (
|
||||
: `Selected input path could not be resolved because symbolic-link traversal looped or exceeded the host limit (ELOOP): ${inputPath}`;
|
||||
|
||||
/** The selected input's kind, checked against the caller's requested format. */
|
||||
const resolveFormat = async (
|
||||
const resolveFormat = (
|
||||
path: string,
|
||||
metadata: Stats,
|
||||
input: JavaScriptArtifactReconstructionInput,
|
||||
): Promise<"asar" | "directory"> => {
|
||||
const metadata = await lstat(path);
|
||||
): "asar" | "directory" => {
|
||||
const observed = metadata.isDirectory()
|
||||
? "directory"
|
||||
: metadata.isFile() && path.toLowerCase().endsWith(".asar")
|
||||
|
||||
Reference in new issue
Block a user