def test_no_unsafe_default_src_none(self): values = ( "default-src", # no value == 'none' "default-src 'none'; script-src 'strict-dynamic' 'nonce-abc123' 'unsafe-inline'", "default-src 'none'; script-src https://mozilla.org;" + "style-src https://mozilla.org; upgrade-insecure-requests;", "default-src 'none'; object-src https://mozilla.org") for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals( 'csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['http']) self.assertFalse(result['meta']) self.assertTrue(result['pass']) self.assertTrue(result['policy']['defaultNone']) # Do the same with an HTTP equiv self.reqs = empty_requests('test_parse_http_equiv_headers_csp1.html') result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertFalse(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass']) # Do the same with an HTTP equiv self.reqs = empty_requests( 'test_parse_http_equiv_headers_csp_multiple_http_equiv1.html') result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertFalse(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass']) # And that same thing, but with both a header and a CSP policy self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = "script-src https://mozilla.org;" result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass'])
def test_insecure_scheme(self): self.reqs['responses']['auto'].headers['Content-Security-Policy'] = 'default-src http://mozilla.org' result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-insecure-scheme', result['result']) self.assertFalse(result['pass'])
def test_header_invalid(self): self.reqs['responses']['auto'].headers['Content-Security-Policy'] = ' ' result = content_security_policy(self.reqs) self.assertEquals(result['result'], 'csp-header-invalid') self.assertFalse(result['pass'])
def test_unsafe_inline(self): values = ( "script-src 'unsafe-inline'", "script-src data:", # overly broad "script-src http:", "script-src ftp:", "default-src 'unsafe-inline'", "default-src 'UNSAFE-INLINE'", "DEFAULT-SRC 'none'", # See CSP bug report on case-sensitivity "script-src 'unsafe-inline'; SCRIPT-SRC 'none'", # again "upgrade-insecure-requests", "script-src 'none'", "script-src https:", "script-src https://mozilla.org https:", "default-src https://mozilla.org https:", "default-src 'none'; script-src *", "default-src *; script-src *; object-src 'none'", "default-src 'none'; script-src 'none', object-src *", "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; script-src 'unsafe-inline' http:", "object-src https:; script-src 'none'") for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass']) self.assertTrue(result['policy']['unsafeInline'])
def test_unsafe_inline(self): values = ("script-src 'unsafe-inline'", "script-src data:", # overly broad "script-src http:", "script-src ftp:", "default-src 'unsafe-inline'", "default-src 'UNSAFE-INLINE'", "DEFAULT-SRC 'none'", # See CSP bug report on case-sensitivity "script-src 'unsafe-inline'; SCRIPT-SRC 'none'", # again "upgrade-insecure-requests", "script-src 'none'", "script-src https:", "script-src https://mozilla.org https:", "default-src https://mozilla.org https:", "default-src 'none'; script-src *", "default-src *; script-src *; object-src 'none'", "default-src 'none'; script-src 'none', object-src *", "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; script-src 'unsafe-inline' http:", "object-src https:; script-src 'none'") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass']) self.assertTrue(result['policy']['unsafeInline'])
def test_no_unsafe(self): # See https://github.com/mozilla/http-observatory/issues/88 and # https://github.com/mozilla/http-observatory/issues/277 for 'unsafe-inline' + hash/nonce values = ( "default-src https://mozilla.org", "default-src https://mozilla.org;;; ;;;script-src 'none'", "object-src 'none'; script-src https://mozilla.org; " + "style-src https://mozilla.org; upgrade-insecure-requests;", "object-src 'none'; script-src 'strict-dynamic' 'nonce-abc' 'unsafe-inline'; style-src 'none'", "object-src 'none'; style-src 'self';" + "script-src 'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBA='", "object-src 'none'; style-src 'self'; script-src 'unsafe-inline' " + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBA='" + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBB='", "object-src 'none'; script-src 'unsafe-inline' 'nonce-abc123' 'unsafe-inline'; style-src 'none'", "default-src https://mozilla.org; style-src 'unsafe-inline' 'nonce-abc123' 'unsafe-inline'", "default-src https://mozilla.org; style-src 'unsafe-inline' " + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBB=' 'unsafe-inline'" ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe', result['result']) self.assertTrue(result['pass'])
def test_no_unsafe(self): # See https://github.com/mozilla/http-observatory/issues/88 and # https://github.com/mozilla/http-observatory/issues/277 for 'unsafe-inline' + hash/nonce values = ("default-src https://mozilla.org", "default-src https://mozilla.org;;; ;;;script-src 'none'", "object-src 'none'; script-src https://mozilla.org; " + "style-src https://mozilla.org; upgrade-insecure-requests;", "object-src 'none'; script-src 'strict-dynamic' 'nonce-abc' 'unsafe-inline'; style-src 'none'", "object-src 'none'; style-src 'self';" + "script-src 'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBA='", "object-src 'none'; style-src 'self'; script-src 'unsafe-inline' " + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBA='" + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBB='", "object-src 'none'; script-src 'unsafe-inline' 'nonce-abc123' 'unsafe-inline'; style-src 'none'", "default-src https://mozilla.org; style-src 'unsafe-inline' 'nonce-abc123' 'unsafe-inline'", "default-src https://mozilla.org; style-src 'unsafe-inline' " + "'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBB=' 'unsafe-inline'") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe', result['result']) self.assertTrue(result['pass'])
def test_unsafe_eval(self): self.reqs['responses']['auto'].headers['Content-Security-Policy'] = "script-src 'unsafe-eval'" result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-eval', result['result']) self.assertEquals(result['data']['script-src'], ["'unsafe-eval'"]) self.assertFalse(result['pass'])
def test_no_unsafe_default_src_none(self): values = ("default-src 'none'; script-src https://mozilla.org;" "style-src https://mozilla.org; upgrade-insecure-requests;",) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['pass'])
def test_no_unsafe_default_src_none(self): values = ("default-src", # no value == 'none' "default-src 'none'; script-src 'strict-dynamic' 'nonce-abc123' 'unsafe-inline'", "default-src 'none'; script-src https://mozilla.org;" + "style-src https://mozilla.org; upgrade-insecure-requests;", "default-src 'none'; object-src https://mozilla.org") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['http']) self.assertFalse(result['meta']) self.assertTrue(result['pass']) self.assertTrue(result['policy']['defaultNone']) # Do the same with an HTTP equiv self.reqs = empty_requests('test_parse_http_equiv_headers_csp1.html') result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertFalse(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass']) # Do the same with an HTTP equiv self.reqs = empty_requests('test_parse_http_equiv_headers_csp_multiple_http_equiv1.html') result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertFalse(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass']) # And that same thing, but with both a header and a CSP policy self.reqs['responses']['auto'].headers['Content-Security-Policy'] = "script-src https://mozilla.org;" result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['http']) self.assertTrue(result['meta']) self.assertTrue(result['pass'])
def test_unsafe_inline(self): values = ("script-src 'unsafe-inline'", "script-src data:", "default-src 'unsafe-inline'", "upgrade-insecure-requests") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass'])
def test_unsafe_inline_in_style_src_only(self): values = ("script-src 'none'; style-src 'unsafe-inline'", "default-src 'none'; script-src https://mozilla.org; style-src 'unsafe-inline'", "default-src 'unsafe-inline'; script-src https://mozilla.org;", "default-src 'none'; style-src data:") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline-in-style-src-only', result['result']) self.assertTrue(result['pass'])
def test_unsafe_inline(self): values = ("script-src 'unsafe-inline'", "script-src data:", "default-src 'unsafe-inline'", "upgrade-insecure-requests") for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass'])
def test_unsafe_inline_in_style_src_only(self): values = ("script-src 'none'; style-src 'unsafe-inline'", "default-src 'none'; script-src https://mozilla.org; style-src 'unsafe-inline'", "default-src 'unsafe-inline'; script-src https://mozilla.org;", "default-src 'none'; style-src data:") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline-in-style-src-only', result['result']) self.assertFalse(result['pass'])
def test_strict_dynamic(self): values = ( "default-src 'none'; script-src 'strict-dynamic' 'nonce-abc123'", "default-src 'none'; script-src 'strict-dynamic' 'sha256-abc123'", "default-src 'none'; script-src 'strict-dynamic' 'sha256-abc123' https://", "default-src 'none'; script-src 'strict-dynamic' 'sha256-abc123' 'unsafe-inline'", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-no-unsafe-default-src-none', result['result']) self.assertTrue(result['policy']['strictDynamic'])
def test_insecure_scheme(self): values = ( "default-src http://mozilla.org", "default-src 'none'; script-src http://mozilla.org", "default-src 'none'; script-src http://mozilla.org", "default-src 'none'; script-src ftp://mozilla.org", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-insecure-scheme', result['result']) self.assertFalse(result['pass']) self.assertTrue(result['policy']['insecureSchemeActive'])
def test_header_invalid(self): values = ( " ", "\r\n", "", "default-src 'none'; default-src 'none'", # Repeated directives not allowed "default-src 'none'; img-src 'self'; default-src 'none'", "default-src 'none'; script-src 'strict-dynamic'", # strict dynamic without hash/nonce "defa", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals(result['result'], 'csp-header-invalid') self.assertFalse(result['pass'])
def test_insecure_scheme_in_passive_content_only(self): values = ( "default-src 'none'; img-src http://mozilla.org", "default-src 'self'; img-src ftp:", "default-src 'self'; img-src http:", "default-src 'none'; img-src https:; media-src http://mozilla.org", "default-src 'none'; img-src http: https:; script-src 'self'; style-src 'self'", "default-src 'none'; img-src 'none'; media-src http:; script-src 'self'; style-src 'self'", "default-src 'none'; img-src 'none'; media-src http:; script-src 'self'; style-src 'unsafe-inline'", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-insecure-scheme-in-passive-content-only', result['result']) self.assertTrue(result['pass']) self.assertTrue(result['policy']['insecureSchemePassive'])
def test_unsafe_inline_in_style_src_only(self): values = ("object-src 'none'; script-src 'none'; style-src 'unsafe-inline'", "default-src 'none'; script-src https://mozilla.org; style-src 'unsafe-inline'", "default-src 'unsafe-inline'; script-src https://mozilla.org", "default-src 'none';;; ;;;style-src 'self' 'unsafe-inline'", "default-src 'none'; style-src data:", "default-src 'none'; style-src *", "default-src 'none'; style-src https:", "default-src 'none'; style-src 'unsafe-inline'; " + "script-src 'sha256-hqBEA/HXB3aJU2FgOnYN8rkAgEVgyfi3Vs1j2/XMPBB=' " + "'unsafe-inline'") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline-in-style-src-only', result['result']) self.assertTrue(result['pass']) self.assertTrue(result['policy']['unsafeInlineStyle'])
def test_unsafe_inline(self): values = ( "script-src 'unsafe-inline'", "script-src data:", "default-src 'unsafe-inline'", "upgrade-insecure-requests", "script-src 'none'", "script-src https:", "script-src https://mozilla.org https:", "default-src https://mozilla.org https:", "default-src 'none'; script-src *", "default-src *; script-src *; object-src 'none'", "default-src 'none'; script-src 'none', object-src *", "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; script-src 'unsafe-inline' http:", "object-src https:; script-src 'none'") for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass'])
def test_unsafe_inline(self): values = ("script-src 'unsafe-inline'", "script-src data:", "default-src 'unsafe-inline'", "upgrade-insecure-requests", "script-src 'none'", "script-src https:", "script-src https://mozilla.org https:", "default-src https://mozilla.org https:", "default-src 'none'; script-src *", "default-src *; script-src *; object-src 'none'", "default-src 'none'; script-src 'none', object-src *", "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; script-src 'unsafe-inline' http:", "object-src https:; script-src 'none'") for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value result = content_security_policy(self.reqs) self.assertEquals('csp-implemented-with-unsafe-inline', result['result']) self.assertFalse(result['pass'])
def test_missing(self): result = content_security_policy(self.reqs) self.assertEquals('csp-not-implemented', result['result']) self.assertFalse(result['pass'])
def test_policy_analysis(self): values = ( "default-src 'none'", # doesn't fall to frame-ancestors "frame-ancestors *", "frame-ancestors http:", "frame-ancestors https:", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertFalse(content_security_policy(self.reqs)['policy']['antiClickjacking']) # Now test where anticlickjacking is enabled self.reqs['responses']['auto'].headers['Content-Security-Policy'] = "default-src *; frame-ancestors 'none'" self.assertTrue(content_security_policy(self.reqs)['policy']['antiClickjacking']) # Test unsafeObjects and insecureBaseUri values = ( "default-src 'none'; base-uri *; object-src *", "default-src 'none'; base-uri https:; object-src https:", "default-src *", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertTrue(content_security_policy(self.reqs)['policy']['insecureBaseUri']) self.assertTrue(content_security_policy(self.reqs)['policy']['unsafeObjects']) # Other tests for insecureBaseUri values = ( "default-src *; base-uri 'none'", "default-src 'none'; base-uri 'self'", "default-src 'none'; base-uri https://mozilla.org", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertFalse(content_security_policy(self.reqs)['policy']['insecureBaseUri']) # Test for insecureSchemePassive values = ( "default-src * http: https: data: 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; img-src http:", "default-src 'none' https://mozilla.org; img-src http://mozilla.org", "default-src https:; media-src http://mozilla.org; script-src http:", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertTrue(content_security_policy(self.reqs)['policy']['insecureSchemePassive']) # Test for insecureFormAction values = ( "default-src *; form-action 'none'", "default-src *; form-action 'self'", "default-src 'none'; form-action 'self' https://mozilla.org", "form-action 'self' https://mozilla.org", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertFalse(content_security_policy(self.reqs)['policy']['insecureFormAction']) values = ( "default-src *", "default-src 'none'", "form-action https:", ) for value in values: self.reqs['responses']['auto'].headers['Content-Security-Policy'] = value self.assertTrue(content_security_policy(self.reqs)['policy']['insecureFormAction'])
def test_policy_analysis(self): values = ( "default-src 'none'", # doesn't fall to frame-ancestors "frame-ancestors *", "frame-ancestors http:", "frame-ancestors https:", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertFalse( content_security_policy( self.reqs)['policy']['antiClickjacking']) # Now test where anticlickjacking is enabled self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = "default-src *; frame-ancestors 'none'" self.assertTrue( content_security_policy(self.reqs)['policy']['antiClickjacking']) # Test unsafeObjects and insecureBaseUri values = ( "default-src 'none'; base-uri *; object-src *", "default-src 'none'; base-uri https:; object-src https:", "default-src *", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertTrue( content_security_policy( self.reqs)['policy']['insecureBaseUri']) self.assertTrue( content_security_policy(self.reqs)['policy']['unsafeObjects']) # Other tests for insecureBaseUri values = ( "default-src *; base-uri 'none'", "default-src 'none'; base-uri 'self'", "default-src 'none'; base-uri https://mozilla.org", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertFalse( content_security_policy( self.reqs)['policy']['insecureBaseUri']) # Test for insecureSchemePassive values = ( "default-src * http: https: data: 'unsafe-inline' 'unsafe-eval'", "default-src 'none'; img-src http:", "default-src 'none' https://mozilla.org; img-src http://mozilla.org", "default-src https:; media-src http://mozilla.org; script-src http:", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertTrue( content_security_policy( self.reqs)['policy']['insecureSchemePassive']) # Test for insecureFormAction values = ( "default-src *; form-action 'none'", "default-src *; form-action 'self'", "default-src 'none'; form-action 'self' https://mozilla.org", "form-action 'self' https://mozilla.org", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertFalse( content_security_policy( self.reqs)['policy']['insecureFormAction']) values = ( "default-src *", "default-src 'none'", "form-action https:", ) for value in values: self.reqs['responses']['auto'].headers[ 'Content-Security-Policy'] = value self.assertTrue( content_security_policy( self.reqs)['policy']['insecureFormAction'])