diff --git a/cmd/errors.go b/cmd/errors.go
index 78ebb4f..5f48dc2 100644
--- a/cmd/errors.go
+++ b/cmd/errors.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/yosssi/gohtml"
+ "seedno.de/seednode/roulette/types"
)
var (
@@ -30,7 +31,11 @@ func notFound(w http.ResponseWriter, r *http.Request, path string) error {
w.WriteHeader(http.StatusNotFound)
w.Header().Add("Content-Type", "text/html")
- _, err := io.WriteString(w, gohtml.Format(newPage("Not Found", "404 Page not found")))
+ nonce := types.GetNonce(6)
+
+ w.Header().Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'nonce-%s';", nonce))
+
+ _, err := io.WriteString(w, gohtml.Format(newPage("Not Found", "404 Page not found", nonce)))
if err != nil {
return err
}
@@ -49,9 +54,14 @@ func notFound(w http.ResponseWriter, r *http.Request, path string) error {
func serverError(w http.ResponseWriter, r *http.Request, i interface{}) {
startTime := time.Now()
+ w.WriteHeader(http.StatusInternalServerError)
w.Header().Add("Content-Type", "text/html")
- io.WriteString(w, gohtml.Format(newPage("Server Error", "An error has occurred. Please try again.")))
+ nonce := types.GetNonce(6)
+
+ w.Header().Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'nonce-%s';", nonce))
+
+ io.WriteString(w, gohtml.Format(newPage("Server Error", "An error has occurred. Please try again.", nonce)))
if Verbose {
fmt.Printf("%s | ERROR: Invalid request for %s from %s\n",
diff --git a/cmd/favicons.go b/cmd/favicons.go
index dc8e412..341be9f 100644
--- a/cmd/favicons.go
+++ b/cmd/favicons.go
@@ -6,6 +6,7 @@ package cmd
import (
"embed"
+ "fmt"
"net/http"
"strconv"
"strings"
@@ -16,15 +17,15 @@ import (
//go:embed favicons/*
var favicons embed.FS
-const (
- faviconHtml string = `
+func getFavicon(nonce string) string {
+ return fmt.Sprintf(`
-
+
- `
-)
+ `, nonce)
+}
func serveFavicons(errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
diff --git a/cmd/refresh.go b/cmd/refresh.go
index 6cbb3ac..8c686da 100644
--- a/cmd/refresh.go
+++ b/cmd/refresh.go
@@ -26,10 +26,11 @@ func refreshInterval(r *http.Request) (int64, string) {
}
}
-func refreshFunction(rootUrl string, refreshTimer int64) string {
+func refreshFunction(rootUrl string, refreshTimer int64, nonce string) string {
var htmlBody strings.Builder
- htmlBody.WriteString(fmt.Sprintf("`, fileUri))
+ html.WriteString(fmt.Sprintf(``, nonce, fileUri))
html.WriteString(fmt.Sprintf(`
`, rootUrl))
return html.String(), nil
diff --git a/types/images/images.go b/types/images/images.go
index 4ab2263..5d96a3a 100644
--- a/types/images/images.go
+++ b/types/images/images.go
@@ -12,6 +12,7 @@ import (
_ "image/jpeg"
_ "image/png"
"math/rand"
+ "net/http"
"os"
"strings"
@@ -30,7 +31,15 @@ type Format struct {
Fun bool
}
-func (t Format) Css() string {
+func (t Format) CSP(w http.ResponseWriter) string {
+ nonce := types.GetNonce(6)
+
+ w.Header().Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'nonce-%s';", nonce))
+
+ return nonce
+}
+
+func (t Format) CSS() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
@@ -41,7 +50,7 @@ func (t Format) Css() string {
css.WriteString(`a{color:inherit;display:block;height:97%;width:100%;text-decoration:none;}`)
}
- css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;`)
+ css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;color:transparent;`)
css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)`)
if t.Fun {
rotate := rand.Intn(360)
@@ -69,19 +78,26 @@ func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string)
dimensions.height), nil
}
-func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime string) (string, error) {
+func (t Format) Body(rootUrl, fileUri, filePath, fileName, prefix, mime, nonce string) (string, error) {
dimensions, err := ImageDimensions(filePath)
if err != nil {
return "", err
}
- return fmt.Sprintf(``,
+ var w strings.Builder
+
+ w.WriteString(fmt.Sprintf(``,
rootUrl,
+ nonce,
fileUri,
dimensions.width,
dimensions.height,
mime,
- fileName), nil
+ fileName))
+
+ w.WriteString(fmt.Sprintf(``, nonce))
+
+ return w.String(), nil
}
func (t Format) Extensions() map[string]string {
diff --git a/types/text/text.go b/types/text/text.go
index a90c914..86023fe 100644
--- a/types/text/text.go
+++ b/types/text/text.go
@@ -7,6 +7,7 @@ package text
import (
"errors"
"fmt"
+ "net/http"
"os"
"strings"
"unicode/utf8"
@@ -16,7 +17,11 @@ import (
type Format struct{}
-func (t Format) Css() string {
+func (t Format) CSP(w http.ResponseWriter) string {
+ return ""
+}
+
+func (t Format) CSS() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
@@ -31,7 +36,7 @@ func (t Format) Title(rootUrl, fileUri, filePath, fileName, prefix, mime string)
return fmt.Sprintf(`