Skip to content

Commit beaeeb0

Browse files
authored
fix(play): add security flag (#126)
* fix(play): add security flag * fix(play): linting error
1 parent 90c6f9e commit beaeeb0

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

cmd/pimo/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ There is NO WARRANTY, to the extent permitted by law.`, version, commit, buildDa
116116
})
117117

118118
playPort := 3010
119+
playSecure := false
119120
playCmd := &cobra.Command{
120121
Use: "play",
121122
Run: func(cmd *cobra.Command, args []string) {
122-
router := pimo.Play()
123+
router := pimo.Play(playSecure)
123124
port := fmt.Sprintf("0.0.0.0:%d", playPort)
124125

125126
if err := router.Start(port); err != nil {
@@ -128,6 +129,7 @@ There is NO WARRANTY, to the extent permitted by law.`, version, commit, buildDa
128129
},
129130
}
130131
playCmd.PersistentFlags().IntVarP(&playPort, "port", "p", 3010, "port number")
132+
playCmd.PersistentFlags().BoolVarP(&playSecure, "secure", "s", false, "enable security features (use this flag if PIMO Play is publicly exposed)")
131133
rootCmd.AddCommand(playCmd)
132134

133135
if err := rootCmd.Execute(); err != nil {

internal/app/pimo/play.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io/fs"
77
"net/http"
8+
"net/url"
89
"strings"
910

1011
"github.com/cgi-fr/pimo/pkg/jsonline"
@@ -17,7 +18,7 @@ import (
1718
//go:embed client
1819
var content embed.FS
1920

20-
func Play() *echo.Echo {
21+
func Play(enableSecurity bool) *echo.Echo {
2122
router := echo.New()
2223

2324
router.Use(middleware.CORS())
@@ -26,6 +27,15 @@ func Play() *echo.Echo {
2627
" err=${error}\n",
2728
}))
2829

30+
if enableSecurity {
31+
router.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
32+
return func(c echo.Context) error {
33+
c.Set("enableSecurity", true)
34+
return next(c)
35+
}
36+
})
37+
}
38+
2939
router.GET("/*", echo.WrapHandler(handleClient()))
3040
router.POST("/play", play)
3141

@@ -70,6 +80,13 @@ func play(ctx echo.Context) error {
7080
return ctx.String(http.StatusInternalServerError, err.Error())
7181
}
7282

83+
if ctx.Get("enableSecurity") == true {
84+
if err := checkSecurityRequirements(pdef); err != nil {
85+
log.Err(err).Msg("Forbidden request")
86+
return ctx.String(http.StatusInternalServerError, err.Error())
87+
}
88+
}
89+
7390
config.SingleInput = &input
7491
context := NewContext(pdef)
7592

@@ -90,6 +107,47 @@ func play(ctx echo.Context) error {
90107
return ctx.JSONBlob(http.StatusOK, []byte(result.String()))
91108
}
92109

110+
func checkSecurityRequirements(pdef model.Definition) error {
111+
for _, mask := range pdef.Masking {
112+
// usage of command is not allowed with pimo play
113+
if len(mask.Mask.Command) > 0 {
114+
return fmt.Errorf("Usage of `command` mask is forbidden")
115+
}
116+
117+
// usage of file scheme is not allowed
118+
if err := checkUriScheme(mask.Mask.FluxURI); err != nil {
119+
return err
120+
}
121+
122+
if err := checkUriScheme(mask.Mask.HashInURI); err != nil {
123+
return err
124+
}
125+
126+
if err := checkUriScheme(mask.Mask.Markov.Sample); err != nil {
127+
return err
128+
}
129+
130+
if err := checkUriScheme(mask.Mask.RandomChoiceInURI); err != nil {
131+
return err
132+
}
133+
}
134+
135+
return nil
136+
}
137+
138+
func checkUriScheme(uri string) error {
139+
u, err := url.Parse(uri)
140+
if err != nil {
141+
return nil
142+
}
143+
144+
if u.Scheme == "file" {
145+
return fmt.Errorf("Usage of `file` scheme is forbidden")
146+
}
147+
148+
return nil
149+
}
150+
93151
func handleClient() http.Handler {
94152
fSys, err := fs.Sub(content, "client")
95153
if err != nil {

0 commit comments

Comments
 (0)