@harness-engineering/eslint-plugin 0.2.4 → 0.3.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/dist/index.d.ts CHANGED
@@ -22,6 +22,9 @@ declare const rules: {
22
22
  'no-nested-loops-in-critical': _typescript_eslint_utils_ts_eslint.RuleModule<"nestedLoopInCritical", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
23
23
  name: string;
24
24
  };
25
+ 'no-process-env-in-spawn': _typescript_eslint_utils_ts_eslint.RuleModule<"processEnvInSpawn", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
26
+ name: string;
27
+ };
25
28
  'no-sync-io-in-async': _typescript_eslint_utils_ts_eslint.RuleModule<"syncIoInAsync", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
26
29
  name: string;
27
30
  };
@@ -66,6 +69,9 @@ declare const plugin: {
66
69
  'no-nested-loops-in-critical': _typescript_eslint_utils_ts_eslint.RuleModule<"nestedLoopInCritical", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
67
70
  name: string;
68
71
  };
72
+ 'no-process-env-in-spawn': _typescript_eslint_utils_ts_eslint.RuleModule<"processEnvInSpawn", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
73
+ name: string;
74
+ };
69
75
  'no-sync-io-in-async': _typescript_eslint_utils_ts_eslint.RuleModule<"syncIoInAsync", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
70
76
  name: string;
71
77
  };
@@ -95,6 +101,7 @@ declare const plugin: {
95
101
  '@harness-engineering/enforce-doc-exports': string;
96
102
  '@harness-engineering/no-unix-shell-command': string;
97
103
  '@harness-engineering/no-hardcoded-path-separator': string;
104
+ '@harness-engineering/no-process-env-in-spawn': string;
98
105
  '@harness-engineering/require-path-normalization': string;
99
106
  };
100
107
  };
@@ -110,6 +117,7 @@ declare const plugin: {
110
117
  '@harness-engineering/enforce-doc-exports': string;
111
118
  '@harness-engineering/no-unix-shell-command': string;
112
119
  '@harness-engineering/no-hardcoded-path-separator': string;
120
+ '@harness-engineering/no-process-env-in-spawn': string;
113
121
  '@harness-engineering/require-path-normalization': string;
114
122
  };
115
123
  };
@@ -146,6 +154,9 @@ declare const configs: {
146
154
  'no-nested-loops-in-critical': _typescript_eslint_utils_ts_eslint.RuleModule<"nestedLoopInCritical", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
147
155
  name: string;
148
156
  };
157
+ 'no-process-env-in-spawn': _typescript_eslint_utils_ts_eslint.RuleModule<"processEnvInSpawn", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
158
+ name: string;
159
+ };
149
160
  'no-sync-io-in-async': _typescript_eslint_utils_ts_eslint.RuleModule<"syncIoInAsync", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
150
161
  name: string;
151
162
  };
@@ -173,6 +184,7 @@ declare const configs: {
173
184
  '@harness-engineering/enforce-doc-exports': string;
174
185
  '@harness-engineering/no-unix-shell-command': string;
175
186
  '@harness-engineering/no-hardcoded-path-separator': string;
187
+ '@harness-engineering/no-process-env-in-spawn': string;
176
188
  '@harness-engineering/require-path-normalization': string;
177
189
  };
178
190
  };
@@ -205,6 +217,9 @@ declare const configs: {
205
217
  'no-nested-loops-in-critical': _typescript_eslint_utils_ts_eslint.RuleModule<"nestedLoopInCritical", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
206
218
  name: string;
207
219
  };
220
+ 'no-process-env-in-spawn': _typescript_eslint_utils_ts_eslint.RuleModule<"processEnvInSpawn", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
221
+ name: string;
222
+ };
208
223
  'no-sync-io-in-async': _typescript_eslint_utils_ts_eslint.RuleModule<"syncIoInAsync", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
209
224
  name: string;
210
225
  };
@@ -232,6 +247,7 @@ declare const configs: {
232
247
  '@harness-engineering/enforce-doc-exports': string;
233
248
  '@harness-engineering/no-unix-shell-command': string;
234
249
  '@harness-engineering/no-hardcoded-path-separator': string;
250
+ '@harness-engineering/no-process-env-in-spawn': string;
235
251
  '@harness-engineering/require-path-normalization': string;
236
252
  };
237
253
  };
package/dist/index.js CHANGED
@@ -935,11 +935,71 @@ var no_hardcoded_path_separator_default = createRule10({
935
935
  }
936
936
  });
937
937
 
938
- // src/rules/require-path-normalization.ts
938
+ // src/rules/no-process-env-in-spawn.ts
939
939
  import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
940
940
  var createRule11 = ESLintUtils11.RuleCreator(
941
941
  (name) => `https://github.com/harness-engineering/eslint-plugin/blob/main/docs/rules/${name}.md`
942
942
  );
