From af05fbea27df62c96b411a941cf5bb612f256e9d Mon Sep 17 00:00:00 2001 From: Julio Capote Date: Fri, 6 Jan 2023 21:43:11 -0500 Subject: sanitize/strip any incoming html --- cgi/servers.go | 20 ++++++++++++-------- go.mod | 9 ++++++--- go.sum | 12 ++++++++++++ main.go | 4 +++- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/cgi/servers.go b/cgi/servers.go index b014fdb..1f15227 100644 --- a/cgi/servers.go +++ b/cgi/servers.go @@ -20,6 +20,7 @@ import ( "git.capotej.com/capotej/communique/models" "git.capotej.com/capotej/communique/urls" "git.capotej.com/capotej/communique/views" + "github.com/microcosm-cc/bluemonday" "github.com/mmcdole/gofeed" "go.uber.org/zap" ) @@ -28,10 +29,11 @@ type Servers struct { log *zap.SugaredLogger persister *models.Persister cfg config.Config + policy *bluemonday.Policy } -func NewServers(log *zap.SugaredLogger, persister *models.Persister, cfg config.Config) *Servers { - return &Servers{log: log, persister: persister, cfg: cfg} +func NewServers(log *zap.SugaredLogger, persister *models.Persister, cfg config.Config, policy *bluemonday.Policy) *Servers { + return &Servers{log: log, persister: persister, cfg: cfg, policy: policy} } // Start iterates over all Handlers and starts an internal CGI server for each one @@ -57,14 +59,14 @@ func (s *Servers) Start() { // Ticker go func(aHandler config.Handler) { defer wg.Done() - startTicker(aHandler, s.persister, handlerLogger, s.cfg, signed) + startTicker(aHandler, s.persister, handlerLogger, s.cfg, signed, s.policy) }(handler) // Execute a handler tick on start since Go's ticker waits until $interval to trigger first tick go func(aHandler config.Handler) { defer wg.Done() time.Sleep(1 * time.Second) output := tick(aHandler, handlerLogger) - err := processTick(aHandler, output, s.persister, handlerLogger, s.cfg, signed) + err := processTick(aHandler, output, s.persister, handlerLogger, s.cfg, signed, s.policy) if err != nil { s.log.Error(err) } @@ -91,7 +93,7 @@ func startCGIServer(h config.Handler, log *zap.SugaredLogger) { server.Serve(unixListener) } -func startTicker(h config.Handler, persister *models.Persister, log *zap.SugaredLogger, cfg config.Config, signed *delivery.Signed) { +func startTicker(h config.Handler, persister *models.Persister, log *zap.SugaredLogger, cfg config.Config, signed *delivery.Signed, policy *bluemonday.Policy) { ticker := time.NewTicker(h.Interval) // TODO add some random jitter here so handlers dont run at the same exact intervals done := make(chan bool) func() { @@ -101,7 +103,7 @@ func startTicker(h config.Handler, persister *models.Persister, log *zap.Sugared return case _ = <-ticker.C: output := tick(h, log) - err := processTick(h, output, persister, log, cfg, signed) + err := processTick(h, output, persister, log, cfg, signed, policy) if err != nil { log.Error(err) } @@ -110,7 +112,7 @@ func startTicker(h config.Handler, persister *models.Persister, log *zap.Sugared }() } -func processTick(h config.Handler, output []byte, persister *models.Persister, log *zap.SugaredLogger, cfg config.Config, signed *delivery.Signed) error { +func processTick(h config.Handler, output []byte, persister *models.Persister, log *zap.SugaredLogger, cfg config.Config, signed *delivery.Signed, policy *bluemonday.Policy) error { fp := gofeed.NewParser() fp.ParseString(string(output)) feed, err := fp.ParseString(string(output)) @@ -126,8 +128,10 @@ func processTick(h config.Handler, output []byte, persister *models.Persister, l } else if len(v.Description) != 0 { extractedContent = v.Description } + if len(extractedContent) != 0 { - log.Debugf("extracted content '%s'", extractedContent) + extractedContent := policy.Sanitize(extractedContent) + log.Debugf("extracted and sanitized content '%s'", extractedContent) outboxItem := models.CreateOutboxItem(h, []byte(extractedContent)) err = persister.StoreWithCallback(outboxItem, func() { logger := log.With("handler", h.Name).With("type", "subscription") diff --git a/go.mod b/go.mod index a6b76bb..a6695e0 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/Jeffail/gabs/v2 v2.6.1 // indirect github.com/PuerkitoBio/goquery v1.8.0 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgraph-io/badger/v3 v3.2103.5 // indirect @@ -27,10 +28,12 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v22.11.23+incompatible // indirect + github.com/gorilla/css v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.13 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-isatty v0.0.16 // indirect + github.com/microcosm-cc/bluemonday v1.0.21 // indirect github.com/mmcdole/gofeed v1.1.3 // indirect github.com/mmcdole/goxpp v1.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -44,9 +47,9 @@ require ( go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/crypto v0.4.0 // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/net v0.5.0 // indirect + golang.org/x/sys v0.4.0 // indirect + golang.org/x/text v0.6.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index b80dceb..455f416 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9Pq github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -100,6 +102,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -121,6 +125,8 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg= +github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mmcdole/gofeed v1.1.3 h1:pdrvMb18jMSLidGp8j0pLvc9IGziX4vbmvVqmLH6z8o= @@ -217,6 +223,8 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -239,6 +247,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -247,6 +257,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/main.go b/main.go index 62d971b..261c247 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "git.capotej.com/capotej/communique/registry" "github.com/BurntSushi/toml" "github.com/dgraph-io/badger/v3" + "github.com/microcosm-cc/bluemonday" "go.uber.org/zap" "go.uber.org/zap/zapio" ) @@ -61,7 +62,8 @@ func main() { var mainWg sync.WaitGroup // // Internal CGI Servers - cgiServers := cgi.NewServers(log, persister, cfg) + policy := bluemonday.StrictPolicy() + cgiServers := cgi.NewServers(log, persister, cfg, policy) mainWg.Add(1) go cgiServers.Start() -- cgit v1.2.3