Skip to content

Commit be9dde2

Browse files
fix[backend](threat_intelligense): added header injection protection and sanitized id on proxy requests
1 parent 99c85dd commit be9dde2

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

backend/modules/threatintel/handler/proxy.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"io"
66
"net/http"
77
"net/http/httputil"
8+
"net/textproto"
89
"net/url"
10+
"time"
911

1012
"github.com/gin-gonic/gin"
1113
"github.com/utmstack/utmstack/backend/modules/threatintel/internal"
@@ -96,19 +98,35 @@ func (h *ReverseProxyHandler) HandleUsageEndpoint(c *gin.Context) {
9698
return
9799
}
98100

101+
allowed := map[string]struct{}{
102+
"Accept": {},
103+
"Content-Type": {},
104+
"Content-Length": {},
105+
"User-Agent": {},
106+
"X-Request-Id": {},
107+
"X-Correlation-Id": {},
108+
}
109+
99110
// Copy headers
100111
for k, v := range c.Request.Header {
101112
if k != "Authorization" && k != "Id" && k != "Key" {
102113
req.Header[k] = v
103114
}
115+
canonical := textproto.CanonicalMIMEHeaderKey(k)
116+
if _, ok := allowed[canonical]; !ok {
117+
continue
118+
}
119+
req.Header[k] = v
104120
}
105121

106122
// Set instance credentials
107123
req.Header.Set("id", cfg.InstanceID)
108124
req.Header.Set("key", cfg.InstanceKey)
109125

110126
// Execute request
111-
client := &http.Client{}
127+
client := &http.Client{
128+
Timeout: 20* time.Second,
129+
}
112130
resp, err := client.Do(req)
113131
if err != nil {
114132
c.JSON(http.StatusBadGateway, gin.H{"error": "upstream service error"})

backend/modules/threatintel/internal/instanceconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"path/filepath"
66
"sync"
77

8+
"github.com/threatwinds/go-sdk/catcher"
89
"gopkg.in/yaml.v3"
910
)
1011

@@ -31,6 +32,7 @@ func LoadInstanceConfig(updatesDir string) (*InstanceConfig, error) {
3132
}
3233
var cfg InstanceConfig
3334
if err := yaml.Unmarshal(data, &cfg); err != nil {
35+
_ = catcher.Error("error loading instance configuration",err,map[string]any{})
3436
return
3537
}
3638
instanceConfig = &cfg

backend/modules/threatintel/routes.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package threatintel
22

33
import (
4+
"strings"
5+
46
"github.com/gin-gonic/gin"
57
"github.com/utmstack/utmstack/backend/modules/threatintel/handler"
68
)
@@ -15,7 +17,9 @@ func RegisterRoutes(api *gin.RouterGroup, m *Module, userAuth gin.HandlerFunc) {
1517
// GET /api/v1/threat-intel/entity/:id → /proxy/api/analytics/v1/entity/{id}/details
1618
g.GET("/entity/:id", func(c *gin.Context) {
1719
id := c.Param("id")
18-
targetPath := "/proxy/api/analytics/v1/entity/" + id + "/details"
20+
replacer := strings.NewReplacer(".", "", "\\", "","/","")
21+
sanitized_id := replacer.Replace(id)
22+
targetPath := "/proxy/api/analytics/v1/entity/" + sanitized_id + "/details"
1923
h := handler.NewReverseProxyHandler(targetPath)
2024
h.Handle(c)
2125
})

0 commit comments

Comments
 (0)