0
# Development Tools
1
2
Source transformation and scope manipulation utilities for advanced SES use cases. These tools provide low-level access to SES's code transformation pipeline and scope management system.
3
4
## Package Import
5
6
```javascript
7
import { transforms, scopeTerminators } from 'ses/tools.js';
8
```
9
10
## Capabilities
11
12
### Source Transformations
13
14
Collection of source-to-source JavaScript transformation functions used internally by SES for secure code execution.
15
16
```javascript { .api }
17
/**
18
* Source transformation function signature
19
* @param source - JavaScript source code to transform
20
* @returns Transformed JavaScript source code
21
*/
22
type Transform = (source: string) => string;
23
24
/**
25
* Object containing all available transformation functions
26
*/
27
interface TransformLibrary {
28
rejectHtmlComments: Transform;
29
evadeHtmlCommentTest: Transform;
30
rejectImportExpressions: Transform;
31
evadeImportExpressionTest: Transform;
32
rejectSomeDirectEvalExpressions: Transform;
33
mandatoryTransforms: Transform;
34
applyTransforms: (source: string, transforms: Transform[]) => string;
35
}
36
37
const transforms: TransformLibrary;
38
```
39
40
**Usage Examples:**
41
42
```javascript
43
import { transforms } from 'ses/tools.js';
44
45
// Reject potentially dangerous HTML comments
46
const safeSource = transforms.rejectHtmlComments(`
47
// This would throw: <!-- comment -->
48
const x = 1;
49
`);
50
51
// Reject dynamic import expressions for security
52
const secureSource = transforms.rejectImportExpressions(`
53
// This would throw: import('dangerous-module')
54
const y = 2;
55
`);
56
57
// Apply all mandatory security transforms
58
const mandatorySecure = transforms.mandatoryTransforms(originalSource);
59
60
// Apply custom transform pipeline
61
const customTransforms = [
62
transforms.rejectHtmlComments,
63
transforms.rejectImportExpressions
64
];
65
const processedSource = transforms.applyTransforms(originalSource, customTransforms);
66
```
67
68
### Individual Transform Functions
69
70
#### HTML Comment Rejection
71
72
Rejects source code containing HTML-like comment syntax to prevent parser confusion.
73
74
```javascript { .api }
75
/**
76
* Reject source code containing HTML-like comments (<!-- or -->)
77
* @param source - JavaScript source code to check
78
* @returns Original source if safe
79
* @throws SyntaxError if HTML comments found
80
*/
81
function rejectHtmlComments(source: string): string;
82
83
/**
84
* Transform HTML-like comments to space-separated operators
85
* @param source - JavaScript source code to transform
86
* @returns Source with HTML comments converted to operators
87
*/
88
function evadeHtmlCommentTest(source: string): string;
89
```
90
91
**Usage Examples:**
92
93
```javascript
94
import { transforms } from 'ses/tools.js';
95
96
try {
97
// This will throw SyntaxError
98
transforms.rejectHtmlComments('const x = 1; <!-- comment -->');
99
} catch (error) {
100
console.log(error.message); // "Possible HTML comment rejected..."
101
}
102
103
// Evade rejection by converting to operators
104
const converted = transforms.evadeHtmlCommentTest('const x = 1; <!-- comment -->');
105
console.log(converted); // "const x = 1; < ! -- comment -- >"
106
```
107
108
#### Import Expression Rejection
109
110
Prevents dynamic import expressions that could bypass module system security.
111
112
```javascript { .api }
113
/**
114
* Reject source code containing dynamic import expressions
115
* @param source - JavaScript source code to check
116
* @returns Original source if safe
117
* @throws SyntaxError if import expressions found
118
*/
119
function rejectImportExpressions(source: string): string;
120
121
/**
122
* Transform import expressions to __import__ to evade rejection
123
* @param source - JavaScript source code to transform
124
* @returns Source with import expressions converted
125
*/
126
function evadeImportExpressionTest(source: string): string;
127
```
128
129
**Usage Examples:**
130
131
```javascript
132
import { transforms } from 'ses/tools.js';
133
134
try {
135
// This will throw SyntaxError
136
transforms.rejectImportExpressions("import('module').then(m => m.run())");
137
} catch (error) {
138
console.log(error.message); // "Possible import expression rejected..."
139
}
140
141
// Evade rejection by renaming import
142
const converted = transforms.evadeImportExpressionTest("import('module')");
143
console.log(converted); // "__import__('module')"
144
```
145
146
#### Direct Eval Rejection
147
148
Heuristically rejects some direct eval expressions that cannot be properly shimmed.
149
150
```javascript { .api }
151
/**
152
* Reject source code that appears to contain direct eval expressions
153
* @param source - JavaScript source code to check
154
* @returns Original source if safe
155
* @throws SyntaxError if direct eval expressions found
156
* @note May have false positives and negatives - designed for innocent code
157
*/
158
function rejectSomeDirectEvalExpressions(source: string): string;
159
```
160
161
**Usage Examples:**
162
163
```javascript
164
import { transforms } from 'ses/tools.js';
165
166
try {
167
// This will throw SyntaxError
168
transforms.rejectSomeDirectEvalExpressions('eval("console.log(\'hello\')")');
169
} catch (error) {
170
console.log(error.message); // "Possible direct eval expression rejected..."
171
}
172
173
// This might not be caught (false negative)
174
const trickyEval = '(eval)("code")'; // Might pass through
175
```
176
177
#### Mandatory Transforms
178
179
Bundles together transforms that must always be applied for security.
180
181
```javascript { .api }
182
/**
183
* Apply all mandatory security transforms in the correct order
184
* @param source - JavaScript source code to secure
185
* @returns Source with all mandatory transforms applied
186
* @throws SyntaxError if dangerous patterns found
187
*/
188
function mandatoryTransforms(source: string): string;
189
```
190
191
**Usage Examples:**
192
193
```javascript
194
import { transforms } from 'ses/tools.js';
195
196
// Apply all security-critical transforms at once
197
const secureSource = transforms.mandatoryTransforms(`
198
function userCode() {
199
// User-provided code that needs security transforms
200
return Math.random();
201
}
202
`);
203
204
// Use in compartment
205
const compartment = new Compartment({
206
transforms: [transforms.mandatoryTransforms],
207
__options__: true
208
});
209
```
210
211
#### Transform Pipeline Application
212
213
Utility for applying multiple transforms in sequence.
214
215
```javascript { .api }
216
/**
217
* Apply a sequence of transforms to source code
218
* @param source - Initial JavaScript source code
219
* @param transforms - Array of transform functions to apply in order
220
* @returns Source with all transforms applied sequentially
221
*/
222
function applyTransforms(source: string, transforms: Transform[]): string;
223
```
224
225
**Usage Examples:**
226
227
```javascript
228
import { transforms } from 'ses/tools.js';
229
230
// Custom transform pipeline
231
const myTransforms = [
232
transforms.rejectHtmlComments,
233
transforms.rejectImportExpressions,
234
(source) => source.replace(/console\.log/g, '/* console.log */')
235
];
236
237
const processedSource = transforms.applyTransforms(originalSource, myTransforms);
238
239
// Use in compartment
240
const compartment = new Compartment({
241
transforms: myTransforms,
242
__options__: true
243
});
244
```
245
246
### Scope Terminators
247
248
Utilities for managing scope boundaries and global object behavior in different execution modes.
249
250
```javascript { .api }
251
/**
252
* Scope termination utilities for controlling variable scoping behavior
253
*/
254
interface ScopeTerminatorLibrary {
255
/** Scope terminator for strict mode execution */
256
strictScopeTerminator: any;
257
258
/** Factory function for creating sloppy mode scope terminators */
259
createSloppyGlobalsScopeTerminator: () => any;
260
}
261
262
const scopeTerminators: ScopeTerminatorLibrary;
263
```
264
265
**Usage Examples:**
266
267
```javascript
268
import { scopeTerminators } from 'ses/tools.js';
269
270
const { strictScopeTerminator, createSloppyGlobalsScopeTerminator } = scopeTerminators;
271
272
// Access strict mode scope terminator
273
const strictTerminator = strictScopeTerminator;
274
275
// Create sloppy mode scope terminator
276
const sloppyTerminator = createSloppyGlobalsScopeTerminator();
277
278
// These are typically used internally by SES's evaluation system
279
// but can be accessed for advanced use cases involving custom
280
// evaluation contexts and scope management
281
```
282
283
## Integration with Compartments
284
285
Using transforms in compartment creation for custom code processing:
286
287
```javascript
288
import 'ses';
289
import { transforms } from 'ses/tools.js';
290
291
lockdown();
292
293
// Create compartment with security transforms
294
const secureCompartment = new Compartment({
295
transforms: [transforms.mandatoryTransforms],
296
globals: { console: harden(console) },
297
__options__: true
298
});
299
300
// Create compartment with custom transform pipeline
301
const customCompartment = new Compartment({
302
transforms: [
303
transforms.rejectHtmlComments,
304
transforms.rejectImportExpressions,
305
// Add custom transforms
306
(source) => `"use strict";\n${source}`
307
],
308
__options__: true
309
});
310
311
// Evaluate code with applied transforms
312
const result = secureCompartment.evaluate(`
313
function calculate(x, y) {
314
return x + y;
315
}
316
calculate(5, 3);
317
`);
318
```
319
320
## Security Considerations
321
322
### Transform Order Matters
323
324
Transforms are applied in the order specified. Security-critical transforms should typically come first:
325
326
```javascript
327
// Correct order - security first
328
const transforms = [
329
transforms.mandatoryTransforms, // Security critical
330
myCustomTransform // Custom logic
331
];
332
333
// Incorrect order - custom transform might introduce vulnerabilities
334
const badTransforms = [
335
myCustomTransform, // Might add dangerous patterns
336
transforms.mandatoryTransforms // Too late to catch them
337
];
338
```
339
340
### Evasion Transforms
341
342
The "evade" transforms are designed to work around the rejection transforms, but they may change code semantics:
343
344
```javascript
345
// Original code
346
const code = 'const result = import("module");';
347
348
// Evade transform changes semantics
349
const evaded = transforms.evadeImportExpressionTest(code);
350
// Result: 'const result = __import__("module");'
351
// Note: __import__ is not the same as import()
352
```
353
354
### Transform Performance
355
356
Transforms are applied synchronously and may impact performance for large codebases:
357
358
```javascript
359
// For performance-critical applications, consider caching
360
const transformCache = new Map();
361
362
const cachedTransform = (source) => {
363
if (transformCache.has(source)) {
364
return transformCache.get(source);
365
}
366
367
const result = transforms.mandatoryTransforms(source);
368
transformCache.set(source, result);
369
return result;
370
};
371
```