@inspecto-dev/plugin 0.3.4 → 0.3.6

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 (39) hide show
  1. package/dist/index.cjs +179 -44
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +179 -44
  4. package/dist/index.js.map +1 -1
  5. package/dist/legacy/rspack/index.cjs +108 -18
  6. package/dist/legacy/rspack/index.cjs.map +1 -1
  7. package/dist/legacy/rspack/index.js +108 -18
  8. package/dist/legacy/rspack/index.js.map +1 -1
  9. package/dist/legacy/rspack/loader.cjs +49 -4
  10. package/dist/legacy/rspack/loader.cjs.map +1 -1
  11. package/dist/legacy/rspack/loader.js +49 -4
  12. package/dist/legacy/rspack/loader.js.map +1 -1
  13. package/dist/legacy/webpack4/index.cjs +120 -20
  14. package/dist/legacy/webpack4/index.cjs.map +1 -1
  15. package/dist/legacy/webpack4/index.d.cts +2 -0
  16. package/dist/legacy/webpack4/index.d.ts +2 -0
  17. package/dist/legacy/webpack4/index.js +120 -20
  18. package/dist/legacy/webpack4/index.js.map +1 -1
  19. package/dist/legacy/webpack4/loader.cjs +49 -4
  20. package/dist/legacy/webpack4/loader.cjs.map +1 -1
  21. package/dist/legacy/webpack4/loader.js +49 -4
  22. package/dist/legacy/webpack4/loader.js.map +1 -1
  23. package/dist/rollup.cjs +179 -44
  24. package/dist/rollup.cjs.map +1 -1
  25. package/dist/rollup.js +179 -44
  26. package/dist/rollup.js.map +1 -1
  27. package/dist/rspack.cjs +179 -44
  28. package/dist/rspack.cjs.map +1 -1
  29. package/dist/rspack.js +179 -44
  30. package/dist/rspack.js.map +1 -1
  31. package/dist/vite.cjs +179 -44
  32. package/dist/vite.cjs.map +1 -1
  33. package/dist/vite.js +179 -44
  34. package/dist/vite.js.map +1 -1
  35. package/dist/webpack.cjs +179 -44
  36. package/dist/webpack.cjs.map +1 -1
  37. package/dist/webpack.js +179 -44
  38. package/dist/webpack.js.map +1 -1
  39. package/package.json +2 -2
@@ -14,7 +14,7 @@ var __dirname = /* @__PURE__ */ getDirname();
14
14
 
15
15
  // src/server/index.ts
16
16
  import http from "http";
17
- import fs4 from "fs";
17
+ import fs5 from "fs";
18
18
  import path6 from "path";
19
19
  import os2 from "os";
20
20
  import crypto2 from "crypto";
