@nocobase/plugin-flow-engine 2.0.0-alpha.2

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 (125) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +29 -0
  3. package/build.config.ts +22 -0
  4. package/client.d.ts +2 -0
  5. package/client.js +1 -0
  6. package/dist/client/index.d.ts +15 -0
  7. package/dist/client/index.js +10 -0
  8. package/dist/externalVersion.js +21 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.js +48 -0
  11. package/dist/locale/en-US.json +61 -0
  12. package/dist/locale/index.d.ts +141 -0
  13. package/dist/locale/index.js +79 -0
  14. package/dist/locale/zh-CN.json +61 -0
  15. package/dist/node_modules/ses/LICENSE +201 -0
  16. package/dist/node_modules/ses/LICENSE-aura +16 -0
  17. package/dist/node_modules/ses/LICENSE-caja +13 -0
  18. package/dist/node_modules/ses/LICENSE-corejs +19 -0
  19. package/dist/node_modules/ses/LICENSE-v8 +9 -0
  20. package/dist/node_modules/ses/assert-shim.js +1 -0
  21. package/dist/node_modules/ses/compartment-shim.js +1 -0
  22. package/dist/node_modules/ses/console-shim.js +1 -0
  23. package/dist/node_modules/ses/dist/lockdown.cjs +13912 -0
  24. package/dist/node_modules/ses/dist/lockdown.umd.js +13912 -0
  25. package/dist/node_modules/ses/dist/lockdown.umd.min.js +1 -0
  26. package/dist/node_modules/ses/dist/ses-hermes.cjs +13912 -0
  27. package/dist/node_modules/ses/dist/ses.cjs +1 -0
  28. package/dist/node_modules/ses/dist/ses.umd.js +13912 -0
  29. package/dist/node_modules/ses/dist/ses.umd.min.js +1 -0
  30. package/dist/node_modules/ses/dist/types.d.cts +606 -0
  31. package/dist/node_modules/ses/index.js +18 -0
  32. package/dist/node_modules/ses/lockdown-shim.js +1 -0
  33. package/dist/node_modules/ses/lockdown.js +1 -0
  34. package/dist/node_modules/ses/package.json +1 -0
  35. package/dist/node_modules/ses/src/assert-shim.js +4 -0
  36. package/dist/node_modules/ses/src/assert-sloppy-mode.js +11 -0
  37. package/dist/node_modules/ses/src/cauterize-property.js +69 -0
  38. package/dist/node_modules/ses/src/commons.js +425 -0
  39. package/dist/node_modules/ses/src/compartment-evaluate.js +93 -0
  40. package/dist/node_modules/ses/src/compartment-shim.js +22 -0
  41. package/dist/node_modules/ses/src/compartment.js +477 -0
  42. package/dist/node_modules/ses/src/console-shim.js +50 -0
  43. package/dist/node_modules/ses/src/enable-property-overrides.js +211 -0
  44. package/dist/node_modules/ses/src/enablements.js +244 -0
  45. package/dist/node_modules/ses/src/error/assert.js +584 -0
  46. package/dist/node_modules/ses/src/error/console.js +541 -0
  47. package/dist/node_modules/ses/src/error/fatal-assert.js +54 -0
  48. package/dist/node_modules/ses/src/error/internal-types.js +98 -0
  49. package/dist/node_modules/ses/src/error/note-log-args.js +77 -0
  50. package/dist/node_modules/ses/src/error/stringify-utils.js +195 -0
  51. package/dist/node_modules/ses/src/error/tame-console.js +197 -0
  52. package/dist/node_modules/ses/src/error/tame-error-constructor.js +284 -0
  53. package/dist/node_modules/ses/src/error/tame-v8-error-constructor.js +386 -0
  54. package/dist/node_modules/ses/src/error/types.js +59 -0
  55. package/dist/node_modules/ses/src/error/unhandled-rejection.js +122 -0
  56. package/dist/node_modules/ses/src/eval-scope.js +89 -0
  57. package/dist/node_modules/ses/src/get-anonymous-intrinsics.js +181 -0
  58. package/dist/node_modules/ses/src/get-source-url.js +50 -0
  59. package/dist/node_modules/ses/src/global-object.js +175 -0
  60. package/dist/node_modules/ses/src/intrinsics.js +192 -0
  61. package/dist/node_modules/ses/src/lockdown-shim.js +37 -0
  62. package/dist/node_modules/ses/src/lockdown.js +558 -0
  63. package/dist/node_modules/ses/src/make-eval-function.js +28 -0
  64. package/dist/node_modules/ses/src/make-evaluate.js +110 -0
  65. package/dist/node_modules/ses/src/make-function-constructor.js +79 -0
  66. package/dist/node_modules/ses/src/make-hardener.js +275 -0
  67. package/dist/node_modules/ses/src/make-safe-evaluator.js +112 -0
  68. package/dist/node_modules/ses/src/module-instance.js +497 -0
  69. package/dist/node_modules/ses/src/module-link.js +159 -0
  70. package/dist/node_modules/ses/src/module-load.js +719 -0
  71. package/dist/node_modules/ses/src/module-proxy.js +200 -0
  72. package/dist/node_modules/ses/src/permits-intrinsics.js +291 -0
  73. package/dist/node_modules/ses/src/permits.js +1761 -0
  74. package/dist/node_modules/ses/src/reporting-types.d.ts +13 -0
  75. package/dist/node_modules/ses/src/reporting.js +105 -0
  76. package/dist/node_modules/ses/src/scope-constants.js +180 -0
  77. package/dist/node_modules/ses/src/shim-arraybuffer-transfer.js +85 -0
  78. package/dist/node_modules/ses/src/sloppy-globals-scope-terminator.js +61 -0
  79. package/dist/node_modules/ses/src/strict-scope-terminator.js +99 -0
  80. package/dist/node_modules/ses/src/tame-date-constructor.js +127 -0
  81. package/dist/node_modules/ses/src/tame-domains.js +41 -0
  82. package/dist/node_modules/ses/src/tame-faux-data-properties.js +210 -0
  83. package/dist/node_modules/ses/src/tame-function-constructors.js +140 -0
  84. package/dist/node_modules/ses/src/tame-function-tostring.js +50 -0
  85. package/dist/node_modules/ses/src/tame-harden.js +29 -0
  86. package/dist/node_modules/ses/src/tame-locale-methods.js +78 -0
  87. package/dist/node_modules/ses/src/tame-math-object.js +41 -0
  88. package/dist/node_modules/ses/src/tame-module-source.js +51 -0
  89. package/dist/node_modules/ses/src/tame-regenerator-runtime.js +29 -0
  90. package/dist/node_modules/ses/src/tame-regexp-constructor.js +65 -0
  91. package/dist/node_modules/ses/src/tame-symbol-constructor.js +64 -0
  92. package/dist/node_modules/ses/src/transforms.js +267 -0
  93. package/dist/node_modules/ses/tools.js +25 -0
  94. package/dist/node_modules/ses/types.d.ts +606 -0
  95. package/dist/server/actions/ui-schema-action.d.ts +27 -0
  96. package/dist/server/actions/ui-schema-action.js +118 -0
  97. package/dist/server/collections/flowModelTreePath.d.ts +11 -0
  98. package/dist/server/collections/flowModelTreePath.js +74 -0
  99. package/dist/server/collections/flowModels.d.ts +11 -0
  100. package/dist/server/collections/flowModels.js +57 -0
  101. package/dist/server/collections/flowsql.d.ts +10 -0
  102. package/dist/server/collections/flowsql.js +51 -0
  103. package/dist/server/dao/ui_schema_node_dao.d.ts +26 -0
  104. package/dist/server/dao/ui_schema_node_dao.js +24 -0
  105. package/dist/server/helper.d.ts +8 -0
  106. package/dist/server/helper.js +9 -0
  107. package/dist/server/index.d.ts +9 -0
  108. package/dist/server/index.js +42 -0
  109. package/dist/server/model.d.ts +12 -0
  110. package/dist/server/model.js +38 -0
  111. package/dist/server/plugin.d.ts +26 -0
  112. package/dist/server/plugin.js +270 -0
  113. package/dist/server/repository.d.ts +116 -0
  114. package/dist/server/repository.js +1209 -0
  115. package/dist/server/server.d.ts +16 -0
  116. package/dist/server/server.js +198 -0
  117. package/dist/server/template/contexts.d.ts +73 -0
  118. package/dist/server/template/contexts.js +233 -0
  119. package/dist/server/template/resolver.d.ts +30 -0
  120. package/dist/server/template/resolver.js +225 -0
  121. package/dist/server/variables/registry.d.ts +42 -0
  122. package/dist/server/variables/registry.js +299 -0
  123. package/package.json +28 -0
  124. package/server.d.ts +2 -0
  125. package/server.js +1 -0
