@zhuixin/engine 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/engine-main.js +104 -22
  2. package/package.json +1 -1
@@ -19472,8 +19472,8 @@ var DEFINITIONS = [
19472
19472
  id: "javascript:analyze",
19473
19473
  label: "Analyze JS",
19474
19474
  description: "\u5BF9\u89E3\u5305\u5E94\u7528\u4E2D\u7684 uni-app / WebView \u4E1A\u52A1\u811A\u672C\u505A\u9759\u6001\u5206\u6790\u3002",
19475
- targetPlatforms: ["ios"],
19476
- packageFormats: ["ipa"],
19475
+ targetPlatforms: ["ios", "macos"],
19476
+ packageFormats: ["ipa", "app"],
19477
19477
  requiresArtifact: true,
19478
19478
  requiresRea: true
19479
19479
  },
@@ -20261,6 +20261,12 @@ function renderReportMarkdown(input2) {
20261
20261
  }
20262
20262
  lines.push("");
20263
20263
  }
20264
+ const analysisGaps = findings.filter((finding) => finding.type === "limitation").slice(0, 20);
20265
+ if (analysisGaps.length > 0) {
20266
+ lines.push("### Analysis gaps", "");
20267
+ for (const gap of analysisGaps) lines.push(`- ${gap.value}`);
20268
+ lines.push("");
20269
+ }
20264
20270
  lines.push(
20265
20271
  "## Jobs and evidence",
20266
20272
  "",
@@ -20510,6 +20516,13 @@ function javascriptFindings(job, artifact, evidenceId, parsed, summary) {
20510
20516
  }
20511
20517
  }
20512
20518
  }
20519
+ if (artifact.packageFormat === "app") {
20520
+ push("technology", "Electron", {
20521
+ group: "technology",
20522
+ confidence: "high",
20523
+ metadata: { basis: "electron-bundle" }
20524
+ });
20525
+ }
20513
20526
  const normalized = record2(parsed.normalized_result);
20514
20527
  const graph = record2(normalized?.graph);
20515
20528
  const nodes = Array.isArray(graph?.nodes) ? graph.nodes : [];
@@ -20570,17 +20583,47 @@ function javascriptFindings(job, artifact, evidenceId, parsed, summary) {
20570
20583
  }
20571
20584
  }
20572
20585
  const limitations = Array.isArray(parsed.limitations) ? parsed.limitations : [];
20586
+ const seenLimitations = /* @__PURE__ */ new Set();
20587
+ const LIMITATION_CAP = 50;
20588
+ let kept = 0;
20573
20589
  for (const limitation of limitations) {
20574
- if (typeof limitation === "string") {
20575
- push("limitation", limitation, {
20590
+ if (typeof limitation !== "string") continue;
20591
+ const normalized2 = limitation.replace(/\s+/g, " ").trim();
20592
+ if (!normalized2 || seenLimitations.has(normalized2)) continue;
20593
+ if (kept >= LIMITATION_CAP) break;
20594
+ seenLimitations.add(normalized2);
20595
+ kept += 1;
20596
+ push("limitation", normalized2, {
20597
+ group: "analysis-limitation",
20598
+ confidence: "exact",
20599
+ metadata: { evidenceId }
20600
+ });
20601
+ }
20602
+ if (limitations.length > kept) {
20603
+ push(
20604
+ "limitation",
20605
+ `${limitations.length - kept} additional per-file limitations were omitted from this summary.`,
20606
+ {
20576
20607
  group: "analysis-limitation",
20577
20608
  confidence: "exact",
20578
- metadata: { evidenceId }
20579
- });
20580
- }
20609
+ metadata: { evidenceId, omitted: limitations.length - kept }
20610
+ }
20611
+ );
20581
20612
  }
20582
20613
  return findings;
20583
20614
  }
