Skip to content

Commit

Permalink
Merge commit from fork
Browse files Browse the repository at this point in the history
Input validation rules were applied to all user supplied input in postLocal method
  • Loading branch information
jimafisk authored Feb 3, 2025
2 parents fff52f8 + 1e2204f commit c3e72a9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 10 deletions.
42 changes: 32 additions & 10 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"log"
"net"
"net/http"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
Expand All @@ -24,6 +24,7 @@ import (
"github.com/MakeNowJust/heredoc/v2"
"github.com/briandowns/spinner"
"github.com/gerald1248/httpscerts"
"github.com/go-playground/validator/v10"
"github.com/spf13/cobra"
"golang.org/x/net/websocket"
)
Expand All @@ -40,6 +41,9 @@ var SSLFlag bool
// LocalFlag can be set to false to emulate a remote environment
var LocalFlag bool

// Valditor for input validation
var validate *validator.Validate

func checkPortAvailability(port int) bool {
address := fmt.Sprintf("localhost:%d", port)
conn, err := net.Dial("tcp", address)
Expand Down Expand Up @@ -195,16 +199,28 @@ func init() {
serveCmd.Flags().StringVarP(&ConfigFileFlag, "config", "c", "plenti.json", "use a custom sitewide configuration file")
}

// Validate user supplied values
type localChange struct {
Action string
Encoding string
File string
Contents string
Action string `json:"action" validate:"required,oneof=create update delete"`
Encoding string `json:"encoding" validate:"required,oneof=base64 text"`
File string `json:"file" validate:"file-path"`
Contents string `json:"contents" validate:"required"`
}

// Custom validation for file path. Only allow files in the layouts and content directories.
func FilePathValidation(fl validator.FieldLevel) bool {
reFilePath := regexp.MustCompile(`^(content)[a-zA-Z0-9_\-\/]*(.json)$`)
fmt.Println(fl.Field().String())
return reFilePath.MatchString(fl.Field().String())
}

func postLocal(w http.ResponseWriter, r *http.Request) {
// Register custom rules to validator
validate = validator.New()
validate.RegisterValidation("file-path", FilePathValidation)

if r.Method == "POST" {
b, err := ioutil.ReadAll(r.Body)
b, err := io.ReadAll(r.Body)
if err != nil {
fmt.Printf("Could not read 'body' from local edit: %v", err)
}
Expand All @@ -213,10 +229,16 @@ func postLocal(w http.ResponseWriter, r *http.Request) {
if err != nil {
fmt.Printf("Could not unmarshal JSON data: %v", err)
}

var contents []byte
currentDir, _ := os.Getwd()
for _, change := range localChanges {
change.File = filepath.Join(currentDir, filepath.Clean("/"+change.File))

// Validate user input, there is any error, return 400 Bad Request
err := validate.Struct(change)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

if change.Action == "create" || change.Action == "update" {
contents = []byte(change.Contents)
Expand Down Expand Up @@ -267,7 +289,7 @@ func serveSSL(port int) {
Handler: nil,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
ErrorLog: log.New(ioutil.Discard, "", 0),
ErrorLog: log.New(io.Discard, "", 0),
MaxHeaderBytes: 1 << 20,
TLSConfig: cfg,
}
Expand Down
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@ require (
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.10.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lunixbochs/vtclean v1.0.0 // indirect
github.com/matthewmueller/glob v0.0.3 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gerald1248/httpscerts v0.0.0-20170315065746-2c461ceb29ee h1:peCFhBNAfjd8yznwEnOjqn8Aj6KDTorDKYTYnt6lCTY=
github.com/gerald1248/httpscerts v0.0.0-20170315065746-2c461ceb29ee/go.mod h1:DXNa9ZIDTqZ0mipcmqLRVodihgtvR6PBX5rNtlcMYs0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand All @@ -94,6 +96,12 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
Expand Down Expand Up @@ -171,6 +179,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/livebud/npm v0.0.5 h1:ehDCwZvm/EJ+x3tJfHbbgY7CHPWlG4vJNP3KNBB3mKQ=
github.com/livebud/npm v0.0.5/go.mod h1:JxHp3/zoEtpmkYJw6J7uHqNTQNX6d2HaZ3FEeeL3EO4=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
Expand Down

0 comments on commit c3e72a9

Please sign in to comment.