Skip to content

Remerge dev to master - #14

Merged
WouterKoch merged 80 commits into
masterfrom
dev
Dec 2, 2025
Merged

Remerge dev to master#14
WouterKoch merged 80 commits into
masterfrom
dev

Conversation

@WouterKoch

Copy link
Copy Markdown
Member

No description provided.

Comment thread server.js
Comment on lines +86 to +88
const cleanIP = realIP
.replace(/^::ffff:/, '')
.replace(/:\d+[^:]*$/, '')

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
This
regular expression
that depends on
a user-provided value
may run slow on strings starting with ':0' and with many repetitions of '0'.
Comment thread server.js
Comment on lines +636 to +643
scientificNameIdObject = await axios
.get(url, {
timeout: 3000,
headers: {
'Accept-Encoding': 'gzip',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:145.0) Gecko/20100101 Firefox/145.0'
}
})

Check failure

Code scanning / CodeQL

Server-side request forgery Critical

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

Copilot Autofix

AI 8 months ago

To resolve this SSRF vulnerability, user input for sciNameId (from the /cachetaxon/id/* endpoint) should be validated prior to building an outgoing request URL. The safest approach is to only allow expected, well-formed taxon IDs: for example, restrict to numeric or strictly alphanumeric values, matching the anticipated identifier format. Reject or sanitize any input that could allow path traversal, special characters, or other manipulations.

  1. Validate taxonId in the route handler: Add a check to verify the incoming taxon ID only matches allowed patterns (e.g., numbers, or letters/numbers/underscores). If the validation fails, return a 400 Bad Request.
  2. Optionally, validate in getName as well: As extra defense, you can also validate sciNameId before constructing the remote API URL.

Changes to make:

  • In /cachetaxon/id/* route handler, validate extracted taxonId using a regular expression.
  • If validation fails, return HTTP 400 and do not make backend requests.
  • You may use a well-known library like validator (if allowed), or Node's own regex, as seen in provided imports.

Only changes within server.js are required.


Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -1955,6 +1955,11 @@
 app.get("/cachetaxon/id/*", cacheLimiter, authenticateAdminToken, async (req, res) => {
   try {
     let taxonId = decodeURI(req.originalUrl.replace("/cachetaxon/id/", ""));
+    // Only allow strictly alphanumeric (plus underscore/dash), 1-50 chars -- adjust as needed for real taxon IDs
+    if (!taxonId.match(/^[a-zA-Z0-9_-]{1,50}$/)) {
+      res.status(400).json({ error: "Invalid taxonId." });
+      return;
+    }
     let name = await getName(taxonId, "", true);
     res.status(200).json(name);
   } catch (error) {
EOF
@@ -1955,6 +1955,11 @@
app.get("/cachetaxon/id/*", cacheLimiter, authenticateAdminToken, async (req, res) => {
try {
let taxonId = decodeURI(req.originalUrl.replace("/cachetaxon/id/", ""));
// Only allow strictly alphanumeric (plus underscore/dash), 1-50 chars -- adjust as needed for real taxon IDs
if (!taxonId.match(/^[a-zA-Z0-9_-]{1,50}$/)) {
res.status(400).json({ error: "Invalid taxonId." });
return;
}
let name = await getName(taxonId, "", true);
res.status(200).json(name);
} catch (error) {
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
})
.catch((error) => {
console.log(`Failed to get GBIF names for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To prevent user-controlled input from being interpreted as a format string, do not embed tainted input directly within template literals or string concatenations that are intended as the format string argument in logging functions. Instead, use a static format string with a placeholder (such as %s) and pass the potentially unsafe value as a separate argument.

Specifically, for the problematic log call at line 901:

Edit:

  • Change console.log(Failed to get GBIF names for ${nameResult.scientificName}:, error.message);
  • To: console.log('Failed to get GBIF names for %s:', nameResult.scientificName, error.message);

This ensures that nameResult.scientificName is treated as a value rather than a formatting string.

Only line 901 requires changing in the code you've been shown; there are no required import changes or new method/variable definitions.

Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -898,7 +898,7 @@
             }
           })
           .catch((error) => {
-            console.log(`Failed to get GBIF names for ${nameResult.scientificName}:`, error.message);
+            console.log('Failed to get GBIF names for %s:', nameResult.scientificName, error.message);
             return null;
           });
 
EOF
@@ -898,7 +898,7 @@
}
})
.catch((error) => {
console.log(`Failed to get GBIF names for ${nameResult.scientificName}:`, error.message);
console.log('Failed to get GBIF names for %s:', nameResult.scientificName, error.message);
return null;
});

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
}
} catch (error) {
console.log(`Error fetching GBIF names for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To fix this problem, we need to ensure that any user-provided value is not interpreted as a format string by console.log. The best practice is to use a static format string with explicit %s substitution patterns, and pass tainted/user-supplied data as additional parameters to avoid format string confusion. In this particular case, the correct fix is to change the template literal used as the first argument (`Error fetching GBIF names for ${nameResult.scientificName}:`) to a static string with a %s substitution, so the log call becomes:

console.log("Error fetching GBIF names for %s:", nameResult.scientificName, error.message);

as opposed to pushing user data directly into the format string. There is no need to import any new libraries to implement this change. No additional methods or definitions are required.

Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -932,7 +932,7 @@
           }
         }
       } catch (error) {
-        console.log(`Error fetching GBIF names for ${nameResult.scientificName}:`, error.message);
+        console.log("Error fetching GBIF names for %s:", nameResult.scientificName, error.message);
       }
     }
 
EOF
@@ -932,7 +932,7 @@
}
}
} catch (error) {
console.log(`Error fetching GBIF names for ${nameResult.scientificName}:`, error.message);
console.log("Error fetching GBIF names for %s:", nameResult.scientificName, error.message);
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
})
.catch((error) => {
console.log(`Failed to get Swedish name for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To fix this vulnerability, adjust the logging so that the template string containing the user-supplied value isn't directly passed as a format string to console.log. Instead, use a constant format string with a %s (string) placeholder, and then pass the potentially untrusted value as a separate argument. Specifically, on line 952 of server.js, change this:

console.log(`Failed to get Swedish name for ${nameResult.scientificName}:`, error.message);

to:

console.log("Failed to get Swedish name for %s:", nameResult.scientificName, error.message);

This ensures that user-controlled input does not influence the format string passed to console.log, addressing CodeQL's concern. No new imports or methods are needed; just a simple code edit.

Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -949,7 +949,7 @@
             }
           })
           .catch((error) => {
-            console.log(`Failed to get Swedish name for ${nameResult.scientificName}:`, error.message);
+            console.log("Failed to get Swedish name for %s:", nameResult.scientificName, error.message);
             return null;
           });
 
EOF
@@ -949,7 +949,7 @@
}
})
.catch((error) => {
console.log(`Failed to get Swedish name for ${nameResult.scientificName}:`, error.message);
console.log("Failed to get Swedish name for %s:", nameResult.scientificName, error.message);
return null;
});

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
})
.catch((error) => {
console.log(`Failed to get Wikipedia names for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To mitigate this format string vulnerability, we should avoid placing untrusted data directly into a format string supplied to console.log when additional arguments are provided. The best practice is to use a format specifier (%s) in the log string and pass untrusted data as subsequent arguments, rather than embedding it directly within the template literal. This fixes the issue by ensuring console.log treats the user data as a simple string argument rather than part of a potentially interpreted format string.

Specifically, in server.js at line 986 (and line 1002, which repeats the same pattern), the log statements of the form console.log(`Failed to get Wikipedia names for ${nameResult.scientificName}:`, error.message); and console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message); should be changed to use a format string like "Failed to get Wikipedia names for %s: %s" and pass the relevant variables as arguments. Only these lines need modification.

No additional imports or library methods are necessary, as this is about changing format string usage.

Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -983,7 +983,7 @@
             }
           })
           .catch((error) => {
-            console.log(`Failed to get Wikipedia names for ${nameResult.scientificName}:`, error.message);
+            console.log("Failed to get Wikipedia names for %s: %s", nameResult.scientificName, error.message);
             return null;
           });
 
@@ -999,7 +999,7 @@
           }
         }
       } catch (error) {
-        console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);
+        console.log("Error fetching Wikipedia names for %s: %s", nameResult.scientificName, error.message);
       }
     }
 
EOF
@@ -983,7 +983,7 @@
}
})
.catch((error) => {
console.log(`Failed to get Wikipedia names for ${nameResult.scientificName}:`, error.message);
console.log("Failed to get Wikipedia names for %s: %s", nameResult.scientificName, error.message);
return null;
});

@@ -999,7 +999,7 @@
}
}
} catch (error) {
console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);
console.log("Error fetching Wikipedia names for %s: %s", nameResult.scientificName, error.message);
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
}
} catch (error) {
console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To fix this issue, we must ensure that user-controlled data (nameResult.scientificName) is never used directly as part of a format string in the first argument of console.log when additional arguments are supplied.
Instead, use the %s specifier in the literal format string and pass the untrusted data as a separate argument.
In server.js, at line 1002, replace:

console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);

with:

console.log('Error fetching Wikipedia names for %s:', nameResult.scientificName, error.message);

No additional imports or new methods are needed; simply modify how the console.log call is structured.


Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -999,7 +999,7 @@
           }
         }
       } catch (error) {
-        console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);
+        console.log('Error fetching Wikipedia names for %s:', nameResult.scientificName, error.message);
       }
     }
 
EOF
@@ -999,7 +999,7 @@
}
}
} catch (error) {
console.log(`Error fetching Wikipedia names for ${nameResult.scientificName}:`, error.message);
console.log('Error fetching Wikipedia names for %s:', nameResult.scientificName, error.message);
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
})
.catch((error) => {
console.log(`Failed to get iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To address the externally-controlled format string issue, change any logging statements that interpolate untrusted data (here, nameResult.scientificName, which may be derived from req.originalUrl) directly into the log message using a template string. Instead, use a format specifier, such as %s, in the message string and pass the untrusted value as a second argument to console.log. This ensures that any format specifiers appearing in user-provided data are printed literally and do not affect logging behaviour. Make the same adjustment in all similar logging statements involving user input within the given file and regions (here, lines 1021 and 1037).

No new imports or methods are required.


Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -1018,7 +1018,7 @@
               }
             })
             .catch((error) => {
-              console.log(`Failed to get iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
+              console.log('Failed to get iNaturalist %s name for %s:', lang, nameResult.scientificName, error.message);
               return null;
             });
 
@@ -1034,7 +1034,7 @@
             }
           }
         } catch (error) {
-          console.log(`Error fetching iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
+          console.log('Error fetching iNaturalist %s name for %s:', lang, nameResult.scientificName, error.message);
         }
       }
     }
EOF
@@ -1018,7 +1018,7 @@
}
})
.catch((error) => {
console.log(`Failed to get iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
console.log('Failed to get iNaturalist %s name for %s:', lang, nameResult.scientificName, error.message);
return null;
});

@@ -1034,7 +1034,7 @@
}
}
} catch (error) {
console.log(`Error fetching iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
console.log('Error fetching iNaturalist %s name for %s:', lang, nameResult.scientificName, error.message);
}
}
}
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
}
}
} catch (error) {
console.log(`Error fetching iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.

Copilot Autofix

AI 8 months ago

To fix this issue, ensure that untrusted values (such as nameResult.scientificName, which ultimately come from user input) are never directly interpolated into format strings used as the first argument of console.log or similar functions, especially when additional arguments are passed. The cleanest solution is to use a format string with the %s substitution specifier and provide all arguments separately, so that any untrusted input will be safely rendered as a string rather than interpreted for additional formatting or placeholder replacement.

Edit line 1037 in server.js so that the message passed to console.log uses a fixed format string such as Error fetching iNaturalist %s name for %s: %s, and provides lang, nameResult.scientificName, and error.message as separate arguments.

No additional libraries or major code structure changes are required—just a single code line change.


Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -1034,7 +1034,7 @@
             }
           }
         } catch (error) {
-          console.log(`Error fetching iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
+          console.log('Error fetching iNaturalist %s name for %s: %s', lang, nameResult.scientificName, error.message);
         }
       }
     }
EOF
@@ -1034,7 +1034,7 @@
}
}
} catch (error) {
console.log(`Error fetching iNaturalist ${lang} name for ${nameResult.scientificName}:`, error.message);
console.log('Error fetching iNaturalist %s name for %s: %s', lang, nameResult.scientificName, error.message);
}
}
}
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment thread server.js
Comment on lines +2120 to +2128
headers: {
'Authorization': req.headers['authorization']
},
timeout: 10000
}
);
return res.status(200).json(testResponse.data);
} catch (error) {
writeErrorLog(`Failed to fetch image from test server`, error);

Check failure

Code scanning / CodeQL

Server-side request forgery Critical

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

Copilot Autofix

AI 8 months ago

To address the SSRF risk, user input used in the building of remote request URLs must be strictly validated. For this code, we need to ensure that id and password are well-formed and do not contain dangerous characters (e.g., /, \, ?, #, or ..). The best approach is to whitelist allowed values or at minimum reject possible traversal or injection attempts.

Since only a single code snippet is shown, add logic before using id and password to: (1) Validate id as a simple string (letters, digits, dashes/underscores only). (2) Validate password similarly (assuming it isn't meant to be arbitrary). If validation fails, return an error response and do not make the remote request.

Place this validation right after the assignment of id and password, before use in the remote request.


Suggested changeset 1
server.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server.js b/server.js
--- a/server.js
+++ b/server.js
@@ -2098,6 +2098,13 @@
   const password = urlParam.split("&")[1].toString();
   const id = urlParam.split("&")[0];
 
+  // SSRF protection: validate id and password
+  const validId = /^[a-zA-Z0-9_\-]+$/.test(id);
+  const validPassword = typeof password === 'string' && password.length < 256 && !password.includes('&');
+  if (!validId || !validPassword) {
+    return res.status(400).json({ error: "Invalid parameters." });
+  }
+
   fs.readdir(`${uploadsdir}/`, async (err, files) => {
     let image_list = [];
 
EOF
@@ -2098,6 +2098,13 @@
const password = urlParam.split("&")[1].toString();
const id = urlParam.split("&")[0];

// SSRF protection: validate id and password
const validId = /^[a-zA-Z0-9_\-]+$/.test(id);
const validPassword = typeof password === 'string' && password.length < 256 && !password.includes('&');
if (!validId || !validPassword) {
return res.status(400).json({ error: "Invalid parameters." });
}

fs.readdir(`${uploadsdir}/`, async (err, files) => {
let image_list = [];

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@WouterKoch
WouterKoch merged commit 309224b into master Dec 2, 2025
6 of 7 checks passed
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.

3 participants