jscrambler 8.6.6 → 8.7.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # jscrambler
2
2
 
3
+ ## 8.7.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [ecba0c7]: new beforeProtection type: webpack-ignore-vendors
8
+
9
+ ## 8.7.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [d0b95d7]: Added metadata report feature on cli
14
+
3
15
  ## 8.6.6
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -135,6 +135,8 @@ Options:
135
135
  -n <number> (version 7.2 and above) Create multiple protections at once.
136
136
  --delete-protection-on-success <bool> Deletes the protection files after they have been protected and downloaded (default: false)
137
137
  --mode <mode> (version 8.4 and above) Define protection mode. Possible values: automatic, manual (default: manual)
138
+ --save-src <bool> Protection should save application sources (default: true)
139
+ --protection-report <string> (version 8.4 and above) Protection id for the metadata report
138
140
  -h, --help output usage information
139
141
  ```
140
142
 
@@ -352,6 +354,10 @@ The concatenation of files can result in max file size errors - even though the
352
354
  "type": "prepend-js",
353
355
  "target": "/path/to/target/file.js",
354
356
  "source": "/path/to/script/file.js"
357
+ },
358
+ {
359
+ "type": "webpack-ignore-vendors",
360
+ "report": "/path/to/webpack/stats.json"
355
361
  }
356
362
  ]
357
363
  }
@@ -10,6 +10,7 @@ var _filesizeParser = _interopRequireDefault(require("filesize-parser"));
10
10
  var _config2 = _interopRequireDefault(require("../config"));
11
11
  var _ = _interopRequireDefault(require("../"));
12
12
  var _utils = require("../utils");
13
+ var _fs = _interopRequireDefault(require("fs"));
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
15
16
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -66,57 +67,87 @@ const validateBeforeProtection = function () {
66
67
  if (beforeProtectionArray.length === 0) {
67
68
  return;
68
69
  }
69
- const mandatoryKeys = ['type', 'target', 'source'];
70
- const usedTargets = new Set();
71
- const usedSources = new Set();
72
70
  beforeProtectionArray.filter(element => {
73
- // Check if every array element has a type, a target and a source
74
- const validateMandatoryKeys = mandatoryKeys.every(key => key in element);
75
- if (!validateMandatoryKeys) {
76
- console.error('Invalid structure on beforeProtection: each element must have the following structure { type: "type", target: "/path/to/target", source: "/path/to/script"}');
77
- process.exit(1);
78
- }
79
71
  const {
80
- target,
81
- source,
82
72
  type
83
73
  } = element;
74
+ switch (type) {
75
+ case _utils.APPEND_JS_TYPE:
76
+ case _utils.PREPEND_JS_TYPE:
77
+ const mandatoryKeys = ['type', 'target', 'source'];
78
+ const usedTargets = new Set();
79
+ const usedSources = new Set();
84
80
 
85
- // Check if only valid types are being used
86
- if (type !== _utils.APPEND_JS_TYPE && type !== _utils.PREPEND_JS_TYPE) {
87
- console.error("Invalid type on beforeProtection: only \"".concat(_utils.APPEND_JS_TYPE, "\" or \"").concat(_utils.PREPEND_JS_TYPE, "\" are allowed."));
88
- process.exit(1);
89
- }
81
+ // Check if every array element has a type, a target and a source
82
+ const validateMandatoryKeys = mandatoryKeys.every(key => key in element);
83
+ if (!validateMandatoryKeys) {
84
+ console.error('Invalid structure on beforeProtection: each element must have the following structure { type: "type", target: "/path/to/target", source: "/path/to/script"}');
85
+ process.exit(1);
86
+ }
87
+ const {
88
+ target,
89
+ source
90
+ } = element;
90
91
 
91
- // Check if the provided files are js, mjs or cjs files
92
- if (!(0, _utils.isJavascriptFile)(target) || !(0, _utils.isJavascriptFile)(source)) {
93
- console.error('Invalid extension for beforeProtection target or source files: only *js, mjs and cjs* files can be used to append or prepend.');
94
- process.exit(1);
95
- }
92
+ // Check if the provided files are js, mjs or cjs files
93
+ if (!(0, _utils.isJavascriptFile)(target) || !(0, _utils.isJavascriptFile)(source)) {
94
+ console.error("Invalid extension for beforeProtection (".concat(type, ") target or source files: only *js, mjs and cjs* files can be used to append or prepend."));
95
+ process.exit(1);
96
+ }
96
97
 
97
- // Check if the target has already been used as a source
98
- if (usedTargets.has(source)) {
99
- console.error("Error on beforeProtection: file \"".concat(source, "\" has already been used as target and can't be used as source."));
100
- process.exit(1);
101
- }
102
- if (usedSources.has(target)) {
103
- console.error("Error on beforeProtection: file \"".concat(target, "\" has already been used as source and can't be used as target."));
104
- process.exit(1);
105
- }
98
+ // Check if the target has already been used as a source
99
+ if (usedTargets.has(source)) {
100
+ console.error("Error on beforeProtection (".concat(type, "): file \"").concat(source, "\" has already been used as target and can't be used as source."));
101
+ process.exit(1);
102
+ }
103
+ if (usedSources.has(target)) {
104
+ console.error("Error on beforeProtection (".concat(type, "): file \"").concat(target, "\" has already been used as source and can't be used as target."));
105
+ process.exit(1);
106
+ }
106
107
 
107
- // Check if the target and source are the same
108
- if (target === source) {
109
- console.error("Error on beforeProtection: File \"".concat(target, "\" can't be used as both a target and a source."));
110
- process.exit(1);
111
- }
108
+ // Check if the target and source are the same
109
+ if (target === source) {
110
+ console.error("Error on beforeProtection (".concat(type, "): File \"").concat(target, "\" can't be used as both a target and a source."));
111
+ process.exit(1);
112
+ }
112
113
 
113
- // Add the target and the source to the corresponding sets
114
- usedTargets.add(target);
115
- usedSources.add(source);
114
+ // Add the target and the source to the corresponding sets
115
+ usedTargets.add(target);
116
+ usedSources.add(source);
117
+ break;
118
+ case _utils.WEBPACK_IGNORE_VENDORS:
119
+ if (!("report" in element)) {
120
+ console.error("Invalid structure on beforeProtection (".concat(type, "): \"report\" property is mandatory for this type"));
121
+ process.exit(1);
122
+ }
123
+ if (!_fs.default.existsSync(element.report)) {
124
+ console.error("Error on beforeProtection (".concat(type, "): source webpack report does not exist."));
125
+ process.exit(1);
126
+ }
127
+ const content = _fs.default.readFileSync(element.report, 'utf8');
128
+ let report;
129
+ try {
130
+ report = JSON.parse(content);
131
+ } catch (e) {
132
+ console.error("Error on beforeProtection (".concat(type, "): invalid source webpack report. Reason: ").concat(e.message));
133
+ process.exit(1);
134
+ }
135
+ element.excludeModules = new Map();
136
+ for (let module of report.modules) {
137
+ if (module.name && module.name.includes('/node_modules/')) {
138
+ element.excludeModules.set(module.id, module.name);
139
+ }
140
+ }
141
+ console.log("beforeProtection (".concat(type, "): Webpack report \"").concat(_path.default.basename(element.report), "\" was loaded"));
142
+ break;
143
+ default:
144
+ console.error("Invalid type on beforeProtection (".concat(type, "): only \"").concat(_utils.APPEND_JS_TYPE, "\", \"").concat(_utils.PREPEND_JS_TYPE, "\" or \"").concat(_utils.WEBPACK_IGNORE_VENDORS, "\" are allowed."));
145
+ process.exit(1);
146
+ }
116
147
  });
117
148
  return beforeProtectionArray;
118
149
  };
119
- _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')).parse(process.argv);
150
+ _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').parse(process.argv);
120
151
  let globSrc, filesSrc, config;
121
152
 
122
153
  // If -c, --config file was provided
@@ -368,6 +399,15 @@ if (_commander.default.sourceMaps) {
368
399
  console.error(debug ? error : error.message || error);
369
400
  process.exit(1);
370
401
  });
402
+ } else if (_commander.default.protectionReport) {
403
+ (async () => {
404
+ try {
405
+ await _.default.getProtectionMetadata(clientSettings, _commander.default.protectionReport, _commander.default.outputDir);
406
+ } catch (error) {
407
+ console.error(debug ? error : error.message || error);
408
+ process.exit(1);
409
+ }
410
+ })();
371
411
  } else {
372
412
  // Go, go, go
373
413
  (async () => {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = _default;
8
+ exports.getIntrospection = getIntrospection;
8
9
  var introspection = _interopRequireWildcard(require("./introspection"));
9
10
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
10
11
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ var _constants = require("./constants");
19
19
  var _zip = require("./zip");
20
20
  var introspection = _interopRequireWildcard(require("./introspection"));
21
21
  var _utils = require("./utils");
22
- var _getProtectionDefaultFragments = _interopRequireDefault(require("./get-protection-default-fragments"));
22
+ var _getProtectionDefaultFragments = _interopRequireWildcard(require("./get-protection-default-fragments"));
23
23
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
24
24
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
25
25
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -150,7 +150,7 @@ var _default = exports.default = {
150
150
  }
151
151
  if (runBeforeProtection.length > 0) {
152
152
  runBeforeProtection.map(element => {
153
- if (!_filesSrc.includes(element.target)) {
153
+ if ((element.type === _utils.PREPEND_JS_TYPE || element.type === _utils.APPEND_JS_TYPE) && !_filesSrc.includes(element.target)) {
154
154
  console.error('Error on beforeProtection: Target files need to be in the files to protect list (or filesSrc).');
155
155
  process.exit(1);
156
156
  }
@@ -764,7 +764,7 @@ var _default = exports.default = {
764
764
  if (typeof destCallback === 'function') {
765
765
  destCallback(download, filesDest);
766
766
  } else {
767
- await fsPromises.writeFile(_path.default.join(filesDest, "".concat(protectionId, "_symbolTable.json")), download);
767
+ await _fs.default.promises.writeFile(_path.default.join(filesDest, "".concat(protectionId, "_symbolTable.json")), download);
768
768
  }
769
769
  },
770
770
  /**
@@ -1108,6 +1108,84 @@ var _default = exports.default = {
1108
1108
  const dataArg = result.args.find(arg => arg.name === 'data');
1109
1109
  const isFieldSupported = dataArg && dataArg.type.inputFields.some(e => e.name === field);
1110
1110
  return isFieldSupported;
1111
+ },
1112
+ async getProtectionMetadata(conf, protectionId, outputDir) {
1113
+ const INVALID_PARAMETERS = ['original', 'initialCleanup', 'wrapUp'];
1114
+ const finalConfig = buildFinalConfig(conf);
1115
+ const {
1116
+ applicationId,
1117
+ host,
1118
+ port,
1119
+ basePath,
1120
+ protocol,
1121
+ cafile,
1122
+ keys,
1123
+ jscramblerVersion,
1124
+ proxy,
1125
+ utc,
1126
+ clientId
1127
+ } = finalConfig;
1128
+ const {
1129
+ accessKey,
1130
+ secretKey
1131
+ } = keys;
1132
+ const client = new this.Client({
1133
+ accessKey,
1134
+ secretKey,
1135
+ host,
1136
+ port,
1137
+ basePath,
1138
+ protocol,
1139
+ cafile,
1140
+ jscramblerVersion,
1141
+ proxy,
1142
+ utc,
1143
+ clientId
1144
+ });
1145
+ const appSource = await (0, _getProtectionDefaultFragments.getIntrospection)(client, 'ApplicationSource');
1146
+ if (!appSource.fields.some(_ref6 => {
1147
+ let {
1148
+ name
1149
+ } = _ref6;
1150
+ return name === 'transformedContentHash';
1151
+ })) {
1152
+ console.error("\"Protection report\" it's only available on Jscrambler version 8.4 and above.");
1153
+ process.exit(1);
1154
+ }
1155
+ const response = await this.getApplicationProtection(client, applicationId, protectionId, {
1156
+ application: '_id',
1157
+ applicationProtection: '_id, applicationId, parameters, version, areSubscribersOrdered, useRecommendedOrder, tolerateMinification, profilingDataMode, useAppClassification, browsers, sourceMaps, sources { filename, transformedContentHash, metrics { transformation } }'
1158
+ });
1159
+ errorHandler(response);
1160
+ const sourcesInfo = response.data.applicationProtection.sources.map(source => {
1161
+ const parameters = source.metrics.filter(metric => !INVALID_PARAMETERS.includes(metric.transformation));
1162
+ return {
1163
+ filename: source.filename,
1164
+ sha256Checksum: source.transformedContentHash,
1165
+ parameters: parameters.map(param => param.transformation)
1166
+ };
1167
+ });
1168
+ const metadataJson = JSON.stringify({
1169
+ applicationId: response.data.applicationProtection.applicationId,
1170
+ // eslint-disable-next-line no-underscore-dangle
1171
+ protectionId: response.data.applicationProtection._id,
1172
+ jscramblerVersion: response.data.applicationProtection.version,
1173
+ areSubscribersOrdered: response.data.applicationProtection.areSubscribersOrdered,
1174
+ useRecommendedOrder: response.data.applicationProtection.useRecommendedOrder,
1175
+ tolerateMinification: response.data.applicationProtection.tolerateMinification,
1176
+ profilingDataMode: response.data.applicationProtection.profilingDataMode,
1177
+ useAppClassification: response.data.applicationProtection.useAppClassification,
1178
+ browsers: response.data.applicationProtection.browsers,
1179
+ sourceMaps: response.data.applicationProtection.sourceMaps,
1180
+ parameters: response.data.applicationProtection.parameters,
1181
+ sources: sourcesInfo
1182
+ }, null, 2);
1183
+ if (outputDir) {
1184
+ await _fs.default.promises.writeFile(outputDir, metadataJson);
1185
+ console.log("Protection Report ".concat(protectionId, " saved in ").concat(outputDir));
1186
+ } else {
1187
+ console.log(metadataJson);
1188
+ }
1111
1189
  }
1112
1190
  };
1113
1191
  function getFileFromUrl(client, url) {