eslint-plugin-rulvar 1.36.0 → 1.38.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.
Files changed (2) hide show
  1. package/dist/index.js +69 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -151,6 +151,73 @@ const noProcessEnv = {
151
151
  }
152
152
  };
153
153
  //#endregion
154
+ //#region src/rules/dialect.ts
155
+ const noCodeGeneration = {
156
+ meta: {
157
+ type: "problem",
158
+ docs: { description: "ban dynamic code generation (eval, the Function constructor, and .constructor access) in workflow modules; it reopens the import allowlist and the ambient capability surface the sandbox dialect closes" },
159
+ messages: {
160
+ noEval: "eval is not part of the workflow dialect; it compiles code in a fresh scope that reopens import() and ambient capability. Stay on the ctx surface.",
161
+ noFunctionConstructor: "the Function constructor is not part of the workflow dialect; it compiles arbitrary code that bypasses the import allowlist. Stay on the ctx surface.",
162
+ noConstructorAccess: ".constructor access reaches the Function constructor from any function value and reopens dynamic code generation; it is not part of the workflow dialect."
163
+ },
164
+ schema: []
165
+ },
166
+ create(context) {
167
+ const checkCallee = (node, callee) => {
168
+ if (callee.type === "Identifier" && isGlobalReference(context, callee)) {
169
+ if (callee.name === "eval") {
170
+ context.report({
171
+ node,
172
+ messageId: "noEval"
173
+ });
174
+ return;
175
+ }
176
+ if (callee.name === "Function") {
177
+ context.report({
178
+ node,
179
+ messageId: "noFunctionConstructor"
180
+ });
181
+ return;
182
+ }
183
+ }
184
+ if (isGlobalMemberCall(context, callee, "globalThis", "eval")) {
185
+ context.report({
186
+ node,
187
+ messageId: "noEval"
188
+ });
189
+ return;
190
+ }
191
+ if (isGlobalMemberCall(context, callee, "globalThis", "Function")) context.report({
192
+ node,
193
+ messageId: "noFunctionConstructor"
194
+ });
195
+ };
196
+ return {
197
+ CallExpression(node) {
198
+ checkCallee(node, node.callee);
199
+ },
200
+ NewExpression(node) {
201
+ checkCallee(node, node.callee);
202
+ },
203
+ MemberExpression(node) {
204
+ const { property, computed } = node;
205
+ if (!computed && property.type === "Identifier" && property.name === "constructor") {
206
+ context.report({
207
+ node,
208
+ messageId: "noConstructorAccess"
209
+ });
210
+ return;
211
+ }
212
+ if (computed && property.type === "Literal" && property.value === "constructor") context.report({
213
+ node,
214
+ messageId: "noConstructorAccess"
215
+ });
216
+ }
217
+ };
218
+ }
219
+ };
220
+ //#endregion
154
221
  //#region src/rules/scheduling.ts
155
222
  const PROMISE_COMBINATORS = /* @__PURE__ */ new Set([
156
223
  "all",
@@ -245,6 +312,7 @@ const rules = {
245
312
  "no-bare-random": noBareRandom,
246
313
  "no-fetch": noFetch,
247
314
  "no-process-env": noProcessEnv,
315
+ "no-code-generation": noCodeGeneration,
248
316
  "no-promise-all-over-ctx": noPromiseAllOverCtx,
249
317
  "duplicate-identical-call": duplicateIdenticalCall
250
318
  };
@@ -264,6 +332,7 @@ const workflowsConfig = {
264
332
  "rulvar/no-bare-random": "error",
265
333
  "rulvar/no-fetch": "error",
266
334
  "rulvar/no-process-env": "error",
335
+ "rulvar/no-code-generation": "error",
267
336
  "rulvar/no-promise-all-over-ctx": "error",
268
337
  "rulvar/duplicate-identical-call": "warn"
269
338
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-rulvar",
3
- "version": "1.36.0",
3
+ "version": "1.38.0",
4
4
  "description": "Rulvar determinism lint rules with structural JSON diagnostics for the planner self-repair loop.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",