Fix command injection security issue
All checks were successful
CI / CI (push) Successful in 1m27s

Download using fetch instead of using curl command line. Can't trust
user input :)
This commit is contained in:
SileNce5k 2025-04-11 09:20:44 +02:00
parent 44df923ce9
commit 7dc9be5598
Signed by: SileNce
GPG key ID: B0A142BB4291B204

View file

@ -1,6 +1,8 @@
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { writeFile } = require('node:fs/promises')
const { Readable } = require('node:stream')
module.exports = { module.exports = {
@ -21,10 +23,12 @@ module.exports = {
url = args[0]; url = args[0];
}else if(message.reference){ }else if(message.reference){
let referencedMessage = await message.fetchReference(); let referencedMessage = await message.fetchReference();
if(referencedMessage.attachments.size > 0) if(referencedMessage.attachments.size > 0){
url = await referencedMessage.attachments.first().url; url = await referencedMessage.attachments.first().url;
}
else { else {
message.channel.send("The message you replied to doesn't have any attachments."); message.channel.send("The message you replied to doesn't have any attachments.");
return;
} }
} }
else { else {
@ -34,12 +38,10 @@ module.exports = {
} }
// TODO: Download with correct extension. // TODO: Download with correct extension.
message.channel.sendTyping(); message.channel.sendTyping();
const curlCommand = `curl "${url}" -o ${directory}/input.png`; if(await this.downloadImage(url, path.resolve(directory, "input.png")) != 0){
message.channel.send("Something went wrong during the download.\nThe link might be unreachable for the bot or it's not an image.")
if (this.executeCommand(curlCommand).error === true) {
message.channel.send("Something went wrong during the download.\nTry again and if it keeps happening, contact the owner of the bot.")
fs.rmSync(`${directory}`, {recursive: true}) fs.rmSync(`${directory}`, {recursive: true})
return return;
} }
@ -71,6 +73,15 @@ module.exports = {
return { error: true }; return { error: true };
} }
return { error: false }; return { error: false };
},
// https://stackoverflow.com/a/77210219
async downloadImage(url, path) {
const res = await fetch(url);
if(!res.ok) return 1;
if(!res.headers.get('content-type').startsWith("image")) 2;
const stream = Readable.fromWeb(res.body)
await writeFile(path, stream);
return 0;
} }
} }