Skip to content

Commit

Permalink
[gateway] Add security headers to protect from common security vulner…
Browse files Browse the repository at this point in the history
…abilities (#694)

- Add redirect check against the API_URL to prevent redirect attacks
  • Loading branch information
sandromello authored Feb 25, 2025
1 parent 7158fba commit 8900c9b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
26 changes: 22 additions & 4 deletions gateway/api/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"

Expand Down Expand Up @@ -49,12 +50,15 @@ func New(provider *idp.Provider) *handler { return &handler{idpProv: provider} }
// @Failure 400,409,422,500 {object} openapi.HTTPError
// @Router /login [get]
func (h *handler) Login(c *gin.Context) {
redirectURL := c.Query("redirect")
if redirectURL == "" {
redirectURL = fmt.Sprintf("http://%s/callback", proto.ClientLoginCallbackAddress)
redirectURL, err := parseRedirectURL(c)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{"message": err.Error()})
return
}

// if strings.HasPrefix(appconfig.Get().ApiURL(), redirectURL)
stateUID := uuid.NewString()
err := pglogin.New().Upsert(&types.Login{
err = pglogin.New().Upsert(&types.Login{
ID: stateUID,
Redirect: redirectURL,
Outcome: "",
Expand All @@ -77,6 +81,20 @@ func (h *handler) Login(c *gin.Context) {
c.JSON(http.StatusOK, openapi.Login{URL: url})
}

// parseRedirectURL validates the redirect query attribute to match against the API_URL env
// or the default localhost address
func parseRedirectURL(c *gin.Context) (string, error) {
redirectURL := c.Query("redirect")
if redirectURL != "" {
u, _ := url.Parse(redirectURL)
if u == nil || u.Hostname() != appconfig.Get().ApiHostname() {
return "", fmt.Errorf("redirect attribute does not match with api url")
}
return redirectURL, nil
}
return fmt.Sprintf("http://%s/callback", proto.ClientLoginCallbackAddress), nil
}

// LoginCallback
//
// @Summary Login Callback
Expand Down
13 changes: 13 additions & 0 deletions gateway/api/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,16 @@ func CORSMiddleware() gin.HandlerFunc {
c.Next()
}
}

func SecurityHeaderMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
c.Header("Content-Security-Policy", "default-src 'self'; connect-src *; font-src *; script-src-elem * 'unsafe-inline'; img-src * data:; style-src * 'unsafe-inline';")
c.Header("X-Frame-Options", "DENY")
c.Header("X-Content-Type-Options", "nosniff")
c.Header("Referrer-Policy", "strict-origin")
c.Header("Permissions-Policy", "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()")
c.Header("X-XSS-Protection", "1; mode=block")
c.Next()
}
}
1 change: 1 addition & 0 deletions gateway/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func (a *Api) StartAPI(sentryInit bool) {
a.logger = zaplogger
// https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies
route.SetTrustedProxies(nil)
route.Use(SecurityHeaderMiddleware())
route.Use(CORSMiddleware())
baseURL := appconfig.Get().ApiURLPath()

Expand Down
2 changes: 1 addition & 1 deletion scripts/dev/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ EOT
echo "--> STARTING AGENT ..."
# get digest of the agent secret key
# echo -n xagt-zKQQA9PAjCVJ4O8VlE2QZScNEbfmFisg_OerkI21NEg |sha256sum
HOOP_KEY="http://default:xagt-zKQQA9PAjCVJ4O8VlE2QZScNEbfmFisg_OerkI21NEg@127.0.0.1:8010?mode=standard" /app/bin/hooplinux start agent &
HOOP_KEY="grpc://default:xagt-zKQQA9PAjCVJ4O8VlE2QZScNEbfmFisg_OerkI21NEg@127.0.0.1:8010?mode=standard" /app/bin/hooplinux start agent &

echo "--> STARTING SSHD SERVER ..."

Expand Down

0 comments on commit 8900c9b

Please sign in to comment.