From e0aa10945d0a06f0e19ea005322ea2f652118fc5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 12:05:43 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Fix=20Information=20Exposure=20via=20RPC=20Errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced raw RPC `err.message` output with generic error responses in Discord replies across all tipper modules. Added `.catch` for message deletions to prevent unhandled promise rejections. Actual errors are now logged internally via `console.error`. Co-authored-by: DerUntote <8378077+DerUntote@users.noreply.github.com> --- .jules/sentinel.md | 5 +++++ bot/modules/dogeTipper.js | 24 +++++++++++++++++++++--- bot/modules/exampleTipper.js | 12 +++++++++--- bot/modules/ftcTipper.js | 24 +++++++++++++++++++++--- bot/modules/lbcTipper.js | 24 +++++++++++++++++++++--- bot/modules/protonTipper.js | 24 +++++++++++++++++++++--- bot/modules/pxcTipper.js | 24 +++++++++++++++++++++--- bot/modules/rvnTipper.js | 24 +++++++++++++++++++++--- bot/modules/ufoTipper.js | 24 +++++++++++++++++++++--- bot/modules/vtlTipper.js | 24 +++++++++++++++++++++--- 10 files changed, 182 insertions(+), 27 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..d4c3367 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,5 @@ + +## 2024-06-26 - [MEDIUM] Fix Information Exposure via RPC Errors +**Vulnerability:** The application was passing unhandled RPC connection errors directly to users via Discord messages (`message.reply(err.message)`). +**Learning:** This could leak internal daemon/network information or server configurations if an attacker forced an error state or an unexpected network exception occurred. Discord message limitations must also be considered; raw stack traces can lead to unintended command failures. +**Prevention:** Avoid passing raw `err.message` objects from backend/RPC providers to untrusted clients. Catch and log the detailed errors internally (`console.error(err)`), and provide a safe, generic fallback message to the user (`"An error occurred..."`). diff --git a/bot/modules/dogeTipper.js b/bot/modules/dogeTipper.js index 54258df..9060bdf 100644 --- a/bot/modules/dogeTipper.js +++ b/bot/modules/dogeTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } doge.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendDOGE(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { doge.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendDOGE(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/exampleTipper.js b/bot/modules/exampleTipper.js index 25be559..7b8b440 100644 --- a/bot/modules/exampleTipper.js +++ b/bot/modules/exampleTipper.js @@ -143,7 +143,9 @@ function doWithdraw(message, tipper, words, helpmsg) { } ltc.sendFrom(tipper, address, Number(amount), function(err, txId) { if (err) { - message.reply(err.message).then(message => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message.reply("An error occurred during the transaction. Please try again later.").then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({embed:{ title: '**:outbox_tray::money_with_wings::moneybag:Litecoin (LTC) Transaction Completed!:moneybag::money_with_wings::outbox_tray:**', @@ -228,11 +230,15 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendLTC(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function(err, address) { if (err) { - message.reply(err.message).then(message => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message.reply("An error occurred during the transaction. Please try again later.").then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { ltc.sendFrom(tipper, address, Number(amount), 1, null, null, function(err, txId) { if (err) { - message.reply(err.message).then(message => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message.reply("An error occurred during the transaction. Please try again later.").then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient) // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/ftcTipper.js b/bot/modules/ftcTipper.js index 22bb0b9..006333e 100644 --- a/bot/modules/ftcTipper.js +++ b/bot/modules/ftcTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } ftc.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendFTC(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { ftc.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendFTC(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/lbcTipper.js b/bot/modules/lbcTipper.js index 09ff576..82fb5c9 100644 --- a/bot/modules/lbcTipper.js +++ b/bot/modules/lbcTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } lbc.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendLBC(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { lbc.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendLBC(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/protonTipper.js b/bot/modules/protonTipper.js index 53da2cd..ee78fb4 100644 --- a/bot/modules/protonTipper.js +++ b/bot/modules/protonTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } proton.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendPROTON(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { proton.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendPROTON(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/pxcTipper.js b/bot/modules/pxcTipper.js index db95dc4..cf34a71 100644 --- a/bot/modules/pxcTipper.js +++ b/bot/modules/pxcTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } pxc.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendPXC(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { pxc.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendPXC(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/rvnTipper.js b/bot/modules/rvnTipper.js index 814abc4..9d89050 100644 --- a/bot/modules/rvnTipper.js +++ b/bot/modules/rvnTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } rvn.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendRVN(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { rvn.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendRVN(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/ufoTipper.js b/bot/modules/ufoTipper.js index 74c1cd5..156be7c 100644 --- a/bot/modules/ufoTipper.js +++ b/bot/modules/ufoTipper.js @@ -162,7 +162,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } ufo.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -267,7 +273,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendUFO(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { ufo.sendFrom( tipper, @@ -278,7 +290,13 @@ function sendUFO(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search; diff --git a/bot/modules/vtlTipper.js b/bot/modules/vtlTipper.js index 040a3fa..0585bb7 100644 --- a/bot/modules/vtlTipper.js +++ b/bot/modules/vtlTipper.js @@ -158,7 +158,13 @@ function doWithdraw(message, tipper, words, helpmsg) { } vtl.sendFrom(tipper, address, Number(amount), function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { message.channel.send({ embed: { @@ -263,7 +269,13 @@ function doTip(bot, message, tipper, words, helpmsg) { function sendVTL(bot, message, tipper, recipient, amount, privacyFlag) { getAddress(recipient.toString(), function (err, address) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { vtl.sendFrom( tipper, @@ -274,7 +286,13 @@ function sendVTL(bot, message, tipper, recipient, amount, privacyFlag) { null, function (err, txId) { if (err) { - message.reply(err.message).then((message) => message.delete(10000)); + console.error(err); + // 🛡️ Sentinel: Securely log internal error + message + .reply( + 'An error occurred during the transaction. Please try again later.', + ) + .then((msg) => msg.delete(10000).catch(() => {})); // 🛡️ Sentinel: Avoid leaking RPC error details } else { if (privacyFlag) { let userProfile = message.guild.members.get(recipient); // ⚡ Bolt: O(1) direct ID lookup vs O(N) linear search;