@@ -0,0 +1,558 @@
1
+ // Copyright (C) 2018 Agoric
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // @ts-check
16
+
17
+ import { getEnvironmentOption as getenv } from '@endo/env-options';
18
+ import '@endo/immutable-arraybuffer/shim.js';
19
+ import {
20
+ FERAL_FUNCTION,
21
+ FERAL_EVAL,
22
+ TypeError,
23
+ arrayFilter,
24
+ globalThis,
25
+ is,
26
+ ownKeys,
27
+ stringSplit,
28
+ noEvalEvaluate,
29
+ getOwnPropertyNames,
30
+ getPrototypeOf,
31
+ } from './commons.js';
32
+ import { makeHardener } from './make-hardener.js';
33
+ import { makeIntrinsicsCollector } from './intrinsics.js';
34
+ import removeUnpermittedIntrinsics from './permits-intrinsics.js';
35
+ import tameFunctionConstructors from './tame-function-constructors.js';
36
+ import tameDateConstructor from './tame-date-constructor.js';
37
+ import tameMathObject from './tame-math-object.js';
38
+ import tameRegExpConstructor from './tame-regexp-constructor.js';
39
+ import enablePropertyOverrides from './enable-property-overrides.js';
40
+ import tameLocaleMethods from './tame-locale-methods.js';
41
+ import {
42
+ setGlobalObjectConstantProperties,
43
+ setGlobalObjectMutableProperties,
44
+ setGlobalObjectEvaluators,
45
+ } from './global-object.js';
46
+ import { makeSafeEvaluator } from './make-safe-evaluator.js';
47
+ import { initialGlobalPropertyNames } from './permits.js';
48
+ import { tameFunctionToString } from './tame-function-tostring.js';
49
+ import { tameDomains } from './tame-domains.js';
50
+ import { tameModuleSource } from './tame-module-source.js';
51
+
52
+ import { tameConsole } from './error/tame-console.js';
53
+ import tameErrorConstructor from './error/tame-error-constructor.js';
54
+ import { assert, makeAssert } from './error/assert.js';
55
+ import { getAnonymousIntrinsics } from './get-anonymous-intrinsics.js';
56
+ import { makeCompartmentConstructor } from './compartment.js';
57
+ import { tameHarden } from './tame-harden.js';
58
+ import { tameSymbolConstructor } from './tame-symbol-constructor.js';
59
+ import { tameFauxDataProperties } from './tame-faux-data-properties.js';
60
+ import { tameRegeneratorRuntime } from './tame-regenerator-runtime.js';
61
+ import { shimArrayBufferTransfer } from './shim-arraybuffer-transfer.js';
62
+ import { reportInGroup, chooseReporter } from './reporting.js';
63
+
64
+ /** @import {LockdownOptions} from '../types.js' */
65
+
66
+ const { Fail, details: X, quote: q } = assert;
67
+
68
+ /** @type {Error=} */
69
+ let priorRepairIntrinsics;
70
+
71
+ /** @type {Error=} */
72
+ let priorHardenIntrinsics;
73
+
74
+ // Build a harden() with an empty fringe.
75
+ // Gate it on lockdown.
76
+ /**
77
+ * @template T
78
+ * @param {T} ref
79
+ * @returns {T}
80
+ */
81
+ const safeHarden = makeHardener();
82
+
83
+ /**
84
+ * @callback Transform
85
+ * @param {string} source
86
+ * @returns {string}
87
+ */
88
+
89
+ /**
90
+ * @callback CompartmentConstructor
91
+ * @param {object} endowments
92
+ * @param {object} moduleMap
93
+ * @param {object} [options]
94
+ * @param {Array<Transform>} [options.transforms]
95
+ * @param {Array<Transform>} [options.__shimTransforms__]
96
+ */
97
+
98
+ // TODO https://github.com/endojs/endo/issues/814
99
+ // Lockdown currently allows multiple calls provided that the specified options
100
+ // of every call agree. With experience, we have observed that lockdown should
101
+ // only ever need to be called once and that simplifying lockdown will improve
102
+ // the quality of audits.
103
+
104
+ const probeHostEvaluators = () => {
105
+ let functionAllowed;
106
+ try {
107
+ functionAllowed = FERAL_FUNCTION('return true')();
108
+ } catch (_error) {
109
+ // We reach here if the Function() constructor is outright forbidden by a
110
+ // strict Content Security Policy (containing either a `default-src` or a
111
+ // `script-src` directive), not been implemented in the host, or the host
112
+ // is configured to throw an exception instead of `new Function`.
113
+ functionAllowed = false;
114
+ }
115
+
116
+ let evalAllowed;
117
+ try {
118
+ evalAllowed = FERAL_EVAL('true');
119
+ } catch (_error) {
120
+ // We reach here if `eval` is outright forbidden by a strict Content Security Policy,
121
+ // not implemented in the host, or the host is configured to throw an exception.
122
+ // We allow this for SES usage that delegates the responsibility to isolate
123
+ // guest code to production code generation.
124
+ evalAllowed = false;
125
+ }
126
+
127
+ let directEvalAllowed;
128
+ if (functionAllowed && evalAllowed) {
129
+ directEvalAllowed = FERAL_FUNCTION(
130
+ 'eval',
131
+ 'SES_changed',
132
+ `\
133
+ eval("SES_changed = true");
134
+ return SES_changed;
135
+ `,
136
+ )(FERAL_EVAL, false);
137
+ // If we get here and SES_changed stayed false, that means the eval was sloppy
138
+ // and indirect, which generally creates a new global.
139
+ // We are going to throw an exception for failing to initialize SES, but
140
+ // good neighbors clean up.
141
+ if (!directEvalAllowed) {
142
+ delete globalThis.SES_changed;
143
+ }
144
+ }
145
+
146
+ return { functionAllowed, evalAllowed, directEvalAllowed };
147
+ };
148
+
149
+ /**
150
+ * @param {LockdownOptions} [options]
151
+ */
152
+ export const repairIntrinsics = (options = {}) => {
153
+ // First time, absent options default to 'safe'.
154
+ // Subsequent times, absent options default to first options.
155
+ // Thus, all present options must agree with first options.
156
+ // Reconstructing `option` here also ensures that it is a well
157
+ // behaved record, with only own data properties.
158
+ //
159
+ // The `overrideTaming` is not a safety issue. Rather it is a tradeoff
160
+ // between code compatibility, which is better with the `'moderate'`
161
+ // setting, and tool compatibility, which is better with the `'min'`
162
+ // setting. See
163
+ // https://github.com/Agoric/SES-shim/blob/master/packages/ses/README.md#enabling-override-by-assignment)
164
+ // for an explanation of when to use which.
165
+ //
166
+ // The `stackFiltering` is not a safety issue. Rather it is a tradeoff
167
+ // between relevance and completeness of the stack frames shown on the
168
+ // console. Setting`stackFiltering` to `'verbose'` applies no filters, providing
169
+ // the raw stack frames that can be quite verbose. Setting
170
+ // `stackFrameFiltering` to`'concise'` limits the display to the stack frame
171
+ // information most likely to be relevant, eliminating distracting frames
172
+ // such as those from the infrastructure. However, the bug you're trying to
173
+ // track down might be in the infrastructure, in which case the `'verbose'` setting
174
+ // is useful. See
175
+ // [`stackFiltering` options](https://github.com/Agoric/SES-shim/blob/master/packages/ses/docs/lockdown.md#stackfiltering-options)
176
+ // for an explanation.
177
+
178
+ const {
179
+ errorTaming = /** @type {'safe' | 'unsafe' | 'unsafe-debug'} */ (
180
+ getenv('LOCKDOWN_ERROR_TAMING', 'safe', ['unsafe', 'unsafe-debug'])
181
+ ),
182
+ errorTrapping = /** @type {'platform' | 'none' | 'report' | 'abort' | 'exit'} */ (
183
+ getenv('LOCKDOWN_ERROR_TRAPPING', 'platform', [
184
+ 'none',
185
+ 'report',
186
+ 'abort',
187
+ 'exit',
188
+ ])
189
+ ),
190
+ reporting = /** @type {'platform' | 'console' | 'none'} */ (
191
+ getenv('LOCKDOWN_REPORTING', 'platform', ['console', 'none'])
192
+ ),
193
+ unhandledRejectionTrapping = /** @type {'none' | 'report'} */ (
194
+ getenv('LOCKDOWN_UNHANDLED_REJECTION_TRAPPING', 'report', ['none'])
195
+ ),
196
+ regExpTaming = /** @type {'safe' | 'unsafe'} */ (
197
+ getenv('LOCKDOWN_REGEXP_TAMING', 'safe', ['unsafe'])
198
+ ),
199
+ localeTaming = /** @type {'safe' | 'unsafe'} */ (
200
+ getenv('LOCKDOWN_LOCALE_TAMING', 'safe', ['unsafe'])
201
+ ),
202
+ consoleTaming = /** @type {'unsafe' | 'safe'} */ (
203
+ getenv('LOCKDOWN_CONSOLE_TAMING', 'safe', ['unsafe'])
204
+ ),
205
+ overrideTaming = /** @type {'moderate' | 'min' | 'severe'} */ (
206
+ getenv('LOCKDOWN_OVERRIDE_TAMING', 'moderate', ['min', 'severe'])
207
+ ),
208
+ stackFiltering = /** @type {'concise' | 'omit-frames' | 'shorten-paths' | 'verbose'} */ (
209
+ getenv('LOCKDOWN_STACK_FILTERING', 'concise', [
210
+ 'omit-frames',
211
+ 'shorten-paths',
212
+ 'verbose',
213
+ ])
214
+ ),
215
+ domainTaming = /** @type {'safe' | 'unsafe'} */ (
216
+ getenv('LOCKDOWN_DOMAIN_TAMING', 'safe', ['unsafe'])
217
+ ),
218
+ evalTaming = /** @type {'safe-eval' | 'unsafe-eval' | 'no-eval'} */ (
219
+ getenv('LOCKDOWN_EVAL_TAMING', 'safe-eval', [
220
+ 'unsafe-eval',
221
+ 'no-eval',
222
+ // deprecated
223
+ 'safeEval',
224
+ 'unsafeEval',
225
+ 'noEval',
226
+ ])
227
+ ),
228
+ overrideDebug = /** @type {string[]} */ (
229
+ arrayFilter(
230
+ stringSplit(getenv('LOCKDOWN_OVERRIDE_DEBUG', ''), ','),
231
+ /** @param {string} debugName */
232
+ debugName => debugName !== '',
233
+ )
234
+ ),
235
+ legacyRegeneratorRuntimeTaming = /** @type {'safe' | 'unsafe-ignore'} */ (
236
+ getenv('LOCKDOWN_LEGACY_REGENERATOR_RUNTIME_TAMING', 'safe', [
237
+ 'unsafe-ignore',
238
+ ])
239
+ ),
240
+ __hardenTaming__ = /** @type {'safe' | 'unsafe'} */ (
241
+ getenv('LOCKDOWN_HARDEN_TAMING', 'safe', ['unsafe'])
242
+ ),
243
+ dateTaming, // deprecated
244
+ mathTaming, // deprecated
245
+ ...extraOptions
246
+ } = options;
247
+
248
+ // Assert that only supported options were passed.
249
+ // Use Reflect.ownKeys to reject symbol-named properties as well.
250
+ const extraOptionsNames = ownKeys(extraOptions);
251
+ extraOptionsNames.length === 0 ||
252
+ Fail`lockdown(): non supported option ${q(extraOptionsNames)}`;
253
+
254
+ const reporter = chooseReporter(reporting);
255
+ const { warn } = reporter;
256
+
257
+ if (dateTaming !== undefined) {
258
+ warn(
259
+ `SES The 'dateTaming' option is deprecated and does nothing. In the future specifying it will be an error.`,
260
+ );
261
+ }
262
+ if (mathTaming !== undefined) {
263
+ warn(
264
+ `SES The 'mathTaming' option is deprecated and does nothing. In the future specifying it will be an error.`,
265
+ );
266
+ }
267
+
268
+ priorRepairIntrinsics === undefined ||
269
+ // eslint-disable-next-line @endo/no-polymorphic-call
270
+ assert.fail(
271
+ X`Already locked down at ${priorRepairIntrinsics} (SES_ALREADY_LOCKED_DOWN)`,
272
+ TypeError,
273
+ );
274
+ // See https://github.com/endojs/endo/blob/master/packages/ses/error-codes/SES_ALREADY_LOCKED_DOWN.md
275
+ priorRepairIntrinsics = TypeError('Prior lockdown (SES_ALREADY_LOCKED_DOWN)');
276
+ // Tease V8 to generate the stack string and release the closures the stack
277
+ // trace retained:
278
+ priorRepairIntrinsics.stack;
279
+
280
+ const { functionAllowed, evalAllowed, directEvalAllowed } =
281
+ probeHostEvaluators();
282
+
283
+ if (
284
+ directEvalAllowed === false &&
285
+ evalTaming === 'safe-eval' &&
286
+ (functionAllowed || evalAllowed)
287
+ ) {
288
+ // See https://github.com/endojs/endo/blob/master/packages/ses/error-codes/SES_DIRECT_EVAL.md
289
+ throw TypeError(
290
+ "SES cannot initialize unless 'eval' is the original intrinsic 'eval', suitable for direct eval (dynamically scoped eval) (SES_DIRECT_EVAL)",
291
+ );
292
+ }
293
+
294
+ /**
295
+ * Because of packagers and bundlers, etc, multiple invocations of lockdown
296
+ * might happen in separate instantiations of the source of this module.
297
+ * In that case, each one sees its own `firstOptions` variable, so the test
298
+ * above will not detect that lockdown has already happened. We
299
+ * unreliably test some telltale signs that lockdown has run, to avoid
300
+ * trying to lock down a locked down environment. Although the test is
301
+ * unreliable, this is consistent with the SES threat model. SES provides
302
+ * security only if it runs first in a given realm, or if everything that
303
+ * runs before it is SES-aware and cooperative. Neither SES nor anything
304
+ * can protect itself from corrupting code that runs first. For these
305
+ * purposes, code that turns a realm into something that passes these
306
+ * tests without actually locking down counts as corrupting code.
307
+ *
308
+ * The specifics of what this tests for may change over time, but it
309
+ * should be consistent with any setting of the lockdown options.
310
+ */
311
+ const seemsToBeLockedDown = () => {
312
+ return (
313
+ globalThis.Function.prototype.constructor !== globalThis.Function &&
314
+ // @ts-ignore harden is absent on globalThis type def.
315
+ typeof globalThis.harden === 'function' &&
316
+ // @ts-ignore lockdown is absent on globalThis type def.
317
+ typeof globalThis.lockdown === 'function' &&
318
+ globalThis.Date.prototype.constructor !== globalThis.Date &&
319
+ typeof globalThis.Date.now === 'function' &&
320
+ // @ts-ignore does not recognize that Date constructor is a special
321
+ // Function.
322
+ // eslint-disable-next-line @endo/no-polymorphic-call
323
+ is(globalThis.Date.prototype.constructor.now(), NaN)
324
+ );
325
+ };
326
+
327
+ if (seemsToBeLockedDown()) {
328
+ // See https://github.com/endojs/endo/blob/master/packages/ses/error-codes/SES_MULTIPLE_INSTANCES.md
329
+ throw TypeError(
330
+ `Already locked down but not by this SES instance (SES_MULTIPLE_INSTANCES)`,
331
+ );
332
+ }
333
+
334
+ /**
335
+ * 1. TAME powers & gather intrinsics first.
336
+ */
337
+
338
+ tameDomains(domainTaming);
339
+
340
+ // Replace Function.prototype.toString with one that recognizes
341
+ // shimmed functions as honorary native functions.
342
+ const markVirtualizedNativeFunction = tameFunctionToString();
343
+
344
+ const { addIntrinsics, completePrototypes, finalIntrinsics } =
345
+ makeIntrinsicsCollector(reporter);
346
+
347
+ const tamedHarden = tameHarden(safeHarden, __hardenTaming__);
348
+ addIntrinsics({ harden: tamedHarden });
349
+
350
+ addIntrinsics(tameFunctionConstructors());
351
+
352
+ addIntrinsics(tameDateConstructor());
353
+ addIntrinsics(tameErrorConstructor(errorTaming, stackFiltering));
354
+ addIntrinsics(tameMathObject());
355
+ addIntrinsics(tameRegExpConstructor(regExpTaming));
356
+ addIntrinsics(tameSymbolConstructor());
357
+ addIntrinsics(shimArrayBufferTransfer());
358
+ addIntrinsics(tameModuleSource());
359
+
360
+ addIntrinsics(getAnonymousIntrinsics());
361
+
362
+ completePrototypes();
363
+
364
+ const intrinsics = finalIntrinsics();
365
+
366
+ const hostIntrinsics = { __proto__: null };
367
+
368
+ // The Node.js Buffer is a derived class of Uint8Array, and as such is often
369
+ // passed around where a Uint8Array is expected.
370
+ if (typeof globalThis.Buffer === 'function') {
371
+ hostIntrinsics.Buffer = globalThis.Buffer;
372
+ }
373
+
374
+ /**
375
+ * Wrap console unless suppressed.
376
+ * At the moment, the console is considered a host power in the start
377
+ * compartment, and not a primordial. Hence it is absent from the whilelist
378
+ * and bypasses the intrinsicsCollector.
379
+ *
380
+ * @type {((error: any) => string | undefined) | undefined}
381
+ */
382
+ let optGetStackString;
383
+ if (errorTaming === 'safe') {
384
+ optGetStackString = intrinsics['%InitialGetStackString%'];
385
+ }
386
+ const consoleRecord = tameConsole(
387
+ consoleTaming,
388
+ errorTrapping,
389
+ unhandledRejectionTrapping,
390
+ optGetStackString,
391
+ );
392
+ globalThis.console = /** @type {Console} */ (consoleRecord.console);
393
+
394
+ // The untamed Node.js console cannot itself be hardened as it has mutable
395
+ // internal properties, but some of these properties expose internal versions
396
+ // of classes from node's "primordials" concept.
397
+ // eslint-disable-next-line no-underscore-dangle
398
+ if (typeof (/** @type {any} */ (consoleRecord.console)._times) === 'object') {
399
+ // SafeMap is a derived Map class used internally by Node
400
+ // There doesn't seem to be a cleaner way to reach it.
401
+ hostIntrinsics.SafeMap = getPrototypeOf(
402
+ // eslint-disable-next-line no-underscore-dangle
403
+ /** @type {any} */ (consoleRecord.console)._times,
404
+ );
405
+ }
406
+
407
+ // @ts-ignore assert is absent on globalThis type def.
408
+ if (
409
+ (errorTaming === 'unsafe' || errorTaming === 'unsafe-debug') &&
410
+ globalThis.assert === assert
411
+ ) {
412
+ // If errorTaming is 'unsafe' or 'unsafe-debug' we replace the
413
+ // global assert with
414
+ // one whose `details` template literal tag does not redact
415
+ // unmarked substitution values. IOW, it blabs information that
416
+ // was supposed to be secret from callers, as an aid to debugging
417
+ // at a further cost in safety.
418
+ // @ts-ignore assert is absent on globalThis type def.
419
+ globalThis.assert = makeAssert(undefined, true);
420
+ }
421
+
422
+ // Replace *Locale* methods with their non-locale equivalents
423
+ tameLocaleMethods(intrinsics, localeTaming);
424
+
425
+ tameFauxDataProperties(intrinsics);
426
+
427
+ /**
428
+ * 2. Enforce PERMITS on shared intrinsics
429
+ */
430
+
431
+ // Remove non-standard properties.
432
+ // All remaining functions encountered during whitelisting are
433
+ // branded as honorary native functions.
434
+ reportInGroup(
435
+ 'SES Removing unpermitted intrinsics',
436
+ reporter,
437
+ groupReporter =>
438
+ removeUnpermittedIntrinsics(
439
+ intrinsics,
440
+ markVirtualizedNativeFunction,
441
+ groupReporter,
442
+ ),
443
+ );
444
+
445
+ // Initialize the powerful initial global, i.e., the global of the
446
+ // start compartment, from the intrinsics.
447
+
448
+ setGlobalObjectConstantProperties(globalThis);
449
+
450
+ setGlobalObjectMutableProperties(globalThis, {
451
+ intrinsics,
452
+ newGlobalPropertyNames: initialGlobalPropertyNames,
453
+ makeCompartmentConstructor,
454
+ markVirtualizedNativeFunction,
455
+ });
456
+
457
+ if (
458
+ evalTaming === 'no-eval' ||
459
+ // deprecated
460
+ evalTaming === 'noEval'
461
+ ) {
462
+ setGlobalObjectEvaluators(
463
+ globalThis,
464
+ noEvalEvaluate,
465
+ markVirtualizedNativeFunction,
466
+ );
467
+ } else if (
468
+ evalTaming === 'safe-eval' ||
469
+ // deprecated
470
+ evalTaming === 'safeEval'
471
+ ) {
472
+ const { safeEvaluate } = makeSafeEvaluator({ globalObject: globalThis });
473
+ setGlobalObjectEvaluators(
474
+ globalThis,
475
+ safeEvaluate,
476
+ markVirtualizedNativeFunction,
477
+ );
478
+ } else if (
479
+ evalTaming === 'unsafe-eval' ||
480
+ // deprecated
481
+ evalTaming === 'unsafeEval'
482
+ ) {
483
+ // Leave eval function and Function constructor of the initial
484
+ // compartment intact.
485
+ // Other compartments will not have access to these evaluators unless a
486
+ // guest program escapes containment.
487
+ }
488
+
489
+ /**
490
+ * 3. HARDEN to share the intrinsics.
491
+ *
492
+ * We define hardenIntrinsics here so that options are in scope, but return
493
+ * it to the caller because we intend to eventually allow vetted shims to run
494
+ * between repairs and the hardening of intrinsics and so we can benchmark
495
+ * repair separately from hardening.
496
+ */
497
+
498
+ const hardenIntrinsics = () => {
499
+ priorHardenIntrinsics === undefined ||
500
+ // eslint-disable-next-line @endo/no-polymorphic-call
501
+ assert.fail(
502
+ X`Already locked down at ${priorHardenIntrinsics} (SES_ALREADY_LOCKED_DOWN)`,
503
+ TypeError,
504
+ );
505
+ // See https://github.com/endojs/endo/blob/master/packages/ses/error-codes/SES_ALREADY_LOCKED_DOWN.md
506
+ priorHardenIntrinsics = TypeError(
507
+ 'Prior lockdown (SES_ALREADY_LOCKED_DOWN)',
508
+ );
509
+ // Tease V8 to generate the stack string and release the closures the stack
510
+ // trace retained:
511
+ priorHardenIntrinsics.stack;
512
+
513
+ // Circumvent the override mistake.
514
+ // TODO consider moving this to the end of the repair phase, and
515
+ // therefore before vetted shims rather than afterwards. It is not
516
+ // clear yet which is better.
517
+ // @ts-ignore enablePropertyOverrides does its own input validation
518
+ reportInGroup('SES Enabling property overrides', reporter, groupReporter =>
519
+ enablePropertyOverrides(
520
+ intrinsics,
521
+ overrideTaming,
522
+ groupReporter,
523
+ overrideDebug,
524
+ ),
525
+ );
526
+ if (legacyRegeneratorRuntimeTaming === 'unsafe-ignore') {
527
+ tameRegeneratorRuntime();
528
+ }
529
+
530
+ // Finally register and optionally freeze all the intrinsics. This
531
+ // must be the operation that modifies the intrinsics.
532
+ const toHarden = {
533
+ intrinsics,
534
+ hostIntrinsics,
535
+ globals: {
536
+ // Harden evaluators
537
+ Function: globalThis.Function,
538
+ eval: globalThis.eval,
539
+ // @ts-ignore Compartment does exist on globalThis
540
+ Compartment: globalThis.Compartment,
541
+
542
+ // Harden Symbol
543
+ Symbol: globalThis.Symbol,
544
+ },
545
+ };
546
+
547
+ // Harden Symbol and properties for initialGlobalPropertyNames in the host realm
548
+ for (const prop of getOwnPropertyNames(initialGlobalPropertyNames)) {
549
+ toHarden.globals[prop] = globalThis[prop];
550
+ }
551
+
552
+ tamedHarden(toHarden);
553
+
554
+ return tamedHarden;
555
+ };
556
+
557
+ return hardenIntrinsics;
558
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * makeEvalFunction()
3
+ * A safe version of the native eval function which relies on
4
+ * the safety of `safe-eval` for confinement, unless `no-eval`
5
+ * is specified (then a TypeError is thrown on use).
6
+ *
7
+ * @param {Function} evaluator
8
+ */
9
+ export const makeEvalFunction = evaluator => {
10
+ // We use the concise method syntax to create an eval without a
11
+ // [[Construct]] behavior (such that the invocation "new eval()" throws
12
+ // TypeError: eval is not a constructor"), but which still accepts a
13
+ // 'this' binding.
14
+ const newEval = {
15
+ eval(source) {
16
+ if (typeof source !== 'string') {
17
+ // As per the runtime semantic of PerformEval [ECMAScript 18.2.1.1]:
18
+ // If Type(source) is not String, return source.
19
+ // TODO Recent proposals from Mike Samuel may change this non-string
20
+ // rule. Track.
21
+ return source;
22
+ }
23
+ return evaluator(source);
24
+ },
25
+ }.eval;
26
+
27
+ return newEval;
28
+ };
@@ -0,0 +1,110 @@
1
+ // @ts-check
2
+
3
+ import { FERAL_FUNCTION, arrayJoin, apply } from './commons.js';
4
+ import { getScopeConstants } from './scope-constants.js';
5
+
6
+ /**
7
+ * buildOptimizer()
8
+ * Given an array of identifiers, the optimizer returns a `const` declaration
9
+ * destructuring `this.${name}`.
10
+ *
11
+ * @param {Array<string>} constants
12
+ * @param {string} name
13
+ */
14
+ function buildOptimizer(constants, name) {
15
+ // No need to build an optimizer when there are no constants.
16
+ if (constants.length === 0) return '';
17
+ // Use 'this' to avoid going through the scope proxy, which is unnecessary
18
+ // since the optimizer only needs references to the safe global.
19
+ // Destructure the constants from the target scope object.
20
+ return `const {${arrayJoin(constants, ',')}} = this.${name};`;
21
+ }
22
+
23
+ /**
24
+ * makeEvaluate()
25
+ * Create an 'evaluate' function with the correct optimizer inserted.
26
+ *
27
+ * @param {object} context
28
+ * @param {object} context.evalScope
29
+ * @param {object} context.moduleLexicals
30
+ * @param {object} context.globalObject
31
+ * @param {object} context.scopeTerminator
32
+ */
33
+ export const makeEvaluate = context => {
34
+ const { globalObjectConstants, moduleLexicalConstants } = getScopeConstants(
35
+ context.globalObject,
36
+ context.moduleLexicals,
37
+ );
38
+ const globalObjectOptimizer = buildOptimizer(
39
+ globalObjectConstants,
40
+ 'globalObject',
41
+ );
42
+ const moduleLexicalOptimizer = buildOptimizer(
43
+ moduleLexicalConstants,
44
+ 'moduleLexicals',
45
+ );
46
+
47
+ // Create a function in sloppy mode, so that we can use 'with'. It returns
48
+ // a function in strict mode that evaluates the provided code using direct
49
+ // eval, and thus in strict mode in the same scope. We must be very careful
50
+ // to not create new names in this scope
51
+
52
+ // 1: we use multiple nested 'with' to catch all free variable names. The
53
+ // `this` value of the outer sloppy function holds the different scope
54
+ // layers, from inner to outer:
55
+ // a) `evalScope` which must release the `FERAL_EVAL` as 'eval' once for
56
+ // every invocation of the inner `evaluate` function in order to
57
+ // trigger direct eval. The direct eval semantics is what allows the
58
+ // evaluated code to lookup free variable names on the other scope
59
+ // objects and not in global scope.
60
+ // b) `moduleLexicals` which provide a way to introduce free variables
61
+ // that are not available on the globalObject.
62
+ // c) `globalObject` is the global scope object of the evaluator, aka the
63
+ // Compartment's `globalThis`.
64
+ // d) `scopeTerminator` is a proxy object which prevents free variable
65
+ // lookups to escape to the start compartment's global object.
66
+ // 2: `optimizer`s catch constant variable names for speed.
67
+ // 3: The inner strict `evaluate` function should be passed two parameters:
68
+ // a) its arguments[0] is the source to be directly evaluated.
69
+ // b) its 'this' is the this binding seen by the code being
70
+ // directly evaluated (the globalObject).
71
+
72
+ // Notes:
73
+ // - The `optimizer` strings only lookup values on the `globalObject` and
74
+ // `moduleLexicals` objects by construct. Keywords like 'function' are
75
+ // reserved and cannot be used as a variable, so they are excluded from the
76
+ // optimizer. Furthermore to prevent shadowing 'eval', while a valid
77
+ // identifier, that name is also explicitly excluded.
78
+ // - when 'eval' is looked up in the `evalScope`, the powerful unsafe eval
79
+ // intrinsic is returned after automatically removing it from the
80
+ // `evalScope`. Any further reference to 'eval' in the evaluate string will
81
+ // get the tamed evaluator from the `globalObject`, if any.
82
+
83
+ // TODO https://github.com/endojs/endo/issues/816
84
+ // The optimizer currently runs under sloppy mode, and although we doubt that
85
+ // there is any vulnerability introduced just by running the optimizer
86
+ // sloppy, we are much more confident in the semantics of strict mode.
87
+ // The `evaluate` function can be and is reused across multiple evaluations.
88
+ // Since the optimizer should not be re-evaluated every time, it cannot be
89
+ // inside the `evaluate` closure. While we could potentially nest an
90
+ // intermediate layer of `() => {'use strict'; ${optimizers}; ...`, it
91
+ // doesn't seem worth the overhead and complexity.
92
+ const evaluateFactory = FERAL_FUNCTION(`
93
+ with (this.scopeTerminator) {
94
+ with (this.globalObject) {
95
+ with (this.moduleLexicals) {
96
+ with (this.evalScope) {
97
+ ${globalObjectOptimizer}
98
+ ${moduleLexicalOptimizer}
99
+ return function() {
100
+ 'use strict';
101
+ return eval(arguments[0]);
102
+ };
103
+ }
104
+ }
105
+ }
106
+ }
107
+ `);
108
+
109
+ return apply(evaluateFactory, context, []);
110
+ };