u2a 3.3.0 → 3.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u2a",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "description": "URL to App - Turn any URL into a desktop application",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,14 +1,16 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { execSync } = require('child_process');
4
3
  const { normalizeUrl, getDomainName } = require('../utils/url');
5
4
  const { getFavicon, processFavicon } = require('../utils/favicon');
6
5
  const { APPS_DIR, readDB, writeDB } = require('../utils/config');
7
6
  const Logger = require('../utils/logger');
8
7
  const os = require('os');
8
+ const { sanitizeInput } = require('../utils/sanitize');
9
+ const { secureExec } = require('../utils/securexec');
9
10
 
10
11
  const logger = new Logger('create');
11
12
 
13
+
12
14
  function createWindowsShortcut(appInfo) {
13
15
  try {
14
16
  const { appName, appDir, iconPath } = appInfo;
@@ -36,7 +38,7 @@ function createWindowsShortcut(appInfo) {
36
38
  const tempScriptPath = path.join(os.tmpdir(), `create_shortcut_${appName}.ps1`);
37
39
  fs.writeFileSync(tempScriptPath, psScript);
38
40
 
39
- execSync(`powershell -ExecutionPolicy Bypass -File "${tempScriptPath}"`, {
41
+ secureExec(`powershell -ExecutionPolicy Bypass -File "${tempScriptPath}"`, {
40
42
  stdio: ['ignore', 'pipe', 'pipe'],
41
43
  windowsHide: true
42
44
  });
@@ -553,7 +555,7 @@ async function buildExecutable(appDir, appName, platform, iconPath, options) {
553
555
  windowsHide: true
554
556
  };
555
557
 
556
- execSync('npm install --save-dev electron-packager electron', installOptions);
558
+ secureExec('npm install --save-dev electron-packager electron', installOptions);
557
559
 
558
560
  let platformFlag = '';
559
561
  let archFlag = `--arch=${options.arch || 'x64'}`;
@@ -583,7 +585,7 @@ async function buildExecutable(appDir, appName, platform, iconPath, options) {
583
585
 
584
586
  logger.debug(`Executing: ${packageCommand}`);
585
587
 
586
- execSync(packageCommand, installOptions);
588
+ secureExec(packageCommand, installOptions);
587
589
 
588
590
  let distPlatform = '';
589
591
  switch(platform) {
@@ -629,7 +631,7 @@ async function buildSetup(appDir, platform, arch) {
629
631
  windowsHide: true
630
632
  };
631
633
 
632
- execSync('npm install --save-dev electron-builder', installOptions);
634
+ secureExec('npm install --save-dev electron-builder', installOptions);
633
635
 
634
636
  let builderArgs = '';
635
637
  switch(platform) {
@@ -652,7 +654,7 @@ async function buildSetup(appDir, platform, arch) {
652
654
 
653
655
  const builderCommand = `npx electron-builder ${builderArgs}`;
654
656
  logger.debug(`Executing: ${builderCommand}`);
655
- execSync(builderCommand, installOptions);
657
+ secureExec(builderCommand, installOptions);
656
658
 
657
659
  const installerPath = path.join(appDir, 'installer');
658
660
  if (fs.existsSync(installerPath)) {
@@ -673,8 +675,8 @@ async function createApp(url, options) {
673
675
 
674
676
  try {
675
677
  url = await normalizeUrl(url);
676
- const domain = getDomainName(url);
677
- const appName = options.name || domain;
678
+ const domain = sanitizeInput(getDomainName(url));
679
+ const appName = sanitizeInput(options.name || domain);
678
680
 
679
681
  const db = readDB();
680
682
  if (db.hasOwnProperty(appName)) {
@@ -710,7 +712,7 @@ async function createApp(url, options) {
710
712
  windowsHide: true
711
713
  };
712
714
 
713
- execSync('npm install --only=prod', installOptions);
715
+ secureExec('npm install --only=prod', installOptions);
714
716
  logger.debug(`npm install completed`);
715
717
 
716
718
  let executablePath = null;
@@ -1,14 +1,14 @@
1
1
  const fs = require('fs');
2
2
  const inquirer = require('inquirer');
3
- const { normalizeUrl, getDomainName } = require('../utils/url');
4
3
  const { readDB, writeDB, APPS_DIR } = require('../utils/config');
5
4
  const Logger = require('../utils/logger');
6
5
  const { removeAppFromOS } = require('./create');
7
6
  const path = require('path');
7
+ const { sanitizeInput } = require('../utils/sanitize');
8
8
 
9
9
  const logger = new Logger('remove');
10
10
 
11
- async function removeApp(appName) {
11
+ async function processRemoval(appName) {
12
12
  try {
13
13
  const db = readDB();
14
14
 
@@ -53,6 +53,11 @@ async function removeApp(appName) {
53
53
  }
54
54
  }
55
55
 
56
+ async function removeApp(appName) {
57
+ const sAppName = sanitizeInput(appName);
58
+ await processRemoval(sAppName);
59
+ }
60
+
56
61
  module.exports = {
57
62
  removeApp
58
63
  };
@@ -0,0 +1,21 @@
1
+ const Logger = require('./logger');
2
+ const logger = new Logger('sanitize');
3
+
4
+
5
+ function sanitizeInput(userInput) {
6
+ const sInput = userInput.replace(/[^a-zA-Z0-9_\-.\s:/@%]/g, '_');
7
+ logger.debug(`Original content: ${userInput} | Sanitized content: ${sInput}`);
8
+ return sInput;
9
+ }
10
+
11
+ function sanitizeCommand(command) {
12
+ const sCommand = command.replace(/[^\w\-.:/@\\ ="']/g, '_');
13
+ logger.debug(`Original content: ${command} | Sanitized content: ${sCommand}`);
14
+ return sCommand;
15
+ }
16
+
17
+
18
+ module.exports = {
19
+ sanitizeInput,
20
+ sanitizeCommand
21
+ }
@@ -0,0 +1,13 @@
1
+ const { execSync } = require('child_process');
2
+ const { sanitizeCommand } = require('./sanitize');
3
+
4
+ function secureExec(command, options = {}) {
5
+ const sanitizedCommand = sanitizeCommand(command);
6
+ const result = execSync(sanitizedCommand, options);
7
+
8
+ return result;
9
+ }
10
+
11
+ module.exports = {
12
+ secureExec
13
+ }
package/src/utils/url.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const axios = require('axios');
2
+ const { sanitizeInput } = require('./sanitize');
2
3
 
3
4
  async function normalizeUrl(url) {
4
5
  if (!url.startsWith('http://') && !url.startsWith('https://')) {
@@ -9,7 +10,7 @@ async function normalizeUrl(url) {
9
10
  url = 'http://' + url;
10
11
  }
11
12
  }
12
- return url;
13
+ return sanitizeInput(url);
13
14
  }
14
15
 
15
16
  function getDomainName(url) {
@@ -17,7 +18,7 @@ function getDomainName(url) {
17
18
  const { hostname } = new URL(url);
18
19
  return hostname.replace(/^www\./, '');
19
20
  } catch (error) {
20
- return url;
21
+ return sanitizeInput(url);
21
22
  }
22
23
  }
23
24