20615
+ function findElectronJavascriptRoot(appPath) {
20616
+ const asar = import_node_path5.default.join(appPath, "Contents", "Resources", "app.asar");
20617
+ if (import_node_fs5.default.existsSync(asar)) return asar;
20618
+ const unpacked = import_node_path5.default.join(appPath, "Contents", "Resources", "app");
20619
+ if (import_node_fs5.default.existsSync(unpacked) && import_node_fs5.default.statSync(unpacked).isDirectory()) {
20620
+ return unpacked;
20621
+ }
20622
+ fail(
20623
+ "CAPABILITY_UNAVAILABLE",
20624
+ "No Electron JavaScript bundle (app.asar or Resources/app) was found in this app."
20625
+ );
20626
+ }
20584
20627
  function nativeSearchFindings(job, artifact, evidenceId, parsed, kind) {
20585
20628
  const values2 = Array.isArray(parsed.normalized_result) ? parsed.normalized_result : Array.isArray(parsed.raw_result) ? parsed.raw_result : [];
20586
20629
  const createdAt = now();
@@ -20959,31 +21002,52 @@ var CapabilityJobRunner = class {
20959
21002
  }
20960
21003
  async runReaJavascript(job, target, artifact) {
20961
21004
  if (!artifact) fail("ARTIFACT_REQUIRED", "\u8BF7\u5148\u83B7\u53D6 artifact\u3002");
20962
- const extraction = await this.ensureExtraction(job, target, artifact);
20963
- this.log(job, "info", "\u5BF9\u89E3\u5305\u76EE\u5F55\u8FD0\u884C JavaScript \u9759\u6001\u5206\u6790\u3002", {
20964
- path: import_node_path5.default.relative(this.workspace.root, extraction.appRoot)
20965
- });
20966
- this.patch(job, { progress: 25 });
21005
+ let javascriptRoot;
21006
+ if (artifact.packageFormat === "app") {
21007
+ javascriptRoot = findElectronJavascriptRoot(
21008
+ this.workspace.resolveStoredPath(artifact.path)
21009
+ );
21010
+ this.log(job, "info", "Running static analysis on the macOS JavaScript bundle.", {
21011
+ path: import_node_path5.default.relative(this.workspace.root, javascriptRoot)
21012
+ });
21013
+ this.patch(job, { progress: 25 });
21014
+ } else {
21015
+ const extraction = await this.ensureExtraction(job, target, artifact);
21016
+ javascriptRoot = extraction.appRoot;
21017
+ this.log(job, "info", "\u5BF9\u89E3\u5305\u76EE\u5F55\u8FD0\u884C JavaScript \u9759\u6001\u5206\u6790\u3002", {
21018
+ path: import_node_path5.default.relative(this.workspace.root, javascriptRoot)
21019
+ });
21020
+ this.patch(job, { progress: 25 });
21021
+ }
20967
21022
  const rea = await this.runReaJson(
20968
21023
  job,
20969
21024
  target,
20970
21025
  "javascript-analyze",
20971
21026
  [
20972
21027
  "analyze-javascript-application",
20973
- extraction.appRoot,
21028
+ javascriptRoot,
20974
21029
  "--analysis-timeout-ms",
20975
21030
  "300000"
20976
21031
  ],
20977
- 10 * 6e4
21032
+ // Electron bundles are much larger than iOS web bundles; a 136 MB asar
21033
+ // takes several minutes on its own.
21034
+ 15 * 6e4
20978
21035
  );
20979
21036
  const evidenceId = this.reaEvidenceId(rea);
21037
+ const summary = { ...rea.summary };
21038
+ if (artifact.packageFormat === "app") {
21039
+ const technology = record2(summary.technology) ?? {};
21040
+ const hints = Array.isArray(technology.hints) ? [...technology.hints] : [];
21041
+ if (!hints.includes("Electron")) hints.unshift("Electron");
21042
+ summary.technology = { ...technology, hints };
21043
+ }
20980
21044
  this.persistEvidence(
20981
21045
  job,
20982
21046
  artifact,
20983
21047
  "javascript-analysis",
20984
21048
  rea,
20985
21049
  evidenceId,
20986
- javascriptFindings(job, artifact, evidenceId, rea.parsed, rea.summary),
21050
+ javascriptFindings(job, artifact, evidenceId, rea.parsed, summary),
20987
21051
  [
20988
21052
  "technology",
20989
21053
  "route",
@@ -20998,9 +21062,9 @@ var CapabilityJobRunner = class {
20998
21062
  status: "analyzed",
20999
21063
  progress: 100,
21000
21064
  result: {
21001
- ...rea.summary,
21065
+ ...summary,
21002
21066
  evidenceId,
21003
- outputDir: import_node_path5.default.relative(this.workspace.root, extraction.appRoot),
21067
+ outputDir: import_node_path5.default.relative(this.workspace.root, javascriptRoot),
21004
21068
  evidencePath: rea.rawPath
21005
21069
  },
21006
21070
  finishedAt: now()
@@ -21172,16 +21236,34 @@ var CapabilityJobRunner = class {
21172
21236
  "reports",
21173
21237
  `${job.id}.md`
21174
21238
  );
21175
- const findingResult = this.store.searchFindings({
21239
+ const findingTypes = [
21240
+ "technology",
21241
+ "route",
21242
+ "network_endpoint",
21243
+ "module",
21244
+ "asset",
21245
+ "storage",
21246
+ "native_procedure",
21247
+ "risk",
21248
+ "limitation"
21249
+ ];
21250
+ const findings = findingTypes.flatMap(
21251
+ (type) => this.store.searchFindings({
21252
+ targetId: target.id,
21253
+ types: [type],
21254
+ limit: 20
21255
+ }).items
21256
+ );
21257
+ const findingTotal = this.store.searchFindings({
21176
21258
  targetId: target.id,
21177
- limit: 1e3
21178
- });
21259
+ limit: 1
21260
+ }).total;
21179
21261
  const markdown = renderReportMarkdown({
21180
21262
  target,
21181
21263
  artifact,
21182
21264
  jobs: this.store.listJobs(target.id).filter((item) => item.id !== job.id).slice(0, 20),
21183
- findings: findingResult.items,
21184
- findingTotal: findingResult.total,
21265
+ findings,
21266
+ findingTotal,
21185
21267
  hostPlatform: this.config.hostPlatform,
21186
21268
  generatedAt
21187
21269
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhuixin/engine",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "description": "AppTrace analysis engine (compiled)",