943
+ var SPAWN_FUNCTIONS = /* @__PURE__ */ new Set(["spawn", "spawnSync", "execFile", "execFileSync", "fork"]);
944
+ function getSpawnFunctionName(node) {
945
+ if (node.callee.type === "Identifier" && SPAWN_FUNCTIONS.has(node.callee.name)) {
946
+ return node.callee.name;
947
+ }
948
+ if (node.callee.type === "MemberExpression" && node.callee.property.type === "Identifier" && SPAWN_FUNCTIONS.has(node.callee.property.name)) {
949
+ return node.callee.property.name;
950
+ }
951
+ return void 0;
952
+ }
953
+ function isProcessEnv(node) {
954
+ return node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === "process" && node.property.type === "Identifier" && node.property.name === "env";
955
+ }
956
+ function hasProcessEnvProperty(node) {
957
+ for (const prop of node.properties) {
958
+ if (prop.type === "Property" && prop.key.type === "Identifier" && prop.key.name === "env" && isProcessEnv(prop.value)) {
959
+ return prop;
960
+ }
961
+ if (prop.type === "SpreadElement" && isProcessEnv(prop.argument)) {
962
+ return prop;
963
+ }
964
+ }
965
+ return void 0;
966
+ }
967
+ var no_process_env_in_spawn_default = createRule11({
968
+ name: "no-process-env-in-spawn",
969
+ meta: {
970
+ type: "problem",
971
+ docs: {
972
+ description: "Disallow passing process.env directly to spawn/execFile/fork, which leaks all server-side secrets to child processes"
973
+ },
974
+ messages: {
975
+ processEnvInSpawn: "Do not pass process.env directly to '{{name}}'. Build an explicit env object with only the variables the child process needs."
976
+ },
977
+ schema: []
978
+ },
979
+ defaultOptions: [],
980
+ create(context) {
981
+ return {
982
+ CallExpression(node) {
983
+ const name = getSpawnFunctionName(node);
984
+ if (!name) return;
985
+ for (const arg of node.arguments) {
986
+ if (arg.type === "ObjectExpression") {
987
+ const envProp = hasProcessEnvProperty(arg);
988
+ if (envProp) {
989
+ context.report({ node: envProp, messageId: "processEnvInSpawn", data: { name } });
990
+ }
991
+ }
992
+ }
993
+ }
994
+ };
995
+ }
996
+ });
997
+
998
+ // src/rules/require-path-normalization.ts
999
+ import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
1000
+ var createRule12 = ESLintUtils12.RuleCreator(
1001
+ (name) => `https://github.com/harness-engineering/eslint-plugin/blob/main/docs/rules/${name}.md`
1002
+ );
943
1003
  function isRelativeCall(node) {
944
1004
  const callee = node.callee;
945
1005
  if (callee.type === "Identifier" && callee.name === "relative") {
@@ -965,7 +1025,7 @@ function hasNormalization(node) {
965
1025
  if (grandparent?.type !== "CallExpression" || grandparent.arguments.length < 1) return false;
966
1026
  return isBackslashNormalizationArg(grandparent.arguments[0]);
967
1027
  }
968
- var require_path_normalization_default = createRule11({
1028
+ var require_path_normalization_default = createRule12({
969
1029
  name: "require-path-normalization",
970
1030
  meta: {
971
1031
  type: "problem",
@@ -1000,6 +1060,7 @@ var rules = {
1000
1060
  "no-hardcoded-path-separator": no_hardcoded_path_separator_default,
1001
1061
  "no-layer-violation": no_layer_violation_default,
1002
1062
  "no-nested-loops-in-critical": no_nested_loops_in_critical_default,
1063
+ "no-process-env-in-spawn": no_process_env_in_spawn_default,
1003
1064
  "no-sync-io-in-async": no_sync_io_in_async_default,
1004
1065
  "no-unbounded-array-chains": no_unbounded_array_chains_default,
1005
1066
  "no-unix-shell-command": no_unix_shell_command_default,
@@ -1029,6 +1090,7 @@ var plugin = {
1029
1090
  "@harness-engineering/enforce-doc-exports": "warn",
1030
1091
  "@harness-engineering/no-unix-shell-command": "warn",
1031
1092
  "@harness-engineering/no-hardcoded-path-separator": "warn",
1093
+ "@harness-engineering/no-process-env-in-spawn": "error",
1032
1094
  "@harness-engineering/require-path-normalization": "warn"
1033
1095
  }
1034
1096
  },
@@ -1046,6 +1108,7 @@ var plugin = {
1046
1108
  "@harness-engineering/enforce-doc-exports": "error",
1047
1109
  "@harness-engineering/no-unix-shell-command": "error",
1048
1110
  "@harness-engineering/no-hardcoded-path-separator": "error",
1111
+ "@harness-engineering/no-process-env-in-spawn": "error",
1049
1112
  "@harness-engineering/require-path-normalization": "error"
1050
1113
  }
1051
1114
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-engineering/eslint-plugin",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "ESLint plugin for harness engineering architectural constraints",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,19 +16,19 @@
16
16
  "README.md"
17
17
  ],
18
18
  "dependencies": {
19
- "@typescript-eslint/utils": "^8.58.0",
19
+ "@typescript-eslint/utils": "^8.59.0",
20
20
  "minimatch": "^10.2.5",
21
21
  "zod": "^3.25.76"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^22.19.15",
25
- "@typescript-eslint/parser": "^8.58.0",
26
- "@typescript-eslint/rule-tester": "^8.58.0",
27
- "@vitest/coverage-v8": "^4.1.2",
28
- "eslint": "^10.1.0",
25
+ "@typescript-eslint/parser": "^8.59.0",
26
+ "@typescript-eslint/rule-tester": "^8.59.0",
27
+ "@vitest/coverage-v8": "^4.1.5",
28
+ "eslint": "^10.2.1",
29
29
  "tsup": "^8.5.1",
30
30
  "typescript": "^5.9.3",
31
- "vitest": "^4.1.2"
31
+ "vitest": "^4.1.5"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "eslint": "^8.0.0 || ^9.0.0 || ^10.0.0",