github.com/google/go-safeweb@v0.0.0-20231219055052-64d8cfc90fbb/safehttp/plugins/csp/framing.go (about) 1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package csp 16 17 import ( 18 "strings" 19 20 "github.com/google/go-safeweb/safehttp" 21 "github.com/google/go-safeweb/safehttp/plugins/framing/internalunsafeframing" 22 ) 23 24 // FramingPolicy can be used to create a new CSP policy with frame-ancestors 25 // set to 'self'. 26 // 27 // To specify a list of allowed framing hostnames use interceptor configurations. 28 type FramingPolicy struct { 29 // ReportURI controls the report-uri directive. If ReportUri is empty, no report-uri 30 // directive will be set. 31 ReportURI string 32 } 33 34 // Serialize serializes this policy for use in a Content-Security-Policy header 35 // or in a Content-Security-Policy-Report-Only header. A nonce will be provided 36 // to Serialize which can be used in 'nonce-{random-nonce}' values in directives. 37 func (f FramingPolicy) Serialize(nonce string, cfg safehttp.InterceptorConfig) string { 38 var b strings.Builder 39 40 var allow []string 41 if a, ok := cfg.(internalunsafeframing.AllowList); ok { 42 allow = a.Hostnames 43 } 44 b.WriteString(frameAncestors(allow)) 45 b.WriteString(report(f.ReportURI)) 46 47 return strings.TrimSpace(b.String()) 48 } 49 50 // Match matches strict policies overrides. 51 func (FramingPolicy) Match(cfg safehttp.InterceptorConfig) bool { 52 switch cfg.(type) { 53 case internalunsafeframing.Disable, internalunsafeframing.AllowList: 54 return true 55 } 56 return false 57 } 58 59 // Overridden checks the override level. 60 func (FramingPolicy) Overridden(cfg safehttp.InterceptorConfig) (disabled, reportOnly bool) { 61 switch c := cfg.(type) { 62 case internalunsafeframing.Disable: 63 return c.SkipReports, true 64 case internalunsafeframing.AllowList: 65 return false, c.ReportOnly 66 } 67 // This should not happen. 68 return false, false 69 } 70 71 func frameAncestors(sources []string) string { 72 var b strings.Builder 73 b.WriteString("frame-ancestors 'self'") 74 75 for _, s := range sources { 76 b.WriteString(" ") 77 b.WriteString(s) 78 } 79 b.WriteString("; ") 80 81 return b.String() 82 }