feat: THE CREATOR god-tier character, bitcoin choreographies, omni-morph, cameos
- Guy Fawkes mask archetype with golden outline, bitcoin chest symbol, laptop, tier-gated effects - 12 custom bitcoin-themed choreographies (8 regular + 4 exclusive ultimates) - Omni-morph system: creator morphs into any of 80+ archetypes instead of cycling 3 - 6% per-round cameo in non-creator fights — drops golden ₿ gifts to fighters - Custom golden code rain entrance with persistent orbiting particles - pickChoreography: 50% ultimate chance (100% on crits), all tier ultimates + 4 exclusive - Server auto-assigns the_creator archetype on login/register for creator pubkey - FightViewer, payments, queue, orchestrator improvements Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
8a3480e5ab
commit
6d390f69b2
@@ -52,17 +52,32 @@ function emit(fightId: string, type: string, data: Record<string, unknown>) {
|
||||
// SSRF protection: block internal/private URLs
|
||||
function isAllowedWebhookUrl(url: string): boolean {
|
||||
try {
|
||||
if (typeof url !== 'string' || url.length > 2048) return false
|
||||
const parsed = new URL(url)
|
||||
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false
|
||||
const hostname = parsed.hostname.toLowerCase()
|
||||
if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1') return false
|
||||
// Localhost variants
|
||||
if (hostname === 'localhost' || hostname === '::1') return false
|
||||
if (hostname.startsWith('127.')) return false
|
||||
// IPv6-mapped IPv4 localhost
|
||||
if (hostname.startsWith('::ffff:127.')) return false
|
||||
// Private IPv4 ranges
|
||||
if (hostname.startsWith('10.')) return false
|
||||
if (hostname.startsWith('192.168.')) return false
|
||||
if (hostname.startsWith('172.')) {
|
||||
const second = parseInt(hostname.split('.')[1])
|
||||
if (second >= 16 && second <= 31) return false
|
||||
}
|
||||
if (hostname === '169.254.169.254') return false
|
||||
if (hostname.endsWith('.local') || hostname.endsWith('.internal')) return false
|
||||
// Link-local and metadata
|
||||
if (hostname.startsWith('169.254.')) return false
|
||||
// IPv6 private (fc00::/7)
|
||||
if (hostname.startsWith('fc') || hostname.startsWith('fd')) return false
|
||||
// IPv6 link-local (fe80::/10)
|
||||
if (hostname.startsWith('fe80')) return false
|
||||
// Reserved TLDs
|
||||
if (hostname.endsWith('.local') || hostname.endsWith('.internal') || hostname.endsWith('.localhost')) return false
|
||||
// Null byte injection
|
||||
if (hostname.includes('\0')) return false
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user