mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-07 04:50:57 +08:00
fix: prevent panics from unsafe type assertions in trading code + add request body limit
Security & Reliability: - Add requestBodyLimitMiddleware (1MB) to prevent OOM from oversized API payloads - Fix defer resp.Body.Close() inside loop in getPublicIPFromAPI (connection leak) - Add posFloat64/posString safe helpers for position map access Panic Prevention (critical for trading): - Convert 30+ unsafe type assertions (pos["key"].(type)) to safe comma-ok pattern across all exchange traders: OKX, Hyperliquid, Aster, Bybit, KuCoin, Gate, Bitget, Binance - Fix auto_trader_risk.go: drawdown monitor could panic and silently stop monitoring, leaving positions unprotected - Fix auto_trader_decision.go & auto_trader_loop.go: core trading loop position parsing now crash-proof - All trader/ code now has zero unsafe type assertions Frontend: - Fix config.ts: rejected promise cached forever on network error (never retries)
This commit is contained in:
@@ -36,6 +36,9 @@ func NewServer(traderManager *manager.TraderManager, st *store.Store, cryptoServ
|
||||
|
||||
router := gin.Default()
|
||||
|
||||
// Limit request body size to prevent OOM from oversized payloads (1MB default)
|
||||
router.Use(requestBodyLimitMiddleware(1 << 20))
|
||||
|
||||
// Enable CORS
|
||||
router.Use(corsMiddleware())
|
||||
|
||||
@@ -57,6 +60,17 @@ func NewServer(traderManager *manager.TraderManager, st *store.Store, cryptoServ
|
||||
return s
|
||||
}
|
||||
|
||||
// requestBodyLimitMiddleware limits the size of incoming request bodies.
|
||||
// Returns 413 Payload Too Large if the body exceeds maxBytes.
|
||||
func requestBodyLimitMiddleware(maxBytes int64) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.Request.Body != nil {
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxBytes)
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// corsMiddleware CORS middleware with configurable allowed origins.
|
||||
// Set CORS_ALLOWED_ORIGINS env var to a comma-separated list of origins
|
||||
// (e.g. "http://localhost:5173,https://nofx.example.com").
|
||||
@@ -445,25 +459,33 @@ func getPublicIPFromAPI() string {
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
resp, err := client.Get(service)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
ip := func() string {
|
||||
resp, err := client.Get(service)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return ""
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
body := make([]byte, 128)
|
||||
n, err := resp.Body.Read(body)
|
||||
if err != nil && err.Error() != "EOF" {
|
||||
continue
|
||||
return ""
|
||||
}
|
||||
|
||||
ip := strings.TrimSpace(string(body[:n]))
|
||||
parsedIP := net.ParseIP(ip)
|
||||
candidate := strings.TrimSpace(string(body[:n]))
|
||||
parsedIP := net.ParseIP(candidate)
|
||||
// Verify if it's a valid IPv4 address (not containing ":")
|
||||
if parsedIP != nil && parsedIP.To4() != nil {
|
||||
return ip
|
||||
return candidate
|
||||
}
|
||||
return ""
|
||||
}()
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user