@@ -538,6 +538,7 @@ function hasOverrides(overrides) {
538
538
 
539
539
  // src/server/path-guards.ts
540
540
  import path4 from "path";
541
+ import fs3 from "fs";
541
542
  function isWindowsAbsolutePath(file) {
542
543
  return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
543
544
  }
@@ -548,9 +549,94 @@ function resolveWorkspacePath(file, cwd) {
548
549
  return path4.isAbsolute(file) ? path4.resolve(file) : path4.resolve(cwd, file);
549
550
  }
550
551
  function assertPathWithinProject(file, projectRoot) {
551
- const relativeToRoot = isWindowsAbsolutePath(file) || isWindowsAbsolutePath(projectRoot) ? path4.win32.relative(path4.win32.normalize(projectRoot), path4.win32.normalize(file)) : path4.relative(projectRoot, file);
552
- if (relativeToRoot.startsWith("..") || path4.isAbsolute(relativeToRoot)) {
553
- throw new Error("Access denied: File is outside of project workspace");
552
+ let realFile = file;
553
+ let realProjectRoot = projectRoot;
554
+ try {
555
+ if (fs3.existsSync(file)) {
556
+ realFile = fs3.realpathSync(file);
557
+ }
558
+ } catch {
559
+ }
560
+ try {
561
+ if (fs3.existsSync(projectRoot)) {
562
+ realProjectRoot = fs3.realpathSync(projectRoot);
563
+ }
564
+ } catch {
565
+ }
566
+ if (isWithinPath(file, projectRoot) || isWithinPath(realFile, realProjectRoot)) {
567
+ return;
568
+ }
569
+ throw new Error(
570
+ `Access denied: File ${normalizeForComparison(realFile)} is outside of project workspace ${normalizeForComparison(realProjectRoot)}`
571
+ );
572
+ }
573
+ function tryReadPackageName(packageRoot) {
574
+ try {
575
+ const packageJsonPath = path4.join(packageRoot, "package.json");
576
+ if (!fs3.existsSync(packageJsonPath)) return void 0;
577
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
578
+ return typeof packageJson.name === "string" ? packageJson.name : void 0;
579
+ } catch {
580
+ return void 0;
581
+ }
582
+ }
583
+ function findNearestPackageRoot(file) {
584
+ let current = path4.dirname(file);
585
+ while (true) {
586
+ if (fs3.existsSync(path4.join(current, "package.json"))) {
587
+ return current;
588
+ }
589
+ const parent = path4.dirname(current);
590
+ if (parent === current) {
591
+ return void 0;
592
+ }
593
+ current = parent;
594
+ }
595
+ }
596
+ function normalizeForComparison(file) {
597
+ return isWindowsAbsolutePath(file) ? path4.win32.normalize(file) : path4.normalize(file);
598
+ }
599
+ function pathSeparatorFor(file) {
600
+ return isWindowsAbsolutePath(file) ? path4.win32.sep : path4.sep;
601
+ }
602
+ function isWithinPath(file, root) {
603
+ const normalizedFile = normalizeForComparison(file);
604
+ const normalizedRoot = normalizeForComparison(root);
605
+ const separator = pathSeparatorFor(normalizedRoot);
606
+ const rootWithSep = normalizedRoot.endsWith(separator) ? normalizedRoot : normalizedRoot + separator;
607
+ return normalizedFile === normalizedRoot || normalizedFile.startsWith(rootWithSep);
608
+ }
609
+ function resolveLinkedDependencyEntry(projectRoot, packageName) {
610
+ const packageSegments = packageName.split("/");
611
+ const dependencyPath = path4.join(projectRoot, "node_modules", ...packageSegments);
612
+ if (!fs3.existsSync(dependencyPath)) return void 0;
613
+ try {
614
+ return fs3.realpathSync(dependencyPath);
615
+ } catch {
616
+ return dependencyPath;
617
+ }
618
+ }
619
+ function isLinkedDependencyPath(file, projectRoot, packageName) {
620
+ const linkedDependencyRoot = resolveLinkedDependencyEntry(projectRoot, packageName);
621
+ if (!linkedDependencyRoot) return false;
622
+ return isWithinPath(file, linkedDependencyRoot);
623
+ }
624
+ function isLinkedDependencySourcePath(file, projectRoot) {
625
+ const packageRoot = findNearestPackageRoot(file);
626
+ if (!packageRoot) return false;
627
+ const packageName = tryReadPackageName(packageRoot);
628
+ if (!packageName) return false;
629
+ return isLinkedDependencyPath(file, projectRoot, packageName);
630
+ }
631
+ function assertPathWithinIdeOpenScope(file, projectRoot) {
632
+ try {
633
+ assertPathWithinProject(file, projectRoot);
634
+ return;
635
+ } catch {
636
+ if (isLinkedDependencySourcePath(file, projectRoot)) {
637
+ return;
638
+ }
639
+ throw new Error(`Access denied: File is outside of project workspace`);
554
640
  }
555
641
  }
556
642
 
@@ -755,7 +841,7 @@ var VSCODE_FAMILY_SCHEMES = [
755
841
  ];
756
842
  function handleOpenFileRequest(body, serverState3) {
757
843
  const absolutePath = resolveWorkspacePath(body.file, serverState3.cwd);
758
- assertPathWithinProject(absolutePath, serverState3.projectRoot);
844
+ assertPathWithinIdeOpenScope(absolutePath, serverState3.projectRoot);
759
845
  const userConfig = loadUserConfigSync(false, serverState3.cwd, serverState3.configRoot);
760
846
  const configuredIde = userConfig.ide;
761
847
  const activeIde = serverState3.ideInfo?.ide;
@@ -813,7 +899,7 @@ function handleOpenFileRequest(body, serverState3) {
813
899
  }
814
900
 
815
901
  // src/server/project-root.ts
816
- import fs3 from "fs";
902
+ import fs4 from "fs";
817
903
  import path5 from "path";
818
904
  import { execSync } from "child_process";
819
905
  var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
@@ -831,7 +917,7 @@ function resolveProjectRoot() {
831
917
  let current = start;
832
918
  while (!visited.has(current)) {
833
919
  visited.add(current);
834
- if (fs3.existsSync(path5.join(current, ".inspecto"))) return current;
920
+ if (fs4.existsSync(path5.join(current, ".inspecto"))) return current;
835
921
  if (current === stop) break;
836
922
  const parent = path5.dirname(current);
837
923
  if (parent === current) break;
@@ -903,28 +989,28 @@ async function startServer() {
903
989
  const portFile = path6.join(os2.tmpdir(), "inspecto.port.json");
904
990
  try {
905
991
  let portData = {};
906
- if (fs4.existsSync(portFile)) {
992
+ if (fs5.existsSync(portFile)) {
907
993
  try {
908
- portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
994
+ portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
909
995
  } catch (e) {
910
996
  }
911
997
  }
912
998
  const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
913
999
  portData[rootHash] = port;
914
- fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1000
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
915
1001
  } catch (e) {
916
1002
  serverLogger4.warn("Failed to write port file:", e);
917
1003
  }
918
1004
  process.once("exit", () => {
919
1005
  try {
920
- if (fs4.existsSync(portFile)) {
921
- const portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
1006
+ if (fs5.existsSync(portFile)) {
1007
+ const portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
922
1008
  const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
923
1009
  delete portData[rootHash];
924
1010
  if (Object.keys(portData).length === 0) {
925
- fs4.unlinkSync(portFile);
1011
+ fs5.unlinkSync(portFile);
926
1012
  } else {
927
- fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1013
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
928
1014
  }
929
1015
  }
930
1016
  } catch {
@@ -993,8 +1079,10 @@ async function handleRequest(url, req, res) {
993
1079
  }
994
1080
  try {
995
1081
  handleOpenFileRequest(body, serverState);
996
- } catch {
997
- serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
1082
+ } catch (err) {
1083
+ serverLogger4.warn(
1084
+ `Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}. Reason: ${err.message}`
1085
+ );
998
1086
  res.writeHead(403, { "Content-Type": "application/json" });
999
1087
  res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
1000
1088
  return;
@@ -1012,8 +1100,10 @@ async function handleRequest(url, req, res) {
1012
1100
  const absolutePath = resolveWorkspacePath(file, serverState.cwd);
1013
1101
  try {
1014
1102
  assertPathWithinProject(absolutePath, serverState.projectRoot);
1015
- } catch {
1016
- serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
1103
+ } catch (err) {
1104
+ serverLogger4.warn(
1105
+ `Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}. Reason: ${err.message}`
1106
+ );
1017
1107
  res.writeHead(403, { "Content-Type": "application/json" });
1018
1108
  res.end(
1019
1109
  JSON.stringify({