security: Add Discord mention sanitization to prevent abuse

This commit is contained in:
2026-01-02 16:18:16 +01:00
parent c56cd0b6b0
commit 56d8e431bd
3 changed files with 79 additions and 7 deletions

View File

@@ -22,6 +22,23 @@ function isRateLimited(ip) {
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
module.exports = async function handler(req, res) {
// CORS headers
@@ -59,22 +76,29 @@ module.exports = async function handler(req, res) {
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
const embed = {
title: '🔴 Bot Error Report',
description: `\`\`\`\n${String(payload.error).slice(0, 1900)}\n\`\`\``,
description: `\`\`\`\n${sanitizedError.slice(0, 1900)}\n\`\`\``,
color: 0xdc143c,
fields: [
{ name: 'Version', value: String(payload.context?.version || 'unknown'), inline: true },
{ name: 'Platform', value: String(payload.context?.platform || 'unknown'), inline: true },
{ name: 'Node', value: String(payload.context?.nodeVersion || 'unknown'), inline: true }
{ name: 'Version', value: sanitizedVersion, inline: true },
{ name: 'Platform', value: sanitizedPlatform, inline: true },
{ name: 'Node', value: sanitizedNode, inline: true }
],
timestamp: new Date().toISOString(),
footer: { text: 'Community Error Reporting' }
}
if (payload.stack) {
const stackLines = String(payload.stack).split('\n').slice(0, 15).join('\n')
if (sanitizedStack) {
const stackLines = sanitizedStack.split('\n').slice(0, 15).join('\n')
embed.fields.push({
name: 'Stack Trace',
value: `\`\`\`\n${stackLines.slice(0, 1000)}\n\`\`\``,

View File

@@ -28,7 +28,12 @@ const SANITIZE_PATTERNS: Array<[RegExp, string]> = [
[/[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*/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[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 {

43
test-security.ps1 Normal file
View 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 ""