Skip to content

Commit 0b065c3

Browse files
committed
add: Added more secruity checks to eval command for sensitive data
1 parent c2d2598 commit 0b065c3

File tree

1 file changed

+175
-64
lines changed

1 file changed

+175
-64
lines changed
Lines changed: 175 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { Events, EmbedBuilder, MessageFlags } = require('discord.js');
1+
const { Events, EmbedBuilder, MessageFlags, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
22
const fs = require('fs');
33
const path = require('path');
44
const { color, getTimestamp } = require('../../utils/loggingEffects.js');
@@ -17,76 +17,187 @@ module.exports = {
1717
return await interaction.reply({ content: `${client.config.ownerOnlyCommand}`, flags: MessageFlags.Ephemeral,});
1818
}
1919

20-
try {
21-
let evaled;
22-
const logOutput = [];
23-
const originalLog = console.log;
24-
const logFilePath = path.join(__dirname, '../../logs/evalLogs.txt');
25-
const timestamp = getTimestamp();
26-
27-
fs.appendFileSync(logFilePath, `[${timestamp}] [EVAL_COMMAND_INPUT] Eval command input: ${code}\n`);
28-
29-
console.log = function(...args) {
30-
const customContent = `${color.purple}[${timestamp}]${color.reset} [EVAL_COMMAND_LOG] Eval command has logged:`;
31-
const modifiedArgs = args.map(arg => `${customContent} ${arg}`);
32-
33-
originalLog.apply(console, modifiedArgs);
34-
logOutput.push(...args);
35-
};
36-
37-
if (code.includes('await')) {
38-
evaled = await eval(`(async () => { return ${code}; })()`);
39-
} else {
40-
evaled = eval(code);
41-
}
42-
43-
console.log = originalLog;
44-
45-
if (typeof evaled !== 'string') {
46-
evaled = require('util').inspect(evaled);
20+
const sensitivePatterns = [
21+
/process\.env\.token/i,
22+
/client\.token/i,
23+
/process\.env\.mongodb/i,
24+
/mongodb:\/\//i,
25+
/mongo_uri/i,
26+
/mongodburi/i
27+
];
28+
29+
let hasSensitiveInfo = false;
30+
let detectedPattern = '';
31+
32+
for (const pattern of sensitivePatterns) {
33+
if (pattern.test(code)) {
34+
hasSensitiveInfo = true;
35+
detectedPattern = pattern.toString();
36+
break;
4737
}
38+
}
39+
40+
if (hasSensitiveInfo) {
41+
const warningEmbed = new EmbedBuilder()
42+
.setTitle('⚠️ Security Warning')
43+
.setDescription('You are attempting to access sensitive information that could potentially expose your bot\'s security credentials.')
44+
.addFields(
45+
{ name: 'Detected Sensitive Pattern', value: `\`${detectedPattern}\`` },
46+
{ name: 'Security Risk', value: 'Exposing tokens or connection strings can lead to unauthorized access to your bot and databases.' },
47+
{ name: 'Options', value: 'Click "Continue" to proceed with execution anyway, or "Cancel" to abort.' }
48+
)
49+
.setColor('#FF0000')
50+
.setTimestamp()
51+
.setFooter({ text: 'Security Protection', iconURL: client.user.avatarURL() });
52+
53+
const row = new ActionRowBuilder()
54+
.addComponents(
55+
new ButtonBuilder()
56+
.setCustomId('eval_continue')
57+
.setLabel('Continue')
58+
.setStyle(ButtonStyle.Danger),
59+
new ButtonBuilder()
60+
.setCustomId('eval_cancel')
61+
.setLabel('Cancel')
62+
.setStyle(ButtonStyle.Secondary)
63+
);
64+
65+
const response = await interaction.reply({
66+
embeds: [warningEmbed],
67+
components: [row],
68+
flags: MessageFlags.Ephemeral,
69+
fetchReply: true
70+
});
71+
72+
const collector = response.createMessageComponentCollector({
73+
time: 30000,
74+
max: 1
75+
});
76+
77+
collector.on('collect', async i => {
78+
if (i.user.id !== interaction.user.id) {
79+
return i.reply({
80+
content: 'Only the command user can interact with these buttons.',
81+
flags: MessageFlags.Ephemeral
82+
});
83+
}
84+
85+
if (i.customId === 'eval_cancel') {
86+
await i.update({
87+
content: 'Eval command cancelled.',
88+
embeds: [],
89+
components: []
90+
});
91+
return;
92+
}
93+
94+
if (i.customId === 'eval_continue') {
95+
await i.update({
96+
content: 'Proceeding with evaluation...',
97+
embeds: [],
98+
components: []
99+
});
100+
101+
await processEvaluation(code, ephemeralChoice, interaction, client);
102+
}
103+
});
104+
105+
collector.on('end', async collected => {
106+
if (collected.size === 0) {
107+
await interaction.editReply({
108+
content: 'Eval command timed out. Please try again.',
109+
embeds: [],
110+
components: []
111+
});
112+
}
113+
});
114+
115+
return;
116+
}
48117

49-
if (logOutput.length > 0) {
50-
evaled = logOutput.join('\n') + (evaled !== 'undefined' ? `\n${evaled}` : '');
51-
} else if (evaled === 'undefined') {
52-
evaled = 'undefined';
53-
}
118+
await processEvaluation(code, ephemeralChoice, interaction, client);
119+
}
120+
}
121+
}
122+
}
123+
124+
async function processEvaluation(code, ephemeralChoice, interaction, client) {
125+
try {
126+
let evaled;
127+
const logOutput = [];
128+
const originalLog = console.log;
129+
const logFilePath = path.join(__dirname, '../../logs/evalLogs.txt');
130+
const timestamp = getTimestamp();
131+
132+
fs.appendFileSync(logFilePath, `[${timestamp}] [EVAL_COMMAND_INPUT] Eval command input: ${code}\n`);
133+
134+
console.log = function(...args) {
135+
const customContent = `${color.purple}[${timestamp}]${color.reset} [EVAL_COMMAND_LOG] Eval command has logged:`;
136+
const modifiedArgs = args.map(arg => `${customContent} ${arg}`);
137+
138+
originalLog.apply(console, modifiedArgs);
139+
logOutput.push(...args);
140+
};
141+
142+
if (code.includes('await')) {
143+
evaled = await eval(`(async () => { return ${code}; })()`);
144+
} else {
145+
evaled = eval(code);
146+
}
54147

55-
const channelID = client.config.evalLogsChannel;
56-
if (!channelID) {
57-
console.logs.error(`No eval logs channel ID provided. Please provide a valid channel ID in the config.js file.`);
58-
return;
59-
}
148+
console.log = originalLog;
60149

61-
const channel = await client.channels.cache.get(channelID);
150+
if (typeof evaled !== 'string') {
151+
evaled = require('util').inspect(evaled);
152+
}
62153

63-
const originalSend = channel.send;
154+
if (logOutput.length > 0) {
155+
evaled = logOutput.join('\n') + (evaled !== 'undefined' ? `\n${evaled}` : '');
156+
} else if (evaled === 'undefined') {
157+
evaled = 'undefined';
158+
}
64159

65-
channel.send = function(content, options = {}) {
66-
options.ephemeral = false;
67-
return originalSend.call(this, content, options);
68-
};
160+
const channelID = client.config.evalLogsChannel;
161+
if (!channelID) {
162+
console.error(`No eval logs channel ID provided. Please provide a valid channel ID in the config.js file.`);
163+
return;
164+
}
69165

70-
const embed = new EmbedBuilder()
71-
.setAuthor({ name: `Eval Code ${client.config.devBy}`, iconURL: client.user.avatarURL() })
72-
.setTitle(`${client.user.username} Evaluated JavaScript Code ${client.config.arrowEmoji}`)
73-
.setDescription(`__Code has been executed successfully!__`)
74-
.addFields(
75-
{ name: '📥 Input', value: `\`\`\`js\n${code}\n\`\`\`` },
76-
{ name: '📤 Output', value: `\`\`\`js\n${evaled}\n\`\`\`` }
77-
)
78-
.setColor(client.config.embedDev)
79-
.setTimestamp()
80-
.setFooter({ text: `Executed By ${interaction.user.username}`, iconURL: interaction.user.avatarURL() });
81-
82-
await interaction.reply({ embeds: [embed], ephemeral: ephemeralChoice });
83-
await channel.send({ embeds: [embed] });
84-
fs.appendFileSync(logFilePath, `[${timestamp}] [EVAL_COMMAND_OUTPUT] Eval command output: ${evaled}\n`);
85-
} catch (error) {
86-
console.error(error);
87-
await interaction.reply({ content: `\`\`\`js\n${error}\n\`\`\``, flags: MessageFlags.Ephemeral });
88-
}
89-
}
166+
const channel = await client.channels.cache.get(channelID);
167+
168+
const originalSend = channel.send;
169+
170+
channel.send = function(content, options = {}) {
171+
options.ephemeral = false;
172+
return originalSend.call(this, content, options);
173+
};
174+
175+
const embed = new EmbedBuilder()
176+
.setAuthor({ name: `Eval Code ${client.config.devBy}`, iconURL: client.user.avatarURL() })
177+
.setTitle(`${client.user.username} Evaluated JavaScript Code ${client.config.arrowEmoji}`)
178+
.setDescription(`__Code has been executed successfully!__`)
179+
.addFields(
180+
{ name: '📥 Input', value: `\`\`\`js\n${code}\n\`\`\`` },
181+
{ name: '📤 Output', value: `\`\`\`js\n${evaled}\n\`\`\`` }
182+
)
183+
.setColor(client.config.embedDev)
184+
.setTimestamp()
185+
.setFooter({ text: `Executed By ${interaction.user.username}`, iconURL: interaction.user.avatarURL() });
186+
187+
if (interaction.replied || interaction.deferred) {
188+
await interaction.editReply({ embeds: [embed], ephemeral: ephemeralChoice });
189+
} else {
190+
await interaction.reply({ embeds: [embed], ephemeral: ephemeralChoice });
191+
}
192+
193+
await channel.send({ embeds: [embed] });
194+
fs.appendFileSync(logFilePath, `[${timestamp}] [EVAL_COMMAND_OUTPUT] Eval command output: ${evaled}\n`);
195+
} catch (error) {
196+
console.error(error);
197+
if (interaction.replied || interaction.deferred) {
198+
await interaction.editReply({ content: `\`\`\`js\n${error}\n\`\`\``, flags: MessageFlags.Ephemeral });
199+
} else {
200+
await interaction.reply({ content: `\`\`\`js\n${error}\n\`\`\``, flags: MessageFlags.Ephemeral });
90201
}
91202
}
92203
}

0 commit comments

Comments
 (0)