mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
Address multiple vulnerabilities found during security review: - Remove unauthenticated POST /api/crypto/decrypt decryption oracle (route, handler, dead frontend helper) + regression test. Transport encryption is one-directional; the server never needs to decrypt arbitrary client payloads. - Redact secrets in config-update logs: handler_ai_model/handler_exchange logged %+v of decrypted requests, leaking API keys / secret keys / passphrases / private keys. Use named types shared with the log sanitizer so the masking can never drift again; extend masking to passphrase + lighter_api_key_private_key. - crypto: require a valid timestamp in DecryptPayload (a missing ts previously skipped replay protection entirely). - crypto: EncryptedString.Value() now fails closed instead of silently persisting plaintext secrets when encryption errors. - auth: per-IP token-bucket rate limiting on /login and /register against online brute-force; raise registration password minimum 6 -> 8; add dummy bcrypt compare on unknown-email login to close the user-enumeration timing channel. - IDOR: getTraderFromQuery no longer falls back to the global in-memory trader map; trader access is strictly scoped to the authenticated caller. - Bump Go 1.25.10 -> 1.25.11 to resolve reachable net/textproto and crypto/x509 stdlib advisories (govulncheck now reports 0 affecting vulnerabilities).
81 lines
2.4 KiB
Go
81 lines
2.4 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"nofx/config"
|
|
"nofx/crypto"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// CryptoHandler Encryption API handler
|
|
type CryptoHandler struct {
|
|
cryptoService *crypto.CryptoService
|
|
}
|
|
|
|
// NewCryptoHandler Creates encryption handler
|
|
func NewCryptoHandler(cryptoService *crypto.CryptoService) *CryptoHandler {
|
|
return &CryptoHandler{
|
|
cryptoService: cryptoService,
|
|
}
|
|
}
|
|
|
|
// ==================== Crypto Config Endpoint ====================
|
|
|
|
// HandleGetCryptoConfig Get crypto configuration
|
|
func (h *CryptoHandler) HandleGetCryptoConfig(c *gin.Context) {
|
|
cfg := config.Get()
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"transport_encryption": cfg.TransportEncryption,
|
|
})
|
|
}
|
|
|
|
// ==================== Public Key Endpoint ====================
|
|
|
|
// HandleGetPublicKey Get server public key
|
|
func (h *CryptoHandler) HandleGetPublicKey(c *gin.Context) {
|
|
cfg := config.Get()
|
|
if !cfg.TransportEncryption {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"public_key": "",
|
|
"algorithm": "",
|
|
"transport_encryption": false,
|
|
})
|
|
return
|
|
}
|
|
|
|
publicKey := h.cryptoService.GetPublicKeyPEM()
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"public_key": publicKey,
|
|
"algorithm": "RSA-OAEP-2048",
|
|
"transport_encryption": true,
|
|
})
|
|
}
|
|
|
|
// ==================== Encrypted Data Decryption ====================
|
|
//
|
|
// SECURITY: there is deliberately NO public decrypt endpoint. Transport
|
|
// encryption is one-directional — clients encrypt sensitive fields to the
|
|
// server's RSA public key and the authenticated config-update handlers
|
|
// (handleUpdateModelConfigs / handleUpdateExchangeConfigs / handleCreateExchange)
|
|
// decrypt them server-side via cryptoService.DecryptSensitiveData. Exposing a
|
|
// generic decrypt route would turn the server into a decryption oracle that any
|
|
// unauthenticated caller could use to recover the plaintext of a captured
|
|
// ciphertext, defeating the entire transport-encryption layer.
|
|
|
|
// ==================== Audit Log Query Endpoint ====================
|
|
|
|
// Audit log functionality removed, not needed in current simplified implementation
|
|
|
|
// ==================== Utility Functions ====================
|
|
|
|
// isValidPrivateKey Validate private key format
|
|
func isValidPrivateKey(key string) bool {
|
|
// EVM private key: 64 hex characters (optional 0x prefix)
|
|
if len(key) == 64 || (len(key) == 66 && key[:2] == "0x") {
|
|
return true
|
|
}
|
|
// TODO: Add validation for other chains
|
|
return false
|
|
}
|