Skip to content

Conversation

@Kinice
Copy link
Collaborator

@Kinice Kinice commented Jan 23, 2025

No description provided.

const homeDeno = path.resolve(os.homedir(), '.deno/bin/deno');
function checkDeno(command: string) {
return new Promise((resolve, reject) => {
exec(`${command} --version`, (err) => {

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.

Copilot Autofix

AI 9 months ago

To fix the problem, we should avoid constructing the shell command dynamically and instead use execFile or execFileSync to pass the command and its arguments separately. This approach ensures that the shell does not interpret the command string, thus preventing command injection vulnerabilities.

Specifically, we need to:

  1. Replace the use of exec with execFile in the checkDeno function.
  2. Modify the checkDeno function to pass the command and its arguments separately.
Suggested changeset 1
src/utils/installDeno.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/utils/installDeno.ts b/src/utils/installDeno.ts
--- a/src/utils/installDeno.ts
+++ b/src/utils/installDeno.ts
@@ -1,2 +1,2 @@
-import { exec, execSync } from 'child_process';
+import { execFile, execSync } from 'child_process';
 import os from 'os';
@@ -26,3 +26,3 @@
     return new Promise((resolve, reject) => {
-      exec(`${command} --version`, (err) => {
+      execFile(command, ['--version'], (err) => {
         if (err) {
EOF
@@ -1,2 +1,2 @@
import { exec, execSync } from 'child_process';
import { execFile, execSync } from 'child_process';
import os from 'os';
@@ -26,3 +26,3 @@
return new Promise((resolve, reject) => {
exec(`${command} --version`, (err) => {
execFile(command, ['--version'], (err) => {
if (err) {
Copilot is powered by AI and may make mistakes. Always verify output.
const p = path.join(__dirname, './install');
const installCommand = `sh ${p}/installEw2.sh ${manifest.version}`;
try {
execSync(installCommand, { stdio: 'inherit', env: { ...process.env } });

Check failure

Code scanning / CodeQL

Uncontrolled command line Critical

This command line depends on a
user-provided value
.

Copilot Autofix

AI 9 months ago

To fix the problem, we should avoid using execSync with a concatenated string that includes untrusted data. Instead, we can use execFileSync which allows us to pass command arguments as an array, thus avoiding the risk of command injection. This approach ensures that the command and its arguments are properly separated and handled securely by the operating system.

We need to modify the installEw2 function to use execFileSync instead of execSync. We will also need to import execFileSync from the child_process module.

Suggested changeset 1
src/utils/installEw2.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/utils/installEw2.ts b/src/utils/installEw2.ts
--- a/src/utils/installEw2.ts
+++ b/src/utils/installEw2.ts
@@ -5,3 +5,3 @@
 import https from 'https';
-import { execSync } from 'child_process';
+import { execFileSync } from 'child_process';
 import logger from '../libs/logger.js';
@@ -117,5 +117,5 @@
   const p = path.join(__dirname, './install');
-  const installCommand = `sh ${p}/installEw2.sh ${manifest.version}`;
+  const installScript = path.join(p, 'installEw2.sh');
   try {
-    execSync(installCommand, { stdio: 'inherit', env: { ...process.env } });
+    execFileSync('sh', [installScript, manifest.version], { stdio: 'inherit', env: { ...process.env } });
     const md5 = await calculateFileMD5(EW2BinPath);
EOF
@@ -5,3 +5,3 @@
import https from 'https';
import { execSync } from 'child_process';
import { execFileSync } from 'child_process';
import logger from '../libs/logger.js';
@@ -117,5 +117,5 @@
const p = path.join(__dirname, './install');
const installCommand = `sh ${p}/installEw2.sh ${manifest.version}`;
const installScript = path.join(p, 'installEw2.sh');
try {
execSync(installCommand, { stdio: 'inherit', env: { ...process.env } });
execFileSync('sh', [installScript, manifest.version], { stdio: 'inherit', env: { ...process.env } });
const md5 = await calculateFileMD5(EW2BinPath);
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines 152 to 165
const workerRes = await fetch(
`http://${localUpstream ? localUpstream : host}${url}`,
{
method,
headers: {
...headers,
'x-er-context':
'eyJzaXRlX2lkIjogIjYyMjcxODQ0NjgwNjA4IiwgInNpdGVfbmFtZSI6ICJjb21wdXRlbHguYWxpY2RuLXRlc3QuY29tIiwgInNpdGVfcmVjb3JkIjogIm1vY2hlbi1uY2RuLmNvbXB1dGVseC5hbGljZG4tdGVzdC5jb20iLCAiYWxpdWlkIjogIjEzMjI0OTI2ODY2NjU2MDgiLCAic2NoZW1lIjoiaHR0cCIsICAiaW1hZ2VfZW5hYmxlIjogdHJ1ZX0=',
'x-er-id': 'a.bA'
},
body: req.method === 'GET' ? undefined : req,
agent: new HttpProxyAgent(`http://127.0.0.1:${ew2Port}`)
}
);

Check failure

Code scanning / CodeQL

Server-side request forgery Critical

The
URL
of this request depends on a
user-provided value
.

Copilot Autofix

AI 4 months ago

To fix the SSRF vulnerability:

  1. Restrict the use of host: Replace the user-provided req.headers.host with a fixed, pre-approved value or restrict it to an allowlist of trusted hosts.
  2. Sanitize url: Ensure req.url does not contain malicious input (e.g., path traversal or query manipulation).
  3. Use a known-safe base for URLs: Construct the URL using a hardcoded base or a validated and sanitized alternative.

The best fix is to introduce an allowlist of trusted hosts and safely construct the URL using validated components. This ensures the application only communicates with pre-approved endpoints, mitigating SSRF risks.


Suggested changeset 1
src/commands/dev/ew2/server.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/commands/dev/ew2/server.ts b/src/commands/dev/ew2/server.ts
--- a/src/commands/dev/ew2/server.ts
+++ b/src/commands/dev/ew2/server.ts
@@ -161,8 +161,9 @@
         }
       }
       try {
-        const host = req.headers.host;
-        const url = req.url;
+        const trustedHosts = ['allowed-host1.com', 'allowed-host2.com'];
+        const host = trustedHosts.includes(req.headers.host || '') ? req.headers.host : 'default-host.com';
+        const url = new URL(req.url || '/', `http://${host}`);
         const method = req.method;
         const headers = Object.entries(req.headers).reduce(
           (acc: Record<string, string | undefined>, [key, value]) => {
@@ -180,7 +181,7 @@
         // @ts-ignore
         const localUpstream = global.localUpstream;
         const workerRes = await fetch(
-          `http://${localUpstream ? localUpstream : host}${url}`,
+          `http://${localUpstream ? localUpstream : url.hostname}${url.pathname}${url.search}`,
           {
             method,
             headers: {
EOF
@@ -161,8 +161,9 @@
}
}
try {
const host = req.headers.host;
const url = req.url;
const trustedHosts = ['allowed-host1.com', 'allowed-host2.com'];
const host = trustedHosts.includes(req.headers.host || '') ? req.headers.host : 'default-host.com';
const url = new URL(req.url || '/', `http://${host}`);
const method = req.method;
const headers = Object.entries(req.headers).reduce(
(acc: Record<string, string | undefined>, [key, value]) => {
@@ -180,7 +181,7 @@
// @ts-ignore
const localUpstream = global.localUpstream;
const workerRes = await fetch(
`http://${localUpstream ? localUpstream : host}${url}`,
`http://${localUpstream ? localUpstream : url.hostname}${url.pathname}${url.search}`,
{
method,
headers: {
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants