@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.
- package/LICENSE +661 -0
- package/README.md +29 -0
- package/build.config.ts +22 -0
- package/client.d.ts +2 -0
- package/client.js +1 -0
- package/dist/client/index.d.ts +15 -0
- package/dist/client/index.js +10 -0
- package/dist/externalVersion.js +21 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +48 -0
- package/dist/locale/en-US.json +61 -0
- package/dist/locale/index.d.ts +141 -0
- package/dist/locale/index.js +79 -0
- package/dist/locale/zh-CN.json +61 -0
- package/dist/node_modules/ses/LICENSE +201 -0
- package/dist/node_modules/ses/LICENSE-aura +16 -0
- package/dist/node_modules/ses/LICENSE-caja +13 -0
- package/dist/node_modules/ses/LICENSE-corejs +19 -0
- package/dist/node_modules/ses/LICENSE-v8 +9 -0
- package/dist/node_modules/ses/assert-shim.js +1 -0
- package/dist/node_modules/ses/compartment-shim.js +1 -0
- package/dist/node_modules/ses/console-shim.js +1 -0
- package/dist/node_modules/ses/dist/lockdown.cjs +13912 -0
- package/dist/node_modules/ses/dist/lockdown.umd.js +13912 -0
- package/dist/node_modules/ses/dist/lockdown.umd.min.js +1 -0
- package/dist/node_modules/ses/dist/ses-hermes.cjs +13912 -0
- package/dist/node_modules/ses/dist/ses.cjs +1 -0
- package/dist/node_modules/ses/dist/ses.umd.js +13912 -0
- package/dist/node_modules/ses/dist/ses.umd.min.js +1 -0
- package/dist/node_modules/ses/dist/types.d.cts +606 -0
- package/dist/node_modules/ses/index.js +18 -0
- package/dist/node_modules/ses/lockdown-shim.js +1 -0
- package/dist/node_modules/ses/lockdown.js +1 -0
- package/dist/node_modules/ses/package.json +1 -0
- package/dist/node_modules/ses/src/assert-shim.js +4 -0
- package/dist/node_modules/ses/src/assert-sloppy-mode.js +11 -0
- package/dist/node_modules/ses/src/cauterize-property.js +69 -0
- package/dist/node_modules/ses/src/commons.js +425 -0
- package/dist/node_modules/ses/src/compartment-evaluate.js +93 -0
- package/dist/node_modules/ses/src/compartment-shim.js +22 -0
- package/dist/node_modules/ses/src/compartment.js +477 -0
- package/dist/node_modules/ses/src/console-shim.js +50 -0
- package/dist/node_modules/ses/src/enable-property-overrides.js +211 -0
- package/dist/node_modules/ses/src/enablements.js +244 -0
- package/dist/node_modules/ses/src/error/assert.js +584 -0
- package/dist/node_modules/ses/src/error/console.js +541 -0
- package/dist/node_modules/ses/src/error/fatal-assert.js +54 -0
- package/dist/node_modules/ses/src/error/internal-types.js +98 -0
- package/dist/node_modules/ses/src/error/note-log-args.js +77 -0
- package/dist/node_modules/ses/src/error/stringify-utils.js +195 -0
- package/dist/node_modules/ses/src/error/tame-console.js +197 -0
- package/dist/node_modules/ses/src/error/tame-error-constructor.js +284 -0
- package/dist/node_modules/ses/src/error/tame-v8-error-constructor.js +386 -0
- package/dist/node_modules/ses/src/error/types.js +59 -0
- package/dist/node_modules/ses/src/error/unhandled-rejection.js +122 -0
- package/dist/node_modules/ses/src/eval-scope.js +89 -0
- package/dist/node_modules/ses/src/get-anonymous-intrinsics.js +181 -0
- package/dist/node_modules/ses/src/get-source-url.js +50 -0
- package/dist/node_modules/ses/src/global-object.js +175 -0
- package/dist/node_modules/ses/src/intrinsics.js +192 -0
- package/dist/node_modules/ses/src/lockdown-shim.js +37 -0
- package/dist/node_modules/ses/src/lockdown.js +558 -0
- package/dist/node_modules/ses/src/make-eval-function.js +28 -0
- package/dist/node_modules/ses/src/make-evaluate.js +110 -0
- package/dist/node_modules/ses/src/make-function-constructor.js +79 -0
- package/dist/node_modules/ses/src/make-hardener.js +275 -0
- package/dist/node_modules/ses/src/make-safe-evaluator.js +112 -0
- package/dist/node_modules/ses/src/module-instance.js +497 -0
- package/dist/node_modules/ses/src/module-link.js +159 -0
- package/dist/node_modules/ses/src/module-load.js +719 -0
- package/dist/node_modules/ses/src/module-proxy.js +200 -0
- package/dist/node_modules/ses/src/permits-intrinsics.js +291 -0
- package/dist/node_modules/ses/src/permits.js +1761 -0
- package/dist/node_modules/ses/src/reporting-types.d.ts +13 -0
- package/dist/node_modules/ses/src/reporting.js +105 -0
- package/dist/node_modules/ses/src/scope-constants.js +180 -0
- package/dist/node_modules/ses/src/shim-arraybuffer-transfer.js +85 -0
- package/dist/node_modules/ses/src/sloppy-globals-scope-terminator.js +61 -0
- package/dist/node_modules/ses/src/strict-scope-terminator.js +99 -0
- package/dist/node_modules/ses/src/tame-date-constructor.js +127 -0
- package/dist/node_modules/ses/src/tame-domains.js +41 -0
- package/dist/node_modules/ses/src/tame-faux-data-properties.js +210 -0
- package/dist/node_modules/ses/src/tame-function-constructors.js +140 -0
- package/dist/node_modules/ses/src/tame-function-tostring.js +50 -0
- package/dist/node_modules/ses/src/tame-harden.js +29 -0
- package/dist/node_modules/ses/src/tame-locale-methods.js +78 -0
- package/dist/node_modules/ses/src/tame-math-object.js +41 -0
- package/dist/node_modules/ses/src/tame-module-source.js +51 -0
- package/dist/node_modules/ses/src/tame-regenerator-runtime.js +29 -0
- package/dist/node_modules/ses/src/tame-regexp-constructor.js +65 -0
- package/dist/node_modules/ses/src/tame-symbol-constructor.js +64 -0
- package/dist/node_modules/ses/src/transforms.js +267 -0
- package/dist/node_modules/ses/tools.js +25 -0
- package/dist/node_modules/ses/types.d.ts +606 -0
- package/dist/server/actions/ui-schema-action.d.ts +27 -0
- package/dist/server/actions/ui-schema-action.js +118 -0
- package/dist/server/collections/flowModelTreePath.d.ts +11 -0
- package/dist/server/collections/flowModelTreePath.js +74 -0
- package/dist/server/collections/flowModels.d.ts +11 -0
- package/dist/server/collections/flowModels.js +57 -0
- package/dist/server/collections/flowsql.d.ts +10 -0
- package/dist/server/collections/flowsql.js +51 -0
- package/dist/server/dao/ui_schema_node_dao.d.ts +26 -0
- package/dist/server/dao/ui_schema_node_dao.js +24 -0
- package/dist/server/helper.d.ts +8 -0
- package/dist/server/helper.js +9 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +42 -0
- package/dist/server/model.d.ts +12 -0
- package/dist/server/model.js +38 -0
- package/dist/server/plugin.d.ts +26 -0
- package/dist/server/plugin.js +270 -0
- package/dist/server/repository.d.ts +116 -0
- package/dist/server/repository.js +1209 -0
- package/dist/server/server.d.ts +16 -0
- package/dist/server/server.js +198 -0
- package/dist/server/template/contexts.d.ts +73 -0
- package/dist/server/template/contexts.js +233 -0
- package/dist/server/template/resolver.d.ts +30 -0
- package/dist/server/template/resolver.js +225 -0
- package/dist/server/variables/registry.d.ts +42 -0
- package/dist/server/variables/registry.js +299 -0
- package/package.json +28 -0
- package/server.d.ts +2 -0
- 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
|
+
};
|