rea-agents 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -31
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/Doctor.js +56 -6
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +38 -13
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +7 -1
- package/dist/application/JavaScriptArtifactGraphBuilder.js +59 -16
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactReconstruction.js +3 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/runtime.js +2 -0
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +4 -1
- package/dist/cli.js +388 -0
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliCommandNames.js +13 -0
- package/dist/cliElectronCommands.js +103 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/config.js +83 -0
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +47 -45
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +46 -31
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +67 -1
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +31 -43
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +10 -0
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraProvider.js +6 -0
- package/dist/main.js +14 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +52 -0
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +58 -13
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +8 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +51 -86
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +12 -4
- package/scripts/rea.mjs +1 -1
- package/skills/rea-analysis/SKILL.md +59 -3
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { evidenceEnvelopeSchema } from "../domain/evidence.js";
|
|
3
2
|
import { processCaptureComparisonSchema, processCaptureSchema, } from "../domain/processCapture.js";
|
|
4
3
|
import { evidenceBundleSchema } from "../domain/evidenceBundle.js";
|
|
5
4
|
import { residualUnknownSchema } from "../domain/residualUnknown.js";
|
|
6
5
|
import { functionDossierSchema, localVariableSchema, procedureClassificationSchema, procedureIdentitySchema, referenceKindSchema, } from "../domain/hopperValues.js";
|
|
7
6
|
import { demangleSwiftSchema, inspectMachoSchema, inspectPlistSchema, inspectSignatureSchema, listArchitecturesSchema, } from "../domain/nativeInspection.js";
|
|
8
7
|
import { artifactExtractionResultSchema, artifactInventoryResultSchema, } from "../domain/artifactGraph.js";
|
|
8
|
+
import { managedArtifactInspectionSchema, managedMemberInspectionSchema, managedNativeBoundaryInspectionSchema, } from "../domain/managedArtifact.js";
|
|
9
|
+
import { managedMemberComparisonResultSchema } from "../domain/managedMemberComparison.js";
|
|
10
|
+
import { managedNativeVerificationResultSchema } from "../domain/managedNativeVerification.js";
|
|
11
|
+
import { managedReconstructionImportResultSchema } from "../domain/managedReconstruction.js";
|
|
12
|
+
import { managedRuntimeCorrelationResultSchema } from "../domain/managedRuntimeCorrelation.js";
|
|
13
|
+
import { managedApplicationGraphResultSchema } from "../domain/managedApplicationGraph.js";
|
|
9
14
|
import { artifactComparisonResultSchema } from "../domain/artifactComparison.js";
|
|
10
15
|
import { functionComparisonResultSchema } from "../domain/functionComparison.js";
|
|
11
16
|
import { bundleComparisonResultSchema } from "../domain/bundleComparison.js";
|
|
@@ -16,9 +21,13 @@ import { reconstructionVerificationResultSchema } from "../domain/reconstruction
|
|
|
16
21
|
import { analysisErrorProjectionSchema } from "./errorSchemas.js";
|
|
17
22
|
import { analysisProfileSchema } from "../domain/analysisProfile.js";
|
|
18
23
|
import { PROVIDER_REJECTION_CODES, } from "./providerSelection.js";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
/** Compact MCP result with an immutable link to complete session Evidence. */
|
|
25
|
+
export const evidenceResultOf = (schema) => z.strictObject({
|
|
26
|
+
result: schema,
|
|
27
|
+
evidence_id: z.string().regex(/^ev_[a-f0-9]{64}$/u),
|
|
28
|
+
evidence_uri: z.string().regex(/^rea:\/\/evidence\/ev_[a-f0-9]{64}$/u),
|
|
29
|
+
});
|
|
30
|
+
const resultOf = evidenceResultOf;
|
|
22
31
|
const lifecycleResultOf = (schema) => z.object({ result: schema });
|
|
23
32
|
/** Resolve a required named output schema or reject contract drift. */
|
|
24
33
|
export const requireOutputSchema = (schemas, name) => {
|
|
@@ -154,6 +163,16 @@ const sessionProvider = z.object({
|
|
|
154
163
|
"policy_disabled",
|
|
155
164
|
]),
|
|
156
165
|
remediation: z.string().nullable(),
|
|
166
|
+
effects: z.strictObject({
|
|
167
|
+
mutatesTarget: z.boolean(),
|
|
168
|
+
mutatesSession: z.boolean(),
|
|
169
|
+
writesFilesystem: z.boolean(),
|
|
170
|
+
launchesProcess: z.boolean(),
|
|
171
|
+
accessesNetwork: z.boolean(),
|
|
172
|
+
changesUiState: z.boolean(),
|
|
173
|
+
mayDiscardData: z.boolean(),
|
|
174
|
+
idempotent: z.boolean(),
|
|
175
|
+
}),
|
|
157
176
|
annotations: z.object({
|
|
158
177
|
read_only: z.boolean(),
|
|
159
178
|
destructive: z.boolean(),
|
|
@@ -456,6 +475,20 @@ export const artifactOutputSchemas = {
|
|
|
456
475
|
inventory_artifact: resultOf(artifactInventoryResultSchema),
|
|
457
476
|
extract_artifact: resultOf(artifactExtractionResultSchema),
|
|
458
477
|
};
|
|
478
|
+
/** Exact Evidence v2 schema for execution-free managed static analysis. */
|
|
479
|
+
export const managedOutputSchemas = {
|
|
480
|
+
inspect_managed_artifact: resultOf(managedArtifactInspectionSchema),
|
|
481
|
+
inspect_managed_members: resultOf(managedMemberInspectionSchema),
|
|
482
|
+
inspect_managed_native_boundaries: resultOf(managedNativeBoundaryInspectionSchema),
|
|
483
|
+
};
|
|
484
|
+
/** Exact Evidence v2 schema for provider-neutral managed workflows. */
|
|
485
|
+
export const managedWorkflowOutputSchemas = {
|
|
486
|
+
compare_managed_members: resultOf(managedMemberComparisonResultSchema),
|
|
487
|
+
verify_managed_native_boundaries: resultOf(managedNativeVerificationResultSchema),
|
|
488
|
+
import_managed_reconstruction: resultOf(managedReconstructionImportResultSchema),
|
|
489
|
+
plan_managed_runtime_correlation: resultOf(managedRuntimeCorrelationResultSchema),
|
|
490
|
+
project_managed_application_graph: resultOf(managedApplicationGraphResultSchema),
|
|
491
|
+
};
|
|
459
492
|
/** Exact structured-content schemas for target lifecycle operations. */
|
|
460
493
|
export const sessionOutputSchemas = {
|
|
461
494
|
open_binary: lifecycleResultOf(z.object({
|
|
@@ -497,33 +530,15 @@ export const sessionOutputSchemas = {
|
|
|
497
530
|
imported: z.number().int().min(0),
|
|
498
531
|
total: z.number().int().min(0),
|
|
499
532
|
})),
|
|
500
|
-
capture_process_scenario:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
compare_functions: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
510
|
-
normalized_result: functionComparisonResultSchema,
|
|
511
|
-
})),
|
|
512
|
-
compare_bundles: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
513
|
-
normalized_result: bundleComparisonResultSchema,
|
|
514
|
-
})),
|
|
515
|
-
find_changed_behavior: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
516
|
-
normalized_result: changedBehaviorResultSchema,
|
|
517
|
-
})),
|
|
518
|
-
build_call_path: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
519
|
-
normalized_result: callPathResultSchema,
|
|
520
|
-
})),
|
|
521
|
-
correlate_static_and_runtime: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
522
|
-
normalized_result: staticRuntimeCorrelationResultSchema,
|
|
523
|
-
})),
|
|
524
|
-
verify_reconstruction: lifecycleResultOf(evidenceEnvelopeSchema.omit({ normalized_result: true }).extend({
|
|
525
|
-
normalized_result: reconstructionVerificationResultSchema,
|
|
526
|
-
})),
|
|
533
|
+
capture_process_scenario: resultOf(processCaptureSchema),
|
|
534
|
+
compare_process_captures: resultOf(processCaptureComparisonSchema),
|
|
535
|
+
compare_artifacts: resultOf(artifactComparisonResultSchema),
|
|
536
|
+
compare_functions: resultOf(functionComparisonResultSchema),
|
|
537
|
+
compare_bundles: resultOf(bundleComparisonResultSchema),
|
|
538
|
+
find_changed_behavior: resultOf(changedBehaviorResultSchema),
|
|
539
|
+
build_call_path: resultOf(callPathResultSchema),
|
|
540
|
+
correlate_static_and_runtime: resultOf(staticRuntimeCorrelationResultSchema),
|
|
541
|
+
verify_reconstruction: resultOf(reconstructionVerificationResultSchema),
|
|
527
542
|
list_unknowns: lifecycleResultOf(z.array(residualUnknownSchema)),
|
|
528
543
|
record_unknown: lifecycleResultOf(residualUnknownSchema),
|
|
529
544
|
update_unknown: lifecycleResultOf(residualUnknownSchema),
|
package/dist/doctorRuntime.js
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
|
-
import { systemDoctorHost } from "./application/Doctor.js";
|
|
1
|
+
import { systemDoctorHost, } from "./application/Doctor.js";
|
|
2
2
|
import { inspectSystemGhidraProvider } from "./ghidra/GhidraDoctor.js";
|
|
3
|
+
import { parseConfig } from "./config.js";
|
|
4
|
+
import { SystemJavaScriptReplayHost } from "./replay/SystemJavaScriptReplayHost.js";
|
|
3
5
|
/** Compose provider diagnostics at the outer CLI adapter boundary. */
|
|
4
6
|
export const createSystemDoctorHost = () => systemDoctorHost({
|
|
5
7
|
providerInspections: async () => [await inspectSystemGhidraProvider()],
|
|
8
|
+
javascriptReplayCheck: inspectJavaScriptReplay,
|
|
6
9
|
});
|
|
10
|
+
const inspectJavaScriptReplay = async () => {
|
|
11
|
+
const config = parseConfig(process.env);
|
|
12
|
+
if (!config.ok)
|
|
13
|
+
return {
|
|
14
|
+
name: "javascript-replay",
|
|
15
|
+
ok: false,
|
|
16
|
+
classification: "config_drift",
|
|
17
|
+
detail: config.error.message,
|
|
18
|
+
remediation: "Fix the reported REA_JAVASCRIPT_REPLAY_* configuration.",
|
|
19
|
+
};
|
|
20
|
+
if (!config.value.javascriptReplayPolicy.enabled)
|
|
21
|
+
return {
|
|
22
|
+
name: "javascript-replay",
|
|
23
|
+
ok: true,
|
|
24
|
+
classification: "healthy",
|
|
25
|
+
detail: "disabled by default; no extracted-module execution path is admitted",
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
await new SystemJavaScriptReplayHost().probe(config.value.javascriptReplayPolicy);
|
|
29
|
+
return {
|
|
30
|
+
name: "javascript-replay",
|
|
31
|
+
ok: true,
|
|
32
|
+
classification: "healthy",
|
|
33
|
+
detail: "Linux namespace, seccomp, and delegated cgroup probes passed",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (cause) {
|
|
37
|
+
return {
|
|
38
|
+
name: "javascript-replay",
|
|
39
|
+
ok: false,
|
|
40
|
+
classification: process.platform === "linux"
|
|
41
|
+
? "missing_dependency"
|
|
42
|
+
: "unsupported_host",
|
|
43
|
+
detail: cause instanceof Error ? cause.message : "sandbox probe failed",
|
|
44
|
+
remediation: "Install and configure compatible Bubblewrap and systemd user cgroup delegation, or disable controlled replay.",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import canonicalize from "canonicalize";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import {} from "./artifactGraph.js";
|
|
4
|
-
import { evidenceSchema } from "./evidence.js";
|
|
5
4
|
import { parseArtifactInventoryEvidence, } from "./artifactInventoryEvidence.js";
|
|
6
5
|
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
7
6
|
const comparisonStatusSchema = z.enum([
|
|
@@ -32,9 +31,9 @@ const comparisonDimensionSchema = z.enum([
|
|
|
32
31
|
"integrity",
|
|
33
32
|
]);
|
|
34
33
|
/** Strict Evidence-backed input for deterministic artifact comparison. */
|
|
35
|
-
export const artifactComparisonInputSchema = z.
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
export const artifactComparisonInputSchema = z.strictObject({
|
|
35
|
+
left_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
36
|
+
right_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
38
37
|
offset: z.number().int().min(0).default(0),
|
|
39
38
|
limit: z.number().int().min(1).max(500).default(100),
|
|
40
39
|
unknown_registry_approved: z
|
|
@@ -382,6 +382,7 @@ const browserResourceReconciliationSchema = z.discriminatedUnion("status", [
|
|
|
382
382
|
]);
|
|
383
383
|
const browserScriptSchema = z.object({
|
|
384
384
|
script_key: z.string().regex(/^scr_[a-f0-9]{64}(?:_[0-9]+)?$/u),
|
|
385
|
+
frame_id: z.string().nullable().default(null),
|
|
385
386
|
url: z.string(),
|
|
386
387
|
origin: z.string().nullable(),
|
|
387
388
|
cdp_hash: z.string(),
|
|
@@ -464,6 +465,8 @@ const browserWorkerSchema = z.object({
|
|
|
464
465
|
url: z.string(),
|
|
465
466
|
origin: z.string().nullable(),
|
|
466
467
|
attached: z.boolean(),
|
|
468
|
+
opener_target_id: z.string().nullable().default(null),
|
|
469
|
+
parent_frame_id: z.string().nullable().default(null),
|
|
467
470
|
});
|
|
468
471
|
const browserCspSourceSchema = z.object({
|
|
469
472
|
kind: z.enum([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { parseEvidenceBundle, serializeEvidenceBundle, } from "./evidenceBundle.js";
|
|
4
4
|
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
5
5
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
6
6
|
const classificationSchema = z.enum([
|
|
@@ -12,9 +12,9 @@ const classificationSchema = z.enum([
|
|
|
12
12
|
"history_diverged",
|
|
13
13
|
]);
|
|
14
14
|
/** Strict bounded input for canonical Evidence bundle comparison. */
|
|
15
|
-
export const bundleComparisonInputSchema = z.
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export const bundleComparisonInputSchema = z.strictObject({
|
|
16
|
+
left_bundle_path: z.string().min(1).max(4_096),
|
|
17
|
+
right_bundle_path: z.string().min(1).max(4_096),
|
|
18
18
|
record_pairs: z
|
|
19
19
|
.array(z.object({
|
|
20
20
|
left_evidence_id: evidenceIdSchema,
|
|
@@ -38,6 +38,7 @@ export const inspectElectronPageInputSchema = z
|
|
|
38
38
|
max_dom_nodes: z.number().int().min(1).max(10_000).default(2_000),
|
|
39
39
|
max_scripts: z.number().int().min(1).max(2_000).default(500),
|
|
40
40
|
max_resources: z.number().int().min(1).max(10_000).default(2_000),
|
|
41
|
+
max_workers: z.number().int().min(1).max(5_000).default(500),
|
|
41
42
|
max_script_source_bytes: z
|
|
42
43
|
.number()
|
|
43
44
|
.int()
|
|
@@ -56,6 +57,7 @@ export const inspectElectronPageInputSchema = z
|
|
|
56
57
|
max_dom_nodes: 2_000,
|
|
57
58
|
max_scripts: 500,
|
|
58
59
|
max_resources: 2_000,
|
|
60
|
+
max_workers: 500,
|
|
59
61
|
max_script_source_bytes: 1_024 * 1_024,
|
|
60
62
|
max_total_script_source_bytes: 4 * 1_024 * 1_024,
|
|
61
63
|
}),
|
|
@@ -143,6 +145,7 @@ export const electronPageInspectionSchema = z.object({
|
|
|
143
145
|
total: z.number().int().min(0),
|
|
144
146
|
items: z.array(z.object({
|
|
145
147
|
script_key: z.string().regex(/^electron_script_[a-f0-9]{64}$/u),
|
|
148
|
+
frame_id: z.string().nullable().default(null),
|
|
146
149
|
file_path: z.string(),
|
|
147
150
|
cdp_hash: z.string(),
|
|
148
151
|
length: z.number().int().min(0),
|
|
@@ -158,5 +161,15 @@ export const electronPageInspectionSchema = z.object({
|
|
|
158
161
|
mime_type: z.string(),
|
|
159
162
|
content_size: z.number().min(0).nullable(),
|
|
160
163
|
})),
|
|
164
|
+
workers: z
|
|
165
|
+
.array(z.object({
|
|
166
|
+
target_id: z.string().min(1).max(256),
|
|
167
|
+
type: z.string().min(1).max(100),
|
|
168
|
+
file_path: z.string(),
|
|
169
|
+
attached: z.boolean(),
|
|
170
|
+
opener_target_id: z.string().min(1).max(256).nullable(),
|
|
171
|
+
parent_frame_id: z.string().min(1).max(256).nullable(),
|
|
172
|
+
}))
|
|
173
|
+
.default([]),
|
|
161
174
|
limitations: z.array(z.string()),
|
|
162
175
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { inspectElectronBrowserNode } from "./electronStaticAnalysisBrowser.js";
|
|
2
|
+
import { inspectElectronIpcNode } from "./electronStaticAnalysisIpc.js";
|
|
3
|
+
import { inspectElectronNativeNode } from "./electronStaticAnalysisNative.js";
|
|
4
|
+
/** Collect Electron-specific syntax during the shared inert AST traversal. */
|
|
5
|
+
export const inspectElectronStaticNode = (node, context) => {
|
|
6
|
+
inspectElectronBrowserNode(node, context);
|
|
7
|
+
inspectElectronIpcNode(node, context);
|
|
8
|
+
inspectElectronNativeNode(node, context);
|
|
9
|
+
};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { boundedExpression, collectContextBridgeMembers, electronStaticValue, objectProperty, } from "./electronStaticAnalysisValues.js";
|
|
3
|
+
import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
|
|
4
|
+
import { argumentNode, calleeName, compareCodePoints, propertyName, range, staticPath, } from "./javascriptStaticAnalysisHelpers.js";
|
|
5
|
+
const MAX_WEB_PREFERENCES = 64;
|
|
6
|
+
/** Inspect BrowserWindow, contextBridge, and utility-process syntax. */
|
|
7
|
+
export const inspectElectronBrowserNode = (node, context) => {
|
|
8
|
+
if (t.isNewExpression(node))
|
|
9
|
+
inspectBrowserWindow(node, context);
|
|
10
|
+
if (!t.isCallExpression(node))
|
|
11
|
+
return;
|
|
12
|
+
inspectContextBridge(node, context);
|
|
13
|
+
inspectUtilityProcess(node, context);
|
|
14
|
+
};
|
|
15
|
+
const inspectBrowserWindow = (node, context) => {
|
|
16
|
+
const name = calleeName(node.callee);
|
|
17
|
+
if (name !== "BrowserWindow" && !name.endsWith(".BrowserWindow"))
|
|
18
|
+
return;
|
|
19
|
+
const options = argumentNode(node.arguments[0]);
|
|
20
|
+
const collected = collectWindowOptions(context.source, options);
|
|
21
|
+
accountForStructure(context, collected.unknown, collected.omitted);
|
|
22
|
+
const finding = {
|
|
23
|
+
options_status: options === undefined
|
|
24
|
+
? "missing"
|
|
25
|
+
: t.isObjectExpression(options)
|
|
26
|
+
? "object-literal"
|
|
27
|
+
: "dynamic",
|
|
28
|
+
web_preferences_status: collected.status,
|
|
29
|
+
web_preferences: collected.preferences,
|
|
30
|
+
omitted_web_preferences: collected.omitted,
|
|
31
|
+
preload_path: collected.preloadPath,
|
|
32
|
+
module_key: null,
|
|
33
|
+
location: range(node),
|
|
34
|
+
};
|
|
35
|
+
addLocatedFinding(context, {
|
|
36
|
+
collection: context.accumulator.browserWindows,
|
|
37
|
+
key: `electron-window\0${name}`,
|
|
38
|
+
node,
|
|
39
|
+
value: finding,
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const collectWindowOptions = (source, options) => {
|
|
43
|
+
if (!t.isObjectExpression(options))
|
|
44
|
+
return {
|
|
45
|
+
status: options === undefined ? "missing" : "dynamic",
|
|
46
|
+
preferences: [],
|
|
47
|
+
preloadPath: null,
|
|
48
|
+
unknown: options === undefined ? 0 : 1,
|
|
49
|
+
omitted: 0,
|
|
50
|
+
};
|
|
51
|
+
const property = objectProperty(options, "webPreferences");
|
|
52
|
+
if (property === undefined)
|
|
53
|
+
return {
|
|
54
|
+
status: "missing",
|
|
55
|
+
preferences: [],
|
|
56
|
+
preloadPath: null,
|
|
57
|
+
unknown: 0,
|
|
58
|
+
omitted: 0,
|
|
59
|
+
};
|
|
60
|
+
if (!t.isObjectExpression(property.value))
|
|
61
|
+
return {
|
|
62
|
+
status: "dynamic",
|
|
63
|
+
preferences: [],
|
|
64
|
+
preloadPath: null,
|
|
65
|
+
unknown: 1,
|
|
66
|
+
omitted: 0,
|
|
67
|
+
};
|
|
68
|
+
return collectWebPreferences(source, property.value);
|
|
69
|
+
};
|
|
70
|
+
const collectWebPreferences = (source, object) => {
|
|
71
|
+
const preferences = [];
|
|
72
|
+
let unknown = 0;
|
|
73
|
+
let preloadPath = null;
|
|
74
|
+
for (const property of object.properties) {
|
|
75
|
+
if (t.isSpreadElement(property)) {
|
|
76
|
+
unknown += 1;
|
|
77
|
+
preferences.push({
|
|
78
|
+
name: `[spread@${String(property.start ?? -1)}]`,
|
|
79
|
+
value: electronStaticValue(source, property.argument),
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const name = propertyName(property.key);
|
|
84
|
+
if (name === "" || property.computed) {
|
|
85
|
+
unknown += 1;
|
|
86
|
+
preferences.push({
|
|
87
|
+
name: `[dynamic@${String(property.start ?? -1)}]`,
|
|
88
|
+
value: electronStaticValue(source, property),
|
|
89
|
+
});
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (t.isObjectMethod(property)) {
|
|
93
|
+
unknown += 1;
|
|
94
|
+
preferences.push({
|
|
95
|
+
name,
|
|
96
|
+
value: electronStaticValue(source, property),
|
|
97
|
+
});
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const path = name === "preload" ? staticPath(property.value) : undefined;
|
|
101
|
+
if (path !== undefined)
|
|
102
|
+
preloadPath = path;
|
|
103
|
+
const value = path === undefined
|
|
104
|
+
? electronStaticValue(source, property.value)
|
|
105
|
+
: { status: "literal", value: path, expression: null };
|
|
106
|
+
if (value.status === "dynamic")
|
|
107
|
+
unknown += 1;
|
|
108
|
+
preferences.push({ name, value });
|
|
109
|
+
}
|
|
110
|
+
preferences.sort((left, right) => compareCodePoints(left.name, right.name));
|
|
111
|
+
return {
|
|
112
|
+
status: "object-literal",
|
|
113
|
+
preferences: preferences.slice(0, MAX_WEB_PREFERENCES),
|
|
114
|
+
preloadPath,
|
|
115
|
+
unknown,
|
|
116
|
+
omitted: Math.max(0, preferences.length - MAX_WEB_PREFERENCES),
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
const inspectContextBridge = (node, context) => {
|
|
120
|
+
const name = calleeName(node.callee);
|
|
121
|
+
const main = name === "contextBridge.exposeInMainWorld" ||
|
|
122
|
+
name.endsWith(".contextBridge.exposeInMainWorld");
|
|
123
|
+
const isolated = name === "contextBridge.exposeInIsolatedWorld" ||
|
|
124
|
+
name.endsWith(".contextBridge.exposeInIsolatedWorld");
|
|
125
|
+
if (!main && !isolated)
|
|
126
|
+
return;
|
|
127
|
+
const keyNode = argumentNode(node.arguments[isolated ? 1 : 0]);
|
|
128
|
+
const apiNode = argumentNode(node.arguments[isolated ? 2 : 1]);
|
|
129
|
+
const key = electronStaticValue(context.source, keyNode);
|
|
130
|
+
const api = collectContextBridgeMembers(apiNode);
|
|
131
|
+
const worldId = isolated
|
|
132
|
+
? electronStaticValue(context.source, argumentNode(node.arguments[0]))
|
|
133
|
+
: null;
|
|
134
|
+
const unknown = (key.status === "dynamic" ? 1 : 0) +
|
|
135
|
+
(worldId?.status === "dynamic" ? 1 : 0) +
|
|
136
|
+
api.unknown;
|
|
137
|
+
accountForStructure(context, unknown, api.omitted);
|
|
138
|
+
const finding = {
|
|
139
|
+
world: isolated ? "isolated" : "main",
|
|
140
|
+
world_id: worldId,
|
|
141
|
+
api_key: key.status === "literal" && typeof key.value === "string"
|
|
142
|
+
? key.value
|
|
143
|
+
: null,
|
|
144
|
+
api_key_expression: key.status === "dynamic" ? key.expression : null,
|
|
145
|
+
api_status: api.status,
|
|
146
|
+
members: api.members,
|
|
147
|
+
unknown_members: api.unknown,
|
|
148
|
+
omitted_members: api.omitted,
|
|
149
|
+
module_key: null,
|
|
150
|
+
location: range(node),
|
|
151
|
+
};
|
|
152
|
+
addLocatedFinding(context, {
|
|
153
|
+
collection: context.accumulator.contextBridgeApis,
|
|
154
|
+
key: `context-bridge\0${isolated ? "isolated" : "main"}\0${finding.api_key ?? finding.api_key_expression ?? "[missing]"}`,
|
|
155
|
+
node,
|
|
156
|
+
value: finding,
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
const inspectUtilityProcess = (node, context) => {
|
|
160
|
+
const name = calleeName(node.callee);
|
|
161
|
+
if (name !== "utilityProcess.fork" && !name.endsWith(".utilityProcess.fork"))
|
|
162
|
+
return;
|
|
163
|
+
const moduleNode = argumentNode(node.arguments[0]);
|
|
164
|
+
const modulePath = moduleNode === undefined ? undefined : staticPath(moduleNode);
|
|
165
|
+
const options = argumentNode(node.arguments[2]);
|
|
166
|
+
const serviceName = t.isObjectExpression(options) &&
|
|
167
|
+
objectProperty(options, "serviceName") !== undefined
|
|
168
|
+
? staticPath(objectProperty(options, "serviceName")?.value ?? options)
|
|
169
|
+
: undefined;
|
|
170
|
+
if (modulePath === undefined)
|
|
171
|
+
context.accumulator.unknownFindings += 1;
|
|
172
|
+
const finding = {
|
|
173
|
+
module_path: modulePath ?? null,
|
|
174
|
+
module_expression: modulePath === undefined
|
|
175
|
+
? boundedExpression(context.source, moduleNode)
|
|
176
|
+
: null,
|
|
177
|
+
service_name: serviceName ?? null,
|
|
178
|
+
module_key: null,
|
|
179
|
+
location: range(node),
|
|
180
|
+
};
|
|
181
|
+
addLocatedFinding(context, {
|
|
182
|
+
collection: context.accumulator.utilityProcesses,
|
|
183
|
+
key: `electron-utility\0${modulePath ?? finding.module_expression ?? "[missing]"}`,
|
|
184
|
+
node,
|
|
185
|
+
value: finding,
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
const accountForStructure = (context, unknown, omitted) => {
|
|
189
|
+
context.accumulator.unknownFindings += unknown;
|
|
190
|
+
if (omitted === 0)
|
|
191
|
+
return;
|
|
192
|
+
context.accumulator.structuralTruncation = true;
|
|
193
|
+
context.accumulator.droppedFindings += omitted;
|
|
194
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { boundedExpression, electronStaticValue, handlerKind, } from "./electronStaticAnalysisValues.js";
|
|
3
|
+
import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
|
|
4
|
+
import { argumentNode, calleeName, propertyName, range, } from "./javascriptStaticAnalysisHelpers.js";
|
|
5
|
+
/** Inspect Electron IPC operations and validation candidates. */
|
|
6
|
+
export const inspectElectronIpcNode = (node, context) => {
|
|
7
|
+
if (t.isCallExpression(node)) {
|
|
8
|
+
inspectIpcCall(node, context);
|
|
9
|
+
inspectValidationCall(node, context);
|
|
10
|
+
}
|
|
11
|
+
if (t.isBinaryExpression(node))
|
|
12
|
+
inspectValidationComparison(node, context);
|
|
13
|
+
};
|
|
14
|
+
const inspectIpcCall = (node, context) => {
|
|
15
|
+
const name = calleeName(node.callee);
|
|
16
|
+
const descriptor = ipcDescriptor(name);
|
|
17
|
+
if (descriptor === undefined)
|
|
18
|
+
return;
|
|
19
|
+
const channelNode = argumentNode(node.arguments[0]);
|
|
20
|
+
const channelValue = electronStaticValue(context.source, channelNode);
|
|
21
|
+
const channel = channelValue.status === "literal" && typeof channelValue.value === "string"
|
|
22
|
+
? channelValue.value
|
|
23
|
+
: null;
|
|
24
|
+
const channelExpression = channel === null
|
|
25
|
+
? channelValue.status === "dynamic"
|
|
26
|
+
? channelValue.expression
|
|
27
|
+
: boundedExpression(context.source, channelNode)
|
|
28
|
+
: null;
|
|
29
|
+
const hasHandler = descriptor.mode === "listen" || descriptor.mode === "handle";
|
|
30
|
+
const handlerNode = hasHandler ? argumentNode(node.arguments[1]) : undefined;
|
|
31
|
+
if (channel === null)
|
|
32
|
+
context.accumulator.unknownFindings += 1;
|
|
33
|
+
if (hasHandler && handlerNode === undefined)
|
|
34
|
+
context.accumulator.unknownFindings += 1;
|
|
35
|
+
const finding = {
|
|
36
|
+
...descriptor,
|
|
37
|
+
channel,
|
|
38
|
+
channel_expression: channelExpression,
|
|
39
|
+
handler_kind: hasHandler ? handlerKind(handlerNode) : null,
|
|
40
|
+
handler_location: handlerNode === undefined ? null : range(handlerNode),
|
|
41
|
+
module_key: null,
|
|
42
|
+
location: range(node),
|
|
43
|
+
};
|
|
44
|
+
addLocatedFinding(context, {
|
|
45
|
+
collection: context.accumulator.ipc,
|
|
46
|
+
key: `electron-ipc\0${descriptor.side}\0${descriptor.operation}\0${channel ?? channelExpression ?? "[missing]"}`,
|
|
47
|
+
node,
|
|
48
|
+
value: finding,
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const inspectValidationComparison = (node, context) => {
|
|
52
|
+
if (!["==", "===", "!=", "!==", "in"].includes(node.operator))
|
|
53
|
+
return;
|
|
54
|
+
const left = senderSubject(node.left);
|
|
55
|
+
const right = senderSubject(node.right);
|
|
56
|
+
if (left === undefined && right === undefined)
|
|
57
|
+
return;
|
|
58
|
+
const expected = left === undefined ? node.left : node.right;
|
|
59
|
+
addValidation(context, node, {
|
|
60
|
+
subject: left ?? right ?? "sender-frame",
|
|
61
|
+
mechanism: `comparison:${node.operator}`,
|
|
62
|
+
expected: electronStaticValue(context.source, expected),
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
const inspectValidationCall = (node, context) => {
|
|
66
|
+
if (!t.isMemberExpression(node.callee) &&
|
|
67
|
+
!t.isOptionalMemberExpression(node.callee))
|
|
68
|
+
return;
|
|
69
|
+
const method = propertyName(node.callee.property);
|
|
70
|
+
if (!["startsWith", "endsWith", "includes"].includes(method))
|
|
71
|
+
return;
|
|
72
|
+
const subject = t.isNode(node.callee.object)
|
|
73
|
+
? senderSubject(node.callee.object)
|
|
74
|
+
: undefined;
|
|
75
|
+
if (subject === undefined)
|
|
76
|
+
return;
|
|
77
|
+
addValidation(context, node, {
|
|
78
|
+
subject,
|
|
79
|
+
mechanism: `call:${method}`,
|
|
80
|
+
expected: electronStaticValue(context.source, argumentNode(node.arguments[0])),
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const addValidation = (context, node, input) => {
|
|
84
|
+
if (input.expected.status === "dynamic")
|
|
85
|
+
context.accumulator.unknownFindings += 1;
|
|
86
|
+
const finding = {
|
|
87
|
+
...input,
|
|
88
|
+
enforcement: "unknown",
|
|
89
|
+
module_key: null,
|
|
90
|
+
location: range(node),
|
|
91
|
+
};
|
|
92
|
+
addLocatedFinding(context, {
|
|
93
|
+
collection: context.accumulator.senderValidations,
|
|
94
|
+
key: `electron-validation\0${input.subject}\0${input.mechanism}\0${input.expected.status === "literal" ? String(input.expected.value) : input.expected.expression}`,
|
|
95
|
+
node,
|
|
96
|
+
value: finding,
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
const ipcDescriptor = (name) => {
|
|
100
|
+
const renderer = suffixOperation(name, "ipcRenderer");
|
|
101
|
+
if (renderer !== undefined) {
|
|
102
|
+
switch (renderer) {
|
|
103
|
+
case "send":
|
|
104
|
+
return { side: "renderer", operation: "send", mode: "send" };
|
|
105
|
+
case "sendSync":
|
|
106
|
+
return { side: "renderer", operation: "send-sync", mode: "send" };
|
|
107
|
+
case "invoke":
|
|
108
|
+
return { side: "renderer", operation: "invoke", mode: "invoke" };
|
|
109
|
+
case "postMessage":
|
|
110
|
+
return {
|
|
111
|
+
side: "renderer",
|
|
112
|
+
operation: "post-message",
|
|
113
|
+
mode: "send",
|
|
114
|
+
};
|
|
115
|
+
case "sendToHost":
|
|
116
|
+
return {
|
|
117
|
+
side: "renderer",
|
|
118
|
+
operation: "send-to-host",
|
|
119
|
+
mode: "send",
|
|
120
|
+
};
|
|
121
|
+
case "on":
|
|
122
|
+
return { side: "renderer", operation: "on", mode: "listen" };
|
|
123
|
+
case "once":
|
|
124
|
+
return { side: "renderer", operation: "once", mode: "listen" };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const main = suffixOperation(name, "ipcMain");
|
|
128
|
+
switch (main) {
|
|
129
|
+
case "on":
|
|
130
|
+
return { side: "main", operation: "on", mode: "listen" };
|
|
131
|
+
case "once":
|
|
132
|
+
return { side: "main", operation: "once", mode: "listen" };
|
|
133
|
+
case "handle":
|
|
134
|
+
return { side: "main", operation: "handle", mode: "handle" };
|
|
135
|
+
case "handleOnce":
|
|
136
|
+
return { side: "main", operation: "handle-once", mode: "handle" };
|
|
137
|
+
default:
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const suffixOperation = (name, object) => {
|
|
142
|
+
const marker = `${object}.`;
|
|
143
|
+
const index = name.lastIndexOf(marker);
|
|
144
|
+
if (index < 0)
|
|
145
|
+
return undefined;
|
|
146
|
+
const prefix = name.slice(0, index);
|
|
147
|
+
if (prefix !== "" && !prefix.endsWith("."))
|
|
148
|
+
return undefined;
|
|
149
|
+
const operation = name.slice(index + marker.length);
|
|
150
|
+
return operation.includes(".") ? undefined : operation;
|
|
151
|
+
};
|
|
152
|
+
const senderSubject = (node) => {
|
|
153
|
+
const name = t.isCallExpression(node)
|
|
154
|
+
? calleeName(node.callee)
|
|
155
|
+
: calleeName(node);
|
|
156
|
+
if (/(?:^|\.)sender\.getURL$/u.test(name))
|
|
157
|
+
return "sender-url";
|
|
158
|
+
if (/(?:^|\.)senderFrame\.origin$/u.test(name))
|
|
159
|
+
return "sender-origin";
|
|
160
|
+
if (/(?:^|\.)senderFrame\.url$/u.test(name))
|
|
161
|
+
return "sender-url";
|
|
162
|
+
if (/(?:^|\.)senderFrame$/u.test(name))
|
|
163
|
+
return "sender-frame";
|
|
164
|
+
if (/(?:^|\.)sender\.id$/u.test(name))
|
|
165
|
+
return "sender-id";
|
|
166
|
+
if (/(?:^|\.)frameId$/u.test(name))
|
|
167
|
+
return "frame-id";
|
|
168
|
+
if (/(?:^|\.)processId$/u.test(name))
|
|
169
|
+
return "process-id";
|
|
170
|
+
return undefined;
|
|
171
|
+
};
|