mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-10 17:26:17 +00:00
security: Add Discord mention sanitization to prevent abuse
This commit is contained in:
@@ -22,6 +22,23 @@ function isRateLimited(ip) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize text to prevent Discord mention abuse
|
||||||
|
function sanitizeDiscordText(text) {
|
||||||
|
if (!text) return ''
|
||||||
|
|
||||||
|
return String(text)
|
||||||
|
// Remove @everyone and @here mentions
|
||||||
|
.replace(/@(everyone|here)/gi, '@\u200b$1')
|
||||||
|
// Remove user mentions <@123456>
|
||||||
|
.replace(/<@!?(\d+)>/g, '@user')
|
||||||
|
// Remove role mentions <@&123456>
|
||||||
|
.replace(/<@&(\d+)>/g, '@role')
|
||||||
|
// Remove channel mentions <#123456>
|
||||||
|
.replace(/<#(\d+)>/g, '#channel')
|
||||||
|
// Limit length
|
||||||
|
.slice(0, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
// Vercel serverless handler
|
// Vercel serverless handler
|
||||||
module.exports = async function handler(req, res) {
|
module.exports = async function handler(req, res) {
|
||||||
// CORS headers
|
// CORS headers
|
||||||
@@ -59,22 +76,29 @@ module.exports = async function handler(req, res) {
|
|||||||
return res.status(400).json({ error: 'Invalid payload: missing error field' })
|
return res.status(400).json({ error: 'Invalid payload: missing error field' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize all text fields to prevent Discord mention abuse
|
||||||
|
const sanitizedError = sanitizeDiscordText(payload.error)
|
||||||
|
const sanitizedStack = payload.stack ? sanitizeDiscordText(payload.stack) : null
|
||||||
|
const sanitizedVersion = sanitizeDiscordText(payload.context?.version || 'unknown')
|
||||||
|
const sanitizedPlatform = sanitizeDiscordText(payload.context?.platform || 'unknown')
|
||||||
|
const sanitizedNode = sanitizeDiscordText(payload.context?.nodeVersion || 'unknown')
|
||||||
|
|
||||||
// Build Discord embed
|
// Build Discord embed
|
||||||
const embed = {
|
const embed = {
|
||||||
title: '🔴 Bot Error Report',
|
title: '🔴 Bot Error Report',
|
||||||
description: `\`\`\`\n${String(payload.error).slice(0, 1900)}\n\`\`\``,
|
description: `\`\`\`\n${sanitizedError.slice(0, 1900)}\n\`\`\``,
|
||||||
color: 0xdc143c,
|
color: 0xdc143c,
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'Version', value: String(payload.context?.version || 'unknown'), inline: true },
|
{ name: 'Version', value: sanitizedVersion, inline: true },
|
||||||
{ name: 'Platform', value: String(payload.context?.platform || 'unknown'), inline: true },
|
{ name: 'Platform', value: sanitizedPlatform, inline: true },
|
||||||
{ name: 'Node', value: String(payload.context?.nodeVersion || 'unknown'), inline: true }
|
{ name: 'Node', value: sanitizedNode, inline: true }
|
||||||
],
|
],
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
footer: { text: 'Community Error Reporting' }
|
footer: { text: 'Community Error Reporting' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.stack) {
|
if (sanitizedStack) {
|
||||||
const stackLines = String(payload.stack).split('\n').slice(0, 15).join('\n')
|
const stackLines = sanitizedStack.split('\n').slice(0, 15).join('\n')
|
||||||
embed.fields.push({
|
embed.fields.push({
|
||||||
name: 'Stack Trace',
|
name: 'Stack Trace',
|
||||||
value: `\`\`\`\n${stackLines.slice(0, 1000)}\n\`\`\``,
|
value: `\`\`\`\n${stackLines.slice(0, 1000)}\n\`\`\``,
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ const SANITIZE_PATTERNS: Array<[RegExp, string]> = [
|
|||||||
[/[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*/g, '[PATH_REDACTED]'],
|
[/[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*/g, '[PATH_REDACTED]'],
|
||||||
[/\/(?:home|Users)\/[^/\s]+(?:\/[^/\s]+)*/g, '[PATH_REDACTED]'],
|
[/\/(?:home|Users)\/[^/\s]+(?:\/[^/\s]+)*/g, '[PATH_REDACTED]'],
|
||||||
[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g, '[IP_REDACTED]'],
|
[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g, '[IP_REDACTED]'],
|
||||||
[/\b[A-Za-z0-9_-]{20,}\b/g, '[TOKEN_REDACTED]']
|
[/\b[A-Za-z0-9_-]{20,}\b/g, '[TOKEN_REDACTED]'],
|
||||||
|
// Discord mention sanitization (prevent @everyone, @here abuse)
|
||||||
|
[/@(everyone|here)/gi, '@\u200b$1'], // Zero-width space breaks mentions
|
||||||
|
[/<@!?(\d+)>/g, '@user'], // User mentions
|
||||||
|
[/<@&(\d+)>/g, '@role'], // Role mentions
|
||||||
|
[/<#(\d+)>/g, '#channel'] // Channel mentions
|
||||||
]
|
]
|
||||||
|
|
||||||
function sanitizeSensitiveText(text: string): string {
|
function sanitizeSensitiveText(text: string): string {
|
||||||
|
|||||||
43
test-security.ps1
Normal file
43
test-security.ps1
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Test Error Reporting Security
|
||||||
|
|
||||||
|
Write-Host "Testing Discord mention sanitization..." -ForegroundColor Cyan
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
$apiUrl = "https://light-rewards-bot.vercel.app/api/report-error"
|
||||||
|
|
||||||
|
# Test avec des mentions Discord malveillantes
|
||||||
|
$payload = @{
|
||||||
|
error = "Test @everyone @here error with <@123456789> user mention"
|
||||||
|
stack = "at testFunction <@&987654321> role mention`n at main <#555555555> channel"
|
||||||
|
context = @{
|
||||||
|
version = "3.5.6"
|
||||||
|
platform = "win32"
|
||||||
|
arch = "x64"
|
||||||
|
nodeVersion = "v22.0.0"
|
||||||
|
timestamp = [DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
|
||||||
|
botMode = "SECURITY_TEST"
|
||||||
|
}
|
||||||
|
} | ConvertTo-Json -Depth 10
|
||||||
|
|
||||||
|
Write-Host "Payload with malicious mentions:" -ForegroundColor Yellow
|
||||||
|
Write-Host $payload -ForegroundColor Gray
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Invoke-RestMethod -Uri $apiUrl -Method Post -Body $payload -ContentType "application/json" -TimeoutSec 15
|
||||||
|
|
||||||
|
Write-Host "SUCCESS - Sanitization applied!" -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Check Discord - mentions should be neutralized:" -ForegroundColor Cyan
|
||||||
|
Write-Host " @everyone -> @<zero-width>everyone" -ForegroundColor Gray
|
||||||
|
Write-Host " @here -> @<zero-width>here" -ForegroundColor Gray
|
||||||
|
Write-Host " <@123456789> -> @user" -ForegroundColor Gray
|
||||||
|
Write-Host " <@&987654321> -> @role" -ForegroundColor Gray
|
||||||
|
Write-Host " <#555555555> -> #channel" -ForegroundColor Gray
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Host "FAILED!" -ForegroundColor Red
|
||||||
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
Reference in New Issue
Block a user