jscrambler 8.10.9 → 8.11.1
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/CHANGELOG.md +12 -0
- package/README.md +29 -0
- package/dist/bin/jscrambler.js +34 -4
- package/dist/cleanup-input-fields.js +2 -2
- package/dist/index.js +10 -1
- package/dist/utils.js +29 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ If you're looking to gain control over third-party tags and achieve PCI DSS comp
|
|
|
26
26
|
- [Instrument (`--instrument`)](#instrument---instrument)
|
|
27
27
|
- [Symbol Table](#symbol-table)
|
|
28
28
|
- [Global Names Prefix](#global-names-prefix)
|
|
29
|
+
- [Custom labels (customLabels)](#custom-labels-customlabels)
|
|
29
30
|
- [API](#api)
|
|
30
31
|
- [Quick example](#quick-example)
|
|
31
32
|
- [Jscrambler Parameters](#jscrambler-parameters)
|
|
@@ -146,6 +147,7 @@ Options:
|
|
|
146
147
|
--protection-report <string> (version 8.4 and above) Protection id for the metadata report
|
|
147
148
|
--use-global-names-on-modules <bool> (version 8.5 and above) Force the usage of more complex names on modules (default: false)
|
|
148
149
|
--generate-alias <bool> Generate alias for the transformations (default: true)
|
|
150
|
+
--custom-label <key=value> Attach a custom label to the protection (repeatable)
|
|
149
151
|
-h, --help output usage information
|
|
150
152
|
```
|
|
151
153
|
|
|
@@ -441,6 +443,33 @@ If you apply the previous configuration, all generated global variable names wil
|
|
|
441
443
|
|
|
442
444
|
***Note***: The `globalNamesPrefix` parameter must be **short** and **unintelligible** to avoid code size increase and automated attacks
|
|
443
445
|
|
|
446
|
+
## Custom labels (customLabels)
|
|
447
|
+
|
|
448
|
+
You can attach optional **custom labels** to a protection request: a plain object of string keys and string values. They are sent to the API as **`customLabels`** (for example to record build environment, version, or CI metadata). Your Jscrambler API version must support this field; on older APIs the client may omit it and print a warning.
|
|
449
|
+
|
|
450
|
+
### Configuration file
|
|
451
|
+
|
|
452
|
+
Add a `customLabels` object next to your other options (for example in `.jscramblerrc` or a file passed with `-c, --config`):
|
|
453
|
+
|
|
454
|
+
```json
|
|
455
|
+
{
|
|
456
|
+
"customLabels": {
|
|
457
|
+
"env": "production",
|
|
458
|
+
"version": "9.2.2"
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Keys must be non-empty strings; values must be strings (use quoted JSON for numeric-looking values, e.g. `"9.2.2"`).
|
|
464
|
+
|
|
465
|
+
### CLI
|
|
466
|
+
|
|
467
|
+
Use **`--custom-label`** with `key=value`. You can pass it multiple times. Only the first `=` splits the key from the value (so values may contain `=`). If the same key appears in the config file and on the command line, the **CLI value wins**.
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
jscrambler -c config.json --custom-label env=production --custom-label version=9.2.2 -o out/ "src/**/*.js"
|
|
471
|
+
```
|
|
472
|
+
|
|
444
473
|
## API
|
|
445
474
|
```bash
|
|
446
475
|
npm install jscrambler
|
package/dist/bin/jscrambler.js
CHANGED
|
@@ -106,7 +106,20 @@ const validateBeforeProtection = function () {
|
|
|
106
106
|
});
|
|
107
107
|
return beforeProtectionArray;
|
|
108
108
|
};
|
|
109
|
-
|
|
109
|
+
const parseCustomLabelCommandLineOption = function (val) {
|
|
110
|
+
let accumulator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
111
|
+
const idx = val.indexOf('=');
|
|
112
|
+
if (idx < 1) {
|
|
113
|
+
console.error("*--custom-label* expects key=value (for example --custom-label \"env=production\"), got \"".concat(val, "\""));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
const key = val.slice(0, idx);
|
|
117
|
+
const value = val.slice(idx + 1);
|
|
118
|
+
return _objectSpread(_objectSpread({}, accumulator), {}, {
|
|
119
|
+
[key]: value
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
_commander.default.version(require('../../package.json').version).usage('[options] <file ...>').option('-a, --access-key <accessKey>', 'Access key').option('-c, --config <config>', 'Jscrambler configuration options').option('-H, --host <host>', 'Hostname').option('-i, --application-id <id>', 'Application ID').option('-o, --output-dir <dir>', 'Output directory').option('-p, --port <port>', 'Port').option('--base-path <path>', 'Base Path').option('--protocol <protocol>', 'Protocol (http or https)').option('--cafile <path>', 'Internal certificate authority').option('-C, --cwd <dir>', 'Current Working Directory').option('-s, --secret-key <secretKey>', 'Secret key').option('-m, --source-maps <id>', 'Download source maps').option('-R, --randomization-seed <seed>', 'Set randomization seed').option('--instrument', 'Instrument file(s) before start profiling. ATTENTION: previous profiling information will be deleted').option('--start-profiling', 'Starts profiling (assumes an already instrumented application)').option('--stop-profiling', 'Stops profiling').option('--code-hardening-threshold <threshold>', 'Set code hardening file size threshold. Format: {value}{unit="b,kb,mb"}. Example: 200kb', validateCodeHardeningThreshold).option('--recommended-order <bool>', 'Use recommended order', validateBool('recommended-order')).option('-W, --werror <bool>', 'Set werror flag value (default: true)', validateBool('werror')).option('--utc <bool>', 'Set UTC as the request time zone. Otherwise it uses the local time zone (default: true)', validateBool('utc')).option('--tolerate-minification <bool>', "Don't detect minification as malicious tampering (default: true)", validateBool('tolerate-minification')).option('--use-profiling-data <bool>', "(version 6.2 only) Protection should use the existing profiling data (default: true)", validateBool('use-profiling-data')).option('--profiling-data-mode <mode>', "(version 6.3 and above) Select profiling mode (default: automatic)", validateProfilingDataMode).option('--remove-profiling-data', "Removes the current application profiling information").option('--use-app-classification <bool>', '(version 6.3 and above) Protection should use Application Classification metadata when protecting (default: true)', validateBool('--use-app-classification')).option('--input-symbol-table <file>', '(version 6.3 and above) Protection should use symbol table when protecting. (default: no file)').option('--output-symbol-table <id>', '(version 6.3 and above) Download output symbol table (json)').option('--jscramblerVersion <version>', 'Use a specific Jscrambler version').option('--debugMode', 'Protect in debug mode').option('--skip-sources', 'Prevent source files from being updated').option('--force-app-environment <environment>', "(version 7.1 and above) Override application's environment detected automatically. Possible values: ".concat(availableEnvironments.toString()), validateForceAppEnvironment).option('--ensure-code-annotation <bool>', "(version 7.3 and above) Fail protection if no annotations are found on the source code (default: false)", validateBool('ensure-code-annotation')).option('-n <number>', "(version 7.2 and above) Create multiple protections at once.").option('--delete-protection-on-success <bool>', 'Deletes the protection files after they have been protected and downloaded (default: false)', validateBool('--delete-protection-on-success')).option('--mode <mode>', "(version 8.4 and above) Define protection mode. Possible values: automatic, manual (default: manual)", validateMode).option('--save-src <bool>', 'Protection should save application sources (default: true)', validateBool('--save-src')).option('--protection-report <string>', '(version 8.4 and above) Protection id for the metadata report').option('--use-global-names-on-modules <bool>', '(version 8.5 and above) Force the usage of more complex names on modules').option('--balance', '(version 8.4 and above) Gets the balance of the user').option('--generate-alias <bool>', '(version 8.5 and above) Generate alias for the transformations', validateBool('--generate-alias')).option('--custom-label <key=value>', 'Attach a custom label to the protection (repeatable). Example: --custom-label "env=production"', parseCustomLabelCommandLineOption, {}).parse(process.argv);
|
|
110
123
|
let globSrc, filesSrc, config;
|
|
111
124
|
|
|
112
125
|
// If -c, --config file was provided
|
|
@@ -117,6 +130,9 @@ if (_commander.default.config) {
|
|
|
117
130
|
} else {
|
|
118
131
|
config = {};
|
|
119
132
|
}
|
|
133
|
+
|
|
134
|
+
// Merge explicit config file (specified by CLI flag `--config`) with `.jscramblerrc` (`_config` fills undefined keys)
|
|
135
|
+
config = (0, _lodash.default)(config, _config2.default);
|
|
120
136
|
config.accessKey = _commander.default.accessKey || (config.keys ? config.keys.accessKey : undefined);
|
|
121
137
|
config.secretKey = _commander.default.secretKey || (config.keys ? config.keys.secretKey : undefined);
|
|
122
138
|
config.host = _commander.default.host || config.host;
|
|
@@ -174,7 +190,19 @@ if (_commander.default.forceAppEnvironment) {
|
|
|
174
190
|
} else {
|
|
175
191
|
config.forceAppEnvironment = config.forceAppEnvironment ? validateForceAppEnvironment(config.forceAppEnvironment) : undefined;
|
|
176
192
|
}
|
|
177
|
-
|
|
193
|
+
|
|
194
|
+
// Validate customLabels from file config
|
|
195
|
+
try {
|
|
196
|
+
config.customLabels = (0, _utils.validateCustomLabels)(config.customLabels);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
console.error(err.message);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
// Merge file config with CLI `--custom-label` flags (CLI wins on duplicate keys)
|
|
202
|
+
config.customLabels = _objectSpread(_objectSpread({}, config.customLabels), _commander.default.customLabel || {});
|
|
203
|
+
if (Object.keys(config.customLabels).length === 0) {
|
|
204
|
+
delete config.customLabels;
|
|
205
|
+
}
|
|
178
206
|
config.numberOfProtections = (0, _utils.validateNProtections)(_commander.default.N);
|
|
179
207
|
if (config.codeHardeningThreshold) {
|
|
180
208
|
config.codeHardeningThreshold = validateCodeHardeningThreshold(config.codeHardeningThreshold);
|
|
@@ -281,7 +309,8 @@ const {
|
|
|
281
309
|
saveSrc,
|
|
282
310
|
globalNamesPrefix,
|
|
283
311
|
useGlobalNamesOnModules,
|
|
284
|
-
generateAlias
|
|
312
|
+
generateAlias,
|
|
313
|
+
customLabels
|
|
285
314
|
} = config;
|
|
286
315
|
const params = config.params;
|
|
287
316
|
const incompatibleOptions = ['sourceMaps', 'instrument', 'startProfiling', 'stopProfiling'];
|
|
@@ -425,7 +454,8 @@ if (_commander.default.balance) {
|
|
|
425
454
|
saveSrc,
|
|
426
455
|
globalNamesPrefix,
|
|
427
456
|
useGlobalNamesOnModules,
|
|
428
|
-
generateAlias
|
|
457
|
+
generateAlias,
|
|
458
|
+
customLabels
|
|
429
459
|
});
|
|
430
460
|
try {
|
|
431
461
|
if (typeof werror !== 'undefined') {
|
|
@@ -16,9 +16,9 @@ function cleanupInputFields(args, fragments) {
|
|
|
16
16
|
if (!hasFieldArg && typeof options[field] !== 'undefined') {
|
|
17
17
|
options[field] = undefined;
|
|
18
18
|
cleanedUpFragments = cleanedUpFragments.replace(new RegExp(",?[s|\n]*".concat(field)), '');
|
|
19
|
-
console.warn("This API Version does not support the ".concat(field, " argument."));
|
|
19
|
+
console.warn("Warning: This API Version does not support the '".concat(field, "' argument."));
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
['tolerateMinification', 'useProfilingData', 'useAppClassification', 'inputSymbolTable', 'entryPoint', 'ensureCodeAnnotation', 'generateAlias'].forEach(fieldCleanUp);
|
|
22
|
+
['tolerateMinification', 'useProfilingData', 'useAppClassification', 'inputSymbolTable', 'entryPoint', 'ensureCodeAnnotation', 'generateAlias', 'customLabels'].forEach(fieldCleanUp);
|
|
23
23
|
return [options, cleanedUpFragments];
|
|
24
24
|
}
|
package/dist/index.js
CHANGED
|
@@ -221,6 +221,7 @@ var _default = exports.default = {
|
|
|
221
221
|
// {
|
|
222
222
|
// "filesSrc": [""],
|
|
223
223
|
// "params": {},
|
|
224
|
+
// "customLabels": { "env": "production", "version": "9.2.2" },
|
|
224
225
|
// "cwd": "",
|
|
225
226
|
// "host": "api.jscrambler.com",
|
|
226
227
|
// "port": "443",
|
|
@@ -233,6 +234,9 @@ var _default = exports.default = {
|
|
|
233
234
|
//
|
|
234
235
|
// `params` if provided will replace all the application transformation parameters.
|
|
235
236
|
//
|
|
237
|
+
// `customLabels` if provided attaches string key-value metadata to the protection request
|
|
238
|
+
// (API must support this field).
|
|
239
|
+
//
|
|
236
240
|
// `cwd` allows you to set the current working directory to resolve problems with
|
|
237
241
|
// relative paths with your `filesSrc` is outside the current working directory.
|
|
238
242
|
//
|
|
@@ -286,7 +290,8 @@ var _default = exports.default = {
|
|
|
286
290
|
saveSrc,
|
|
287
291
|
globalNamesPrefix,
|
|
288
292
|
useGlobalNamesOnModules,
|
|
289
|
-
generateAlias
|
|
293
|
+
generateAlias,
|
|
294
|
+
customLabels
|
|
290
295
|
} = finalConfig;
|
|
291
296
|
const {
|
|
292
297
|
accessKey,
|
|
@@ -416,6 +421,10 @@ var _default = exports.default = {
|
|
|
416
421
|
useGlobalNamesOnModules,
|
|
417
422
|
generateAlias
|
|
418
423
|
});
|
|
424
|
+
const normalizedCustomLabels = (0, _utils.validateCustomLabels)(customLabels);
|
|
425
|
+
if (Object.keys(normalizedCustomLabels).length) {
|
|
426
|
+
protectionOptions.customLabels = normalizedCustomLabels;
|
|
427
|
+
}
|
|
419
428
|
if (finalConfig.inputSymbolTable) {
|
|
420
429
|
const inputSymbolTableContents = await _fs.default.promises.readFile(finalConfig.inputSymbolTable, 'utf-8');
|
|
421
430
|
protectionOptions.inputSymbolTable = inputSymbolTableContents;
|
package/dist/utils.js
CHANGED
|
@@ -7,8 +7,10 @@ exports.PREPEND_JS_TYPE = exports.APPEND_JS_TYPE = void 0;
|
|
|
7
7
|
exports.concatenate = concatenate;
|
|
8
8
|
exports.getMatchedFiles = getMatchedFiles;
|
|
9
9
|
exports.isJavascriptFile = isJavascriptFile;
|
|
10
|
+
exports.validateCustomLabels = validateCustomLabels;
|
|
10
11
|
exports.validateNProtections = validateNProtections;
|
|
11
12
|
exports.validateThresholdFn = void 0;
|
|
13
|
+
require("core-js/modules/web.dom-collections.iterator.js");
|
|
12
14
|
var _glob = require("glob");
|
|
13
15
|
var _fs = _interopRequireDefault(require("fs"));
|
|
14
16
|
var _path = require("path");
|
|
@@ -41,6 +43,33 @@ function validateNProtections(n) {
|
|
|
41
43
|
}
|
|
42
44
|
return nProtections;
|
|
43
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validate protection `customLabels`: a plain object with non-empty keys and string values.
|
|
49
|
+
* @param {*} customLabels From config or programmatic options; omit or pass `undefined` for none.
|
|
50
|
+
* @returns {Object.<string, string>} A shallow copy when valid; `{}` when `customLabels` is `undefined`.
|
|
51
|
+
* @throws {Error} If `customLabels` is `null`, an array, a non-object, or has invalid keys/values.
|
|
52
|
+
*/
|
|
53
|
+
function validateCustomLabels(customLabels) {
|
|
54
|
+
if (typeof customLabels === 'undefined') {
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
if (customLabels === null || typeof customLabels !== 'object' || Array.isArray(customLabels)) {
|
|
58
|
+
throw new Error('Invalid *customLabels*: expected a plain object. Eg: { "env": "production", "version": "9.2.2" }');
|
|
59
|
+
}
|
|
60
|
+
const out = {};
|
|
61
|
+
for (const key of Object.keys(customLabels)) {
|
|
62
|
+
if (!key) {
|
|
63
|
+
throw new Error('Invalid *customLabels*: keys must be non-empty strings. Eg: { "env": "production", "version": "9.2.2" }');
|
|
64
|
+
}
|
|
65
|
+
const value = customLabels[key];
|
|
66
|
+
if (typeof value !== 'string') {
|
|
67
|
+
throw new Error("Invalid *customLabels*: value for \"".concat(key, "\" must be a string. Eg: { \"env\": \"production\", \"version\": \"9.2.2\" }"));
|
|
68
|
+
}
|
|
69
|
+
out[key] = value;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
44
73
|
const APPEND_JS_TYPE = exports.APPEND_JS_TYPE = 'append-js';
|
|
45
74
|
const PREPEND_JS_TYPE = exports.PREPEND_JS_TYPE = 'prepend-js';
|
|
46
75
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jscrambler",
|
|
3
3
|
"description": "Jscrambler Code Integrity API client.",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.11.1",
|
|
5
5
|
"homepage": "https://github.com/jscrambler/jscrambler",
|
|
6
6
|
"author": "Jscrambler <support@jscrambler.com>",
|
|
7
7
|
"repository": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"node": ">= 12.17.0"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"axios": "1.
|
|
24
|
+
"axios": "1.15.0",
|
|
25
25
|
"commander": "^2.8.1",
|
|
26
26
|
"core-js": "3.38.1",
|
|
27
27
|
"filesize-parser": "1.5.0",
|