technical-debt: move unrolled/secure replacement to own org

Signed-off-by: Christian Richter <c.richter@opencloud.eu>
This commit is contained in:
Christian Richter
2026-03-11 17:47:51 +01:00
committed by Christian Richter
parent b84a2edefd
commit dd57a53310
8 changed files with 106 additions and 60 deletions

2
go.mod
View File

@@ -404,7 +404,7 @@ require (
replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202
replace github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
replace github.com/unrolled/secure => github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4
replace go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3

4
go.sum
View File

@@ -70,8 +70,6 @@ github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CiscoM31/godata v1.0.11 h1:w7y8twuW02LdH6mak3/GJ5i0GrCv2IoZUJVqa/g5Yeo=
github.com/CiscoM31/godata v1.0.11/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c h1:ocsNvQ2tNHme4v/lTs17HROamc7mFzZfzWcg4m+UXN0=
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
github.com/KimMachineGun/automemlimit v0.7.5 h1:RkbaC0MwhjL1ZuBKunGDjE/ggwAX43DwZrJqVwyveTk=
github.com/KimMachineGun/automemlimit v0.7.5/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@@ -967,6 +965,8 @@ github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260204102724-10bcda1b3068
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260204102724-10bcda1b3068/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
github.com/opencloud-eu/reva/v2 v2.42.5 h1:Srhk8++3zJe3KA1u2Vqh4VbmljbblF75DR7t4HW0Kxw=
github.com/opencloud-eu/reva/v2 v2.42.5/go.mod h1:U3UaHyAQcutavXyLaLE3UVY5n6t2pRAN9uv09n69lwI=
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI=
github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=

View File

@@ -1,36 +1,32 @@
run:
timeout: 5m
timeout: 10m
modules-download-mode: readonly
allow-parallel-runners: true
linters:
enable-all: true
disable:
# Deprecated linters
- varcheck
- exhaustivestruct
- ifshort
- structcheck
- golint
- maligned
- interfacer
- nosnakecase
- deadcode
- scopelint
- rowserrcheck
- sqlclosecheck
- structcheck
- wastedassign
# Ignoring
- lll
- varnamelen
- paralleltest
- testpackage
- goerr113
- gochecknoglobals
- exhaustruct
- nestif
- wrapcheck
- tagliatelle
- depguard
- ireturn
- funlen
- goconst
- varnamelen
- gomnd
- execinquery
- copyloopvar
- intrange
- gocognit
- lll
- cyclop
- gocyclo
- gocognit
- testpackage
- err113
- nestif
- maintidx
- contextcheck
- perfsprint
- exportloopref

View File

@@ -1,4 +1,4 @@
# Secure [![GoDoc](https://godoc.org/github.com/unrolled/secure?status.svg)](http://godoc.org/github.com/unrolled/secure) [![Test](https://github.com/unrolled/secure/workflows/tests/badge.svg?branch=v1)](https://github.com/unrolled/secure/actions)
# Secure [![GoDoc](https://pkg.go.dev/badge/github.com/unrolled/secure)](http://godoc.org/github.com/unrolled/secure) [![Test](https://github.com/unrolled/secure/actions/workflows/test.yaml/badge.svg)](https://github.com/unrolled/secure/actions)
Secure is an HTTP middleware for Go that facilitates some quick security wins. It's a standard net/http [Handler](http://golang.org/pkg/net/http/#Handler), and can be used with many [frameworks](#integration-examples) or directly with Go's net/http package.
@@ -68,7 +68,7 @@ s := secure.New(secure.Options{
AllowRequestFunc: nil, // AllowRequestFunc is a custom function type that allows you to determine if the request should proceed or not based on your own custom logic. Default is nil.
HostsProxyHeaders: []string{"X-Forwarded-Hosts"}, // HostsProxyHeaders is a set of header keys that may hold a proxied hostname value for the request.
SSLRedirect: true, // If SSLRedirect is set to true, then only allow HTTPS requests. Default is false.
SSLTemporaryRedirect: false, // If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
SSLTemporaryRedirect: false, // If SSLTemporaryRedirect is true, then a 307 will be used while redirecting. Default is false (301).
SSLHost: "ssl.example.com", // SSLHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
SSLHostFunc: nil, // SSLHostFunc is a function pointer, the return value of the function is the host name that has same functionality as `SSHost`. Default is nil. If SSLHostFunc is nil, the `SSLHost` option will be used.
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, // SSLProxyHeaders is set of header keys with associated values that would indicate a valid HTTPS request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map.
@@ -86,7 +86,10 @@ s := secure.New(secure.Options{
FeaturePolicy: "vibrate 'none';", // Deprecated: this header has been renamed to PermissionsPolicy. FeaturePolicy allows the Feature-Policy header with the value to be set with a custom value. Default is "".
PermissionsPolicy: "fullscreen=(), geolocation=()", // PermissionsPolicy allows the Permissions-Policy header with the value to be set with a custom value. Default is "".
CrossOriginOpenerPolicy: "same-origin", // CrossOriginOpenerPolicy allows the Cross-Origin-Opener-Policy header with the value to be set with a custom value. Default is "".
CrossOriginEmbedderPolicy: "require-corp", // CrossOriginEmbedderPolicy allows the Cross-Origin-Embedder-Policy header with the value to be set with a custom value. Default is "".
CrossOriginResourcePolicy: "same-origin", // CrossOriginResourcePolicy allows the Cross-Origin-Resource-Policy header with the value to be set with a custom value. Default is "".
XDNSPrefetchControl: "on", // XDNSPrefetchControl allows the X-DNS-Prefetch-Control header to be set via "on" or "off" keyword. Default is "".
XPermittedCrossDomainPolicies: "none", // XPermittedCrossDomainPolicies allows the X-Permitted-Cross-Domain-Policies to be set with a custom value. Default is "".
IsDevelopment: true, // This will cause the AllowedHosts, SSLRedirect, and STSSeconds/STSIncludeSubdomains options to be ignored during development. When deploying to production, be sure to set this to false.
})
// ...
@@ -123,6 +126,10 @@ l := secure.New(secure.Options{
FeaturePolicy: "",
PermissionsPolicy: "",
CrossOriginOpenerPolicy: "",
CrossOriginEmbedderPolicy: "",
CrossOriginResourcePolicy: "",
XDNSPrefetchControl: "",
XPermittedCrossDomainPolicies: "",
IsDevelopment: false,
})
~~~

View File

@@ -12,7 +12,8 @@ type key int
const cspNonceKey key = iota
// CSPNonce returns the nonce value associated with the present request. If no nonce has been generated it returns an empty string.
// CSPNonce returns the nonce value associated with the present request.
// If no nonce has been generated it returns an empty string.
func CSPNonce(c context.Context) string {
if val, ok := c.Value(cspNonceKey).(string); ok {
return val

View File

@@ -45,7 +45,7 @@ const (
)
type Builder struct {
Directives map[string][]string
Directives map[string]([]string)
}
// MustBuild is like Build but panics if an error occurs.
@@ -61,16 +61,18 @@ func (builder *Builder) MustBuild() string {
// Build creates a content security policy string from the specified directives.
// If any directive contains invalid values, an error is returned instead.
func (builder *Builder) Build() (string, error) {
keys := make([]string, 0, len(builder.Directives))
var sb strings.Builder
for k := range builder.Directives {
keys = append(keys, k)
// Pull the directive keys out.
directiveKeys := []string{}
for key := range builder.Directives {
directiveKeys = append(directiveKeys, key)
}
sort.Strings(keys)
// Sort the policies: https://www.w3.org/TR/CSP3/#framework-policy
sort.Strings(directiveKeys)
var sb strings.Builder
for _, directive := range keys {
for _, directive := range directiveKeys {
if sb.Len() > 0 {
sb.WriteString("; ")
}

View File

@@ -12,26 +12,31 @@ import (
type secureCtxKey string
const (
stsHeader = "Strict-Transport-Security"
stsSubdomainString = "; includeSubDomains"
stsPreloadString = "; preload"
frameOptionsHeader = "X-Frame-Options"
frameOptionsValue = "DENY"
contentTypeHeader = "X-Content-Type-Options"
contentTypeValue = "nosniff"
xssProtectionHeader = "X-XSS-Protection"
xssProtectionValue = "1; mode=block"
cspHeader = "Content-Security-Policy"
cspReportOnlyHeader = "Content-Security-Policy-Report-Only"
referrerPolicyHeader = "Referrer-Policy"
featurePolicyHeader = "Feature-Policy"
permissionsPolicyHeader = "Permissions-Policy"
coopHeader = "Cross-Origin-Opener-Policy"
stsHeader = "Strict-Transport-Security"
stsSubdomainString = "; includeSubDomains"
stsPreloadString = "; preload"
frameOptionsHeader = "X-Frame-Options"
frameOptionsValue = "DENY"
contentTypeHeader = "X-Content-Type-Options"
contentTypeValue = "nosniff"
xssProtectionHeader = "X-XSS-Protection"
xssProtectionValue = "1; mode=block"
cspHeader = "Content-Security-Policy"
cspReportOnlyHeader = "Content-Security-Policy-Report-Only"
hpkpHeader = "Public-Key-Pins"
referrerPolicyHeader = "Referrer-Policy"
featurePolicyHeader = "Feature-Policy"
permissionsPolicyHeader = "Permissions-Policy"
coopHeader = "Cross-Origin-Opener-Policy"
coepHeader = "Cross-Origin-Embedder-Policy"
corpHeader = "Cross-Origin-Resource-Policy"
dnsPreFetchControlHeader = "X-DNS-Prefetch-Control"
permittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies"
robotTagHeader = "X-Robots-Tag"
permittedCrossDomainPoliciesHeader = "X-Permitted-Cross-Domain-Policies"
ctxDefaultSecureHeaderKey = secureCtxKey("SecureResponseHeader")
cspNonceSize = 16
ctxDefaultSecureHeaderKey = secureCtxKey("SecureResponseHeader")
cspNonceSize = 16
)
// SSLHostFunc is a custom function type that can be used to dynamically set the SSL host of a request.
@@ -67,7 +72,7 @@ type Options struct {
SSLRedirect bool
// If SSLForceHost is true and SSLHost is set, requests will be forced to use SSLHost even the ones that are already using SSL. Default is false.
SSLForceHost bool
// If SSLTemporaryRedirect is true, a 302 will be used while redirecting. Default is false (301).
// If SSLTemporaryRedirect is true, then a 307 will be used while redirecting. Default is false (301).
SSLTemporaryRedirect bool
// If STSIncludeSubdomains is set to true, the `includeSubdomains` will be appended to the Strict-Transport-Security header. Default is false.
STSIncludeSubdomains bool
@@ -93,6 +98,18 @@ type Options struct {
// CrossOriginOpenerPolicy allows you to ensure a top-level document does not share a browsing context group with cross-origin documents. Default is "".
// Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy
CrossOriginOpenerPolicy string
// CrossOriginResourcePolicy header blocks others from loading your resources cross-origin in some cases.
// Reference https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy
CrossOriginResourcePolicy string
// CrossOriginEmbedderPolicy header helps control what resources can be loaded cross-origin.
// Reference https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy
CrossOriginEmbedderPolicy string
// XDNSPrefetchControl header helps control DNS prefetching, which can improve user privacy at the expense of performance.
// Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control
XDNSPrefetchControl string
// XPermittedCrossDomainPolicies header tells some clients (mostly Adobe products) your domain's policy for loading cross-domain content.
// Reference: https://owasp.org/www-project-secure-headers/
XPermittedCrossDomainPolicies string
// SSLHost is the host name that is used to redirect http requests to https. Default is "", which indicates to use the same host.
SSLHost string
// AllowedHosts is a slice of fully qualified domain names that are allowed. Default is an empty slice, which allows any and all host names.
@@ -100,12 +117,12 @@ type Options struct {
// AllowedHostsAreRegex determines, if the provided `AllowedHosts` slice contains valid regular expressions. If this flag is set to true, every request's host will be checked against these expressions. Default is false.
AllowedHostsAreRegex bool
// AllowRequestFunc is a custom function that allows you to determine if the request should proceed or not based on your own custom logic. Default is nil.
AllowRequestFunc AllowRequestFunc
AllowRequestFunc AllowRequestFunc `json:"-" toml:"-" yaml:"-"`
// HostsProxyHeaders is a set of header keys that may hold a proxied hostname value for the request.
HostsProxyHeaders []string
// SSLHostFunc is a function pointer, the return value of the function is the host name that has same functionality as `SSHost`. Default is nil.
// If SSLHostFunc is nil, the `SSLHost` option will be used.
SSLHostFunc *SSLHostFunc
SSLHostFunc *SSLHostFunc `json:"-" toml:"-" yaml:"-"`
// SSLProxyHeaders is set of header keys with associated values that would indicate a valid https request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map.
SSLProxyHeaders map[string]string
// STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header.
@@ -474,6 +491,29 @@ func (s *Secure) processRequest(w http.ResponseWriter, r *http.Request) (http.He
responseHeader.Set(coopHeader, s.opt.CrossOriginOpenerPolicy)
}
// Cross Origin Resource Policy header.
if len(s.opt.CrossOriginResourcePolicy) > 0 {
responseHeader.Set(corpHeader, s.opt.CrossOriginResourcePolicy)
}
// Cross-Origin-Embedder-Policy header.
if len(s.opt.CrossOriginEmbedderPolicy) > 0 {
responseHeader.Set(coepHeader, s.opt.CrossOriginEmbedderPolicy)
}
// X-DNS-Prefetch-Control header.
switch strings.ToLower(s.opt.XDNSPrefetchControl) {
case "on":
responseHeader.Set(dnsPreFetchControlHeader, "on")
case "off":
responseHeader.Set(dnsPreFetchControlHeader, "off")
}
// X-Permitted-Cross-Domain-Policies header.
if len(s.opt.XPermittedCrossDomainPolicies) > 0 {
responseHeader.Set(permittedCrossDomainPolicies, s.opt.XPermittedCrossDomainPolicies)
}
// X-Permitted-Cross-Domain-Policies
if len(s.opt.PermittedCrossDomainPolicies) > 0 {
responseHeader.Set(permittedCrossDomainPoliciesHeader, s.opt.PermittedCrossDomainPolicies)

4
vendor/modules.txt vendored
View File

@@ -2154,7 +2154,7 @@ github.com/trustelem/zxcvbn/scoring
# github.com/tus/tusd/v2 v2.8.0
## explicit; go 1.23.0
github.com/tus/tusd/v2/pkg/handler
# github.com/unrolled/secure v1.16.0 => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
# github.com/unrolled/secure v1.16.0 => github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4
## explicit; go 1.13
github.com/unrolled/secure
github.com/unrolled/secure/cspbuilder
@@ -2756,6 +2756,6 @@ sigs.k8s.io/yaml
## explicit; go 1.13
stash.kopano.io/kgol/rndm
# github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202
# github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
# github.com/unrolled/secure => github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4
# go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3
# github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a