@@ -3,6 +3,7 @@ package middlewares
33import (
44 "net/http"
55 "net/http/httptest"
6+ "strings"
67 "testing"
78 "time"
89
@@ -122,4 +123,83 @@ func TestSecure(t *testing.T) {
122123 r = appendCSPRule ("script '*'; toto;" , "frame-ancestors" , "new-rule" )
123124 assert .Equal (t , "script '*'; toto;frame-ancestors new-rule;" , r )
124125 })
126+
127+ t .Run ("SecureMiddlewareCSPWithOrgDomain" , func (t * testing.T ) {
128+ e := echo .New ()
129+ req , _ := http .NewRequest (echo .GET , "http://app.cozy.local/" , nil )
130+ rec := httptest .NewRecorder ()
131+ c := e .NewContext (req , rec )
132+ inst := & instance.Instance {
133+ Domain : "cozy.local" ,
134+ OrgDomain : "example.com" ,
135+ }
136+ c .Set ("instance" , inst )
137+ h := Secure (& SecureConfig {
138+ CSPDefaultSrc : []CSPSource {CSPSrcSelf },
139+ CSPScriptSrc : []CSPSource {CSPSrcSelf },
140+ CSPFrameSrc : []CSPSource {CSPSrcSelf },
141+ CSPConnectSrc : []CSPSource {CSPSrcSelf },
142+ CSPFontSrc : []CSPSource {CSPSrcSelf },
143+ CSPImgSrc : []CSPSource {CSPSrcSelf },
144+ CSPManifestSrc : []CSPSource {CSPSrcSelf },
145+ CSPMediaSrc : []CSPSource {CSPSrcSelf },
146+ CSPObjectSrc : []CSPSource {CSPSrcSelf },
147+ CSPStyleSrc : []CSPSource {CSPSrcSelf },
148+ CSPWorkerSrc : []CSPSource {CSPSrcSelf },
149+ CSPFrameAncestors : []CSPSource {CSPSrcSelf },
150+ CSPBaseURI : []CSPSource {CSPSrcSelf },
151+ CSPFormAction : []CSPSource {CSPSrcSelf },
152+ })(echo .NotFoundHandler )
153+ _ = h (c )
154+
155+ csp := rec .Header ().Get (echo .HeaderContentSecurityPolicy )
156+
157+ // Verify that matrix.example.com appears only once (in frame-src)
158+ count := strings .Count (csp , "matrix.example.com" )
159+ assert .Equal (t , 1 , count ,
160+ "matrix.example.com should appear exactly once (in frame-src), but found %d times. CSP: %s" ,
161+ count , csp )
162+
163+ // Verify that frame-src contains matrix.example.com
164+ frameSrcIndex := strings .Index (csp , "frame-src " )
165+ assert .NotEqual (t , - 1 , frameSrcIndex ,
166+ "frame-src should be present in CSP. Full CSP: %s" , csp )
167+
168+ frameSrcEnd := strings .Index (csp [frameSrcIndex :], ";" )
169+ assert .NotEqual (t , - 1 , frameSrcEnd ,
170+ "frame-src should end with semicolon" )
171+
172+ frameSrcContent := csp [frameSrcIndex : frameSrcIndex + frameSrcEnd ]
173+ assert .Contains (t , frameSrcContent , "matrix.example.com" ,
174+ "frame-src should contain matrix.example.com. Found: %s" , frameSrcContent )
175+
176+ // Verify that other directives do NOT contain matrix.example.com
177+ otherDirectives := []string {
178+ "default-src" ,
179+ "script-src" ,
180+ "connect-src" ,
181+ "font-src" ,
182+ "img-src" ,
183+ "manifest-src" ,
184+ "media-src" ,
185+ "object-src" ,
186+ "style-src" ,
187+ "worker-src" ,
188+ "frame-ancestors" ,
189+ "base-uri" ,
190+ "form-action" ,
191+ }
192+
193+ for _ , directivePattern := range otherDirectives {
194+ directiveIndex := strings .Index (csp , directivePattern + " " )
195+ if directiveIndex != - 1 {
196+ directiveEnd := strings .Index (csp [directiveIndex :], ";" )
197+ if directiveEnd != - 1 {
198+ directiveContent := csp [directiveIndex : directiveIndex + directiveEnd ]
199+ assert .NotContains (t , directiveContent , "matrix.example.com" ,
200+ "Directive %s should NOT contain matrix.example.com. Found: %s" , directivePattern , directiveContent )
201+ }
202+ }
203+ }
204+ })
125205}
0 commit comments