def testReportParser_parse_unicode(self): """The JSON deserialiser returns strings as unicode objects. Check that they are correctly parsed in URIs.""" fullReport = """{"remote-addr": "XXX", "policy-type": "regular", "http-user-agent":""" \ + """ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:27.0) Gecko/20100101 Firefox/27.0",""" \ + """ "timestamp-utc": "2014-03-01 12:13:14.156789", "csp-report": {"violated-directive":""" \ + """ "img-src 'none'", "referrer": "http://handbook5.com/a/a-security-analysis-of-amazon%E2%80%99s-elastic-compute-cloud-service-w14847.html",""" \ + """ "blocked-uri": "http://www.iseclab.org/images/anr.png", "document-uri":""" \ + """ "http://www.iseclab.org/?p"}, "header-type": "standard"}""" expected = Report({ "violated-directive": Directive("img-src", ()), "referrer": URI( "http", "handbook5.com", None, u"/a/a-security-analysis-of-amazon’s-elastic-compute-cloud-service-w14847.html" ), "blocked-uri": URI("http", "www.iseclab.org", None, u"/images/anr.png"), "document-uri": URI("http", "www.iseclab.org", None, u"/", "p") }) parser = ReportParser(requiredKeys=[]) jsonReport = json.loads(fullReport) cspReport = parser.parseJsonDict(jsonReport["csp-report"]) assert cspReport == expected
def testPolicy_matches_defaultSrcNotSpecified_noMatch(self): """Policy contains no directive of resource type, and no default directive either. Should assume 'default-src *' (no match for inline/eval resources).""" pol = Policy((PolicyTest.sampleDirective5, )) selfURI = PolicyTest.sampleURI1a assert not pol.matches(URI.INLINE(), "script-src", selfURI) assert not pol.matches(URI.EVAL(), "script-src", selfURI)
def test_regularURI_singletons(self): """All the singleton URIs should return False for isRegularURI().""" assert URI.EMPTY().isRegularURI() == False assert URI.INVALID().isRegularURI() == False assert URI.INLINE().isRegularURI() == False assert URI.EVAL().isRegularURI() == False assert URI("http", "seclab.nu", None, None, None).isRegularURI() == True
def test_URISourceExpression_match_query(self): """The query component in an URI should not matter when matching.""" srcExpr = URISourceExpression("http", "seclab.nu", 80, "/path") selfURI = SourceExpressionTest.uri_urlFull_secure assert srcExpr.matches(URI("http", "seclab.nu", 80, "/path", None), selfURI) assert srcExpr.matches(URI("http", "seclab.nu", 80, "/path", "query"), selfURI)
def testPolicy_matches_invalid(self): """An invalid policy matches nothing.""" selfURI = PolicyTest.sampleURI2 assert not Policy.INVALID().matches(PolicyTest.sampleURI1a, "script-src", selfURI) assert not Policy.INVALID().matches(URI.INVALID(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.EMPTY(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.INLINE(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.EVAL(), "script-src", selfURI)
def test_InvalidSourceExpression_match(self): """The invalid source expression does not match anything.""" srcExpr = SourceExpression.INVALID() selfURI = SourceExpressionTest.uri_chromeExtension assert not srcExpr.matches(SourceExpressionTest.uri_empty, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_urlFull, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_urlSubstring, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_domain, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_data, selfURI) assert not srcExpr.matches(URI.INVALID(), selfURI) assert not srcExpr.matches(URI.EVAL(), selfURI) assert not srcExpr.matches(URI.INLINE(), selfURI)
def test_URISourceExpression_match_empty_path(self): """If the path component of the source expression or the URI is the empty string, it should be treated the same as being None.""" srcExprEmpty = URISourceExpression("http", "seclab.nu", 80, "") srcExprNone = URISourceExpression("http", "seclab.nu", 80, None) selfURI = SourceExpressionTest.uri_urlFull_secure assert srcExprEmpty.matches(SourceExpressionTest.uri_urlFull, selfURI) assert srcExprEmpty.matches(URI("http", "seclab.nu", 80, ""), selfURI) assert srcExprEmpty.matches(URI("http", "seclab.nu", 80, None), selfURI) assert srcExprNone.matches(SourceExpressionTest.uri_urlFull, selfURI) assert srcExprNone.matches(URI("http", "seclab.nu", 80, ""), selfURI) assert srcExprNone.matches(URI("http", "seclab.nu", 80, None), selfURI)
def testDirective_generateDirective_incompatibleURI(self): violatedRegular = Directive("object-src", []) violatedInline = Directive("style-src", []) violatedEval = Directive("script-src", []) assert violatedRegular.generateDirective( "regular", URI.EMPTY()) == Directive.INVALID() assert violatedRegular.generateDirective( "regular", URI.INVALID()) == Directive.INVALID() #assert violatedInline.generateDirective("inline", DirectiveTest.sampleURI1) == Directive.INVALID() assert violatedInline.generateDirective( "inline", URI.INVALID()) == Directive.INVALID() #assert violatedEval.generateDirective("eval", DirectiveTest.sampleURI1) == Directive.INVALID() assert violatedEval.generateDirective( "eval", URI.INVALID()) == Directive.INVALID()
def test_no_modification_partial_URI_host_path(self): """Simple test with no modification, splitting a partially specified URI.""" uriString = "www.seclab.nu/path/file" uriExpected = URI(None, "www.seclab.nu", None, "/path/file") actual = URIParser(addScheme=False, addPort=False, decodeEscapedCharacters=False) \ .parse(uriString) assert actual == uriExpected
def test_str_unicode(self): """Test URI serialisation with unicode characters.""" url = u'http://handbook5.com/a/a-security-analysis-of-amazon%E2%80%99s-elastic-compute-cloud-service-w14847.html' unicodePath = u"/a/a-security-analysis-of-amazon’s-elastic-compute-cloud-service-w14847.html" parsed = URIParser(decodeEscapedCharacters=True).parse(url) assert parsed == URI("http", "handbook5.com", None, unicodePath) assert str(parsed) == url # must use quoted version
def test_addScheme_addPort_defaultScheme_schemePortMappings_partial_URI_host_path( self): """Test if scheme and port are added properly to partially specified URI.""" uriString = "www.seclab.nu/path/file" uriExpected = URI("test-scheme", "www.seclab.nu", 333, "/path/file") assert URIParser(addScheme=True, defaultScheme="test-scheme", addPort=True, schemePortMappings={"test-scheme": 333}, decodeEscapedCharacters=False) \ .parse(uriString) == uriExpected
def test_stripUserPassword_userOnly_URI(self): """Check if user:password part properly removed.""" uriString = "http://[email protected]:80/index.php" uriExpected = URI("http", "www.seclab.nu", 80, "/index.php") actual = URIParser(decodeEscapedCharacters=False) \ .parse(uriString) assert actual == uriExpected
def test_addPort_schemePortMappingsNone_partial_URI_scheme_host(self): """Simple test with "adding" a None port, splitting a partially specified URI.""" uriString = "chrome-extension://mkfokfffehpeedafpekjeddnmnjhmcmk" uriExpected = URI("chrome-extension", "mkfokfffehpeedafpekjeddnmnjhmcmk", None, None) assert URIParser(addScheme=True, addPort=True, defaultPort=123, schemePortMappings={'chrome-extension': None}, decodeEscapedCharacters=False) \ .parse(uriString) == uriExpected
def test_no_modification_partial_URI_scheme_host(self): """Simple test with no modification, splitting a partially specified URI.""" uriString = "chrome-extension://mkfokfffehpeedafpekjeddnmnjhmcmk" uriExpected = URI("chrome-extension", "mkfokfffehpeedafpekjeddnmnjhmcmk", None, None) assert URIParser(addScheme=False, addPort=False, decodeEscapedCharacters=False) \ .parse(uriString) == uriExpected
def test_no_modification_partial_URI_data(self): """Data URIs use only the scheme and the host for the data. The data should not be converted to lowercase.""" uriString = "data:image/png;base64,iVBORw0KGgoAAAA" uriExpected = URI("data", "image/png;base64,iVBORw0KGgoAAAA", None, None) assert URIParser().parse(uriString) == uriExpected
def test_no_modification_partial_URI_scheme_host_path_query(self): """Simple test with no modification, splitting a partially specified URI.""" uriString = "https://www.seclab.nu/path/file?query=here" uriExpected = URI("https", "www.seclab.nu", None, "/path/file", "query=here") assert URIParser(addScheme=False, addPort=False, decodeEscapedCharacters=False) \ .parse(uriString) == uriExpected
def test_stripUserPassword_userOnly_URI_IPv4(self): """Check if user:password part properly removed (with IPv4 address).""" uriString = "http://[email protected]:80/index.php" uriExpected = URI("http", "123.123.123.123", 80, "/index.php") actual = URIParser(decodeEscapedCharacters=False) \ .parse(uriString) assert actual == uriExpected
def test_getters(self): """Checks the getters of URI.""" inputURI = URI("https", "seclab.nu", 443, "/index.html", "param=val") assert inputURI.getScheme() == "https" assert inputURI.getHost() == "seclab.nu" assert inputURI.getPort() == 443 assert inputURI.getPath() == "/index.html" assert inputURI.getQuery() == "param=val" assert inputURI.isRegularURI() == True
def test_URISourceExpression_match_star(self): "A source expression that should match everything (except for special URIs)." srcExpr = URISourceExpression(None, "*", None, None) selfURI = SourceExpressionTest.uri_chromeExtension assert srcExpr.matches(SourceExpressionTest.uri_chromeExtension, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_urlFull, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_urlFull_secure, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_urlFull_other, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_empty, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_domain, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_data, selfURI) assert not srcExpr.matches(URI.EMPTY(), selfURI) assert not srcExpr.matches(URI.INVALID(), selfURI) assert not srcExpr.matches(URI.INLINE(), selfURI) assert not srcExpr.matches(URI.EVAL(), selfURI)
def testPolicy_matches_matchingDirectiveType(self): """Policy contains directive of resource type that matches.""" pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5)) selfURI = PolicyTest.sampleURI2 assert pol.matches( URI("https", "abc.seclab.nu", 443, "/path", "some-query"), "connect-src", selfURI)
def testReport_generatePolicy_wrongDocumentURI(self): reportEmptyDocument = Report({ "blocked-uri": ReportTest.sampleURI1a, "violated-directive": ReportTest.sampleDirective1a, "document-uri": URI.EMPTY() }) assert reportEmptyDocument.generatePolicy( "regular") == Policy.INVALID()
def test_stripAnchor_full_URI(self): """Check if anchor part properly removed.""" uriString = "http://www.seclab.nu:80/index.php?parameter=value&more#anchor" uriExpected = URI("http", "www.seclab.nu", 80, "/index.php", "parameter=value&more") actual = URIParser(decodeEscapedCharacters=False) \ .parse(uriString) assert actual == uriExpected
def test_decodeEscapedCharacters_full_URI(self): """Check if escaped characters in the path are correctly decoded.""" uriString = "http://www.seclab.nu:80/a%20path/index.py?math=3%3D%281%2B1%29%2A1.5" uriExpected = URI("http", "www.seclab.nu", 80, "/a path/index.py", "math=3%3D%281%2B1%29%2A1.5") actual = URIParser(decodeEscapedCharacters=True) \ .parse(uriString) assert actual == uriExpected
class ReportDataReaderTest(unittest.TestCase): sampleURI1a = URI("http", "seclab.nu", None, None, None) sampleURI1b = URI("http", "seclab.nu", None, None, None) sampleURI2 = URI("http", "seclab.nu", None, "/blocked", "query") sampleDirective1a = Directive("default-src", ()) sampleDirective1b = Directive("default-src", ()) sampleDirective2a = Directive("script-src", (SourceExpression.UNSAFE_INLINE(), )) sampleDirective2b = Directive("script-src", (SourceExpression.UNSAFE_INLINE(), )) samplePolicy1a = Policy((sampleDirective1a, sampleDirective2a)) samplePolicy1b = Policy((sampleDirective1b, sampleDirective2b)) samplePolicy2 = Policy((sampleDirective1a, )) @pytest.fixture(autouse=True) def initdir(self, tmpdir): tmpdir.chdir() def setUp(self): self.fileIn = ReportDataReader(True) self.filename = "encodingdecoding.dat" self.fileOut = DataWriter(self.filename) def tearDown(self): pass def testReportCreation(self): """Writes a Report and loads it back as an object.""" report = Report({ "abc": True, "def": 1, "ghi": "http://seclab.nu/", "document-uri": ReportDataReaderTest.sampleURI1a, "violated-directive": ReportDataReaderTest.sampleDirective1a, "original-policy": ReportDataReaderTest.samplePolicy1a, "blocked-uri": ReportDataReaderTest.sampleURI2 }) self.fileOut.storeAll([report]) self.fileOut.close() dataOut = self.fileIn.loadAll(self.filename) assert len(dataOut) == 1 print report print dataOut[0] assert report in dataOut
def test_str(self): """Checks the string serialisation of a few URIs.""" assert str(URI("data", "", None, None)) == "data:" assert str(URI("data", "image/png;base64,iVBORw0KGgoAAAA", None, None)) == "data:image/png;base64,iVBORw0KGgoAAAA" assert str(URI("about", "blank", None, None)) == "about:blank" assert str( URI("http", "www.seclab.org", 80, "/file", "parameter=value") ) == "http://www.seclab.org:80/file?parameter=value" assert str(URI(None, "www.seclab.nu", None, None)) == "www.seclab.nu" assert str(URI.EMPTY()) == "" assert str(URI.INVALID()) == "[invalid]" assert str(URI.INLINE()) == "[inline]" assert str(URI.EVAL()) == "[eval]"
def testReportParser_parse_emptyOrSelfURI(self): """This tests that the internal settings of the URI parser are chosen such that empty or self URIs are correctly handled.""" report = """{"empty-uri": "", "self-uri": "self", "document-uri": "http://seclab.nu"}""" expected = Report({ "empty-uri": URI.EMPTY(), "self-uri": ReportTest.sampleURI1a, "document-uri": ReportTest.sampleURI1a }) assert ReportParser(requiredKeys=[], strict=True, uriKeys=["empty-uri", "self-uri", "document-uri"]) \ .parseString(report) == expected
def test_SelfSourceExpression_match(self): """A 'self' source expression matches if the scheme, host and port of the self and other URI are the same (using default ports if absent).""" selfURI = URI("http", "seclab.nu", 80, "/other-path") srcExpr = SelfSourceExpression.SELF() assert srcExpr.matches(SourceExpressionTest.uri_urlFull, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_urlFull_longer1, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_urlFull_secure, selfURI) assert not srcExpr.matches(SourceExpressionTest.uri_url1Sub, selfURI) assert srcExpr.matches(SourceExpressionTest.uri_schemedomain, selfURI) # using default port in URI assert not srcExpr.matches(URI.EMPTY(), selfURI) assert not srcExpr.matches(URI.INVALID(), selfURI) assert not srcExpr.matches(URI.INLINE(), selfURI) assert not srcExpr.matches(URI.EVAL(), selfURI) selfURIDefaultPort = URI("https", "seclab.nu", None, "/yet-another-path") assert not srcExpr.matches(SourceExpressionTest.uri_urlFull_secure, selfURIDefaultPort) assert srcExpr.matches( SourceExpressionTest.uri_urlFull_secure_defaultPort, selfURIDefaultPort) selfURINoPort = SourceExpressionTest.uri_chromeExtension assert not srcExpr.matches( SourceExpressionTest.uri_chromeExtension, selfURINoPort) # no valid port can be deduced from this scheme
def test_EvalInlineSourceExpression_match(self): """The source expressions 'unsafe-inline' and 'unsafe-eval' do not match any URI.""" srcExprEval = SourceExpression.UNSAFE_EVAL() srcExprInline = SourceExpression.UNSAFE_INLINE() selfURI = SourceExpressionTest.uri_chromeExtension assert not srcExprEval.matches(SourceExpressionTest.uri_empty, selfURI) assert not srcExprInline.matches(SourceExpressionTest.uri_empty, selfURI) assert not srcExprEval.matches(URI.INVALID(), selfURI) assert not srcExprInline.matches(URI.INVALID(), selfURI) assert srcExprInline.matches(URI.INLINE(), selfURI) assert not srcExprInline.matches(URI.EVAL(), selfURI) assert not srcExprEval.matches(URI.INLINE(), selfURI) assert srcExprEval.matches(URI.EVAL(), selfURI)
def testReportParser_parse_inferSelfURI(self): """Tests if the self URI is correctly inferred from the "document-uri" field (even after renaming).""" report = """{"violated-directive": "default-src 'self'", "referrer": "",""" \ + """ "blocked-uri": "self", "document-URL":""" \ + """ "http://seclab.nu"}""" expected = Report({ "violated-directive": ReportTest.sampleDirective1a, "referrer": URI.EMPTY(), "blocked-uri": ReportTest.sampleURI1a, "document-uri": ReportTest.sampleURI1a }) parser = ReportParser( requiredKeys=["violated-directive", "document-uri", "blocked-uri"], strict=True, directiveKeys=["violated-directive"], uriKeys=["referrer", "blocked-uri", "document-uri"], keyNameReplacements={'document-url': 'document-uri'}) cspReport = parser.parseString(report) assert cspReport == expected
class PolicyTest(unittest.TestCase): sampleURI1a = URI("http", "seclab.nu", None, None, None) sampleURI1b = URI("http", "seclab.nu", None, None, None) sampleURI2 = URI("http", "seclab.ccs.neu.edu", None, None, None) sampleSourceExpression1 = URISourceExpression("http", "seclab.nu", None, None) sampleSourceExpression2 = SelfSourceExpression.SELF() sampleDirective1a = Directive( "default-src", (URISourceExpression("http", "seclab.nu", None, None), )) sampleDirective1b = Directive( "default-src", (URISourceExpression("http", "seclab.nu", None, None), )) sampleDirective2 = Directive("script-src", (SourceExpression.UNSAFE_INLINE(), )) sampleDirective3 = Directive( "img-src", (URISourceExpression(None, "*", None, None), )) sampleDirective4 = Directive("img-src", ()) sampleDirective5 = Directive( "connect-src", (SelfSourceExpression.SELF(), URISourceExpression("chrome-extension", None, None, None), URISourceExpression("https", "abc.seclab.nu", None, "/path"))) sampleDirective6 = Directive( "style-src", (SourceExpression.UNSAFE_INLINE(), SelfSourceExpression.SELF())) sampleDirective7 = Directive("script-src", (SourceExpression.UNSAFE_EVAL(), )) sampleDirective8 = Directive("style-src", (SelfSourceExpression.SELF(), )) sampleDirective9 = Directive("default-src", (SourceExpression.UNSAFE_INLINE(), )) def testPolicy_str_invalid(self): assert str(Policy.INVALID()) == "[invalid]" def testPolicy_str_empty(self): assert str(Policy(())) == "" def testPolicy_str_normal(self): pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2, PolicyTest.sampleDirective3)) assert str( pol ) == "default-src http://seclab.nu; img-src *; script-src 'unsafe-inline'" def testPolicy_eq(self): pol1a = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2, PolicyTest.sampleDirective3)) pol1b = Policy( (PolicyTest.sampleDirective1b, PolicyTest.sampleDirective2, PolicyTest.sampleDirective3)) pol2 = Policy( (PolicyTest.sampleDirective2, PolicyTest.sampleDirective3)) assert Policy.INVALID() == Policy.INVALID() assert pol1a == pol1b assert hash(pol1a) == hash(pol1b) assert pol1a != pol2 def testPolicy_init_duplicateType(self): pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective3, PolicyTest.sampleDirective4)) directives = pol.getDirectives() assert PolicyTest.sampleDirective1a in directives and (PolicyTest.sampleDirective3 in directives \ or PolicyTest.sampleDirective4 in directives) def testPolicy_init_duplicateDirective(self): pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective1b, PolicyTest.sampleDirective2)) assert pol == Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2)) assert pol == Policy( (PolicyTest.sampleDirective1b, PolicyTest.sampleDirective2)) def testPolicy_init_noDuplicatesHere(self): directives = set([ PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2, PolicyTest.sampleDirective5 ]) pol = Policy(directives) assert pol.getDirectives() == directives def testPolicy_init_removeNotRegularDirective(self): pol = Policy([ PolicyTest.sampleDirective1a, Directive.INVALID(), Directive.EVAL_SCRIPT_BASE_RESTRICTION() ]) expected = Policy([PolicyTest.sampleDirective1a]) assert pol == expected def testPolicy_matches_invalid(self): """An invalid policy matches nothing.""" selfURI = PolicyTest.sampleURI2 assert not Policy.INVALID().matches(PolicyTest.sampleURI1a, "script-src", selfURI) assert not Policy.INVALID().matches(URI.INVALID(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.EMPTY(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.INLINE(), "script-src", selfURI) assert not Policy.INVALID().matches(URI.EVAL(), "script-src", selfURI) def testPolicy_matches_matchingDirectiveType(self): """Policy contains directive of resource type that matches.""" pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5)) selfURI = PolicyTest.sampleURI2 assert pol.matches( URI("https", "abc.seclab.nu", 443, "/path", "some-query"), "connect-src", selfURI) def testPolicy_matches_nonMatchingDirectiveTypeButDefaultMatches(self): """Policy contains directive of resource type that does not match and default directive that does match, but it should not be applied.""" pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5)) selfURI = PolicyTest.sampleURI2 assert not pol.matches(PolicyTest.sampleURI1a, "connect-src", selfURI) def testPolicy_matches_defaultSrcMatches(self): """Policy contains no directive of resource type, but a default directive that matches.""" pol = Policy( (PolicyTest.sampleDirective1a, PolicyTest.sampleDirective5)) selfURI = PolicyTest.sampleURI2 assert pol.matches(PolicyTest.sampleURI1a, "script-src", selfURI) def testPolicy_matches_defaultSrcNoMatch(self): """Policy contains no directive of resource type, but a default directive. Default-src does not match.""" pol = Policy((PolicyTest.sampleDirective1a, )) selfURI = PolicyTest.sampleURI1a assert not pol.matches(PolicyTest.sampleURI2, "img-src", selfURI) def testPolicy_matches_defaultSrcNotUsable(self): """Policy contains no directive of resource type, but a default directive. Default-src cannot be used in this case because not allowed for resource type.""" pol = Policy((PolicyTest.sampleDirective1a, )) selfURI = PolicyTest.sampleURI2 assert not pol.matches(PolicyTest.sampleURI1a, "form-action", selfURI) def testPolicy_matches_defaultSrcNotSpecified_match(self): """Policy contains no directive of resource type, and no default directive either. Should assume 'default-src *' (match for regular resources).""" pol = Policy((PolicyTest.sampleDirective5, )) selfURI = PolicyTest.sampleURI1a assert pol.matches(PolicyTest.sampleURI2, "script-src", selfURI) def testPolicy_matches_defaultSrcNotSpecified_noMatch(self): """Policy contains no directive of resource type, and no default directive either. Should assume 'default-src *' (no match for inline/eval resources).""" pol = Policy((PolicyTest.sampleDirective5, )) selfURI = PolicyTest.sampleURI1a assert not pol.matches(URI.INLINE(), "script-src", selfURI) assert not pol.matches(URI.EVAL(), "script-src", selfURI) def testPolicyParser_parse_normal(self): simplePolicy = """connect-src 'self' https://abc.seclab.nu/path chrome-extension:; img-src 'none'""" cspSimplePolicy = PolicyParser().parse(simplePolicy) print cspSimplePolicy assert cspSimplePolicy == Policy( [PolicyTest.sampleDirective4, PolicyTest.sampleDirective5]) def testPolicyParser_parse_strict_onlyValidDirectives(self): """Ensures that a CSP policy does not parse in strict mode if it contains an invalid directive.""" policy = """img-src 'none'; script-src""" cspPolicy = PolicyParser(strict=True).parse(policy) assert cspPolicy == Policy.INVALID() def testPolicyParser_parse_nonstrict_onlyValidDirectives(self): """Ensures that a CSP policy does ignore invalid portions in non-strict mode if it contains an invalid directive.""" policy = """img-src 'none'; script-src""" cspPolicy = PolicyParser(strict=False).parse(policy) assert cspPolicy == Policy([PolicyTest.sampleDirective4]) def testPolicyParser_parse_ignoredDirective(self): """Ensure that unsupported directives ('report-uri' etc.) are skipped without causing an error.""" policy = """img-src *; report-uri /csp.cgi""" cspPolicy = PolicyParser(strict=True, ignoredTypes=("report-uri", )).parse(policy) assert cspPolicy == Policy([PolicyTest.sampleDirective3]) def testPolicyParser_parse_defaultSrcRewriting(self): """The default directive is used for each type that is not specifically defined (if the flag is enabled).""" policy = """default-src 'self' http://seclab.nu; connect-src 'self' https://abc.seclab.nu/path chrome-extension:""" cspPolicy = PolicyParser(expandDefaultSrc=True, defaultSrcTypes=("img-src", "connect-src")).parse(policy) assert cspPolicy == Policy([ PolicyTest.sampleDirective5, Directive("img-src", [ PolicyTest.sampleSourceExpression1, PolicyTest.sampleSourceExpression2 ]) ]) def testPolicyParser_parse_noDefaultSrcRewriting(self): policy = """default-src 'self' http://seclab.nu""" cspPolicy = PolicyParser(expandDefaultSrc=False, defaultSrcTypes=("img-src", "connect-src")).parse(policy) assert cspPolicy == Policy([ Directive("default-src", [ PolicyTest.sampleSourceExpression1, PolicyTest.sampleSourceExpression2 ]) ]) def testPolicyParser_parse_duplicates(self): """The CSP standard mandates that only the first directive of each type should be used.""" duplicatePolicy = """connect-src 'self' chrome-extension: https://abc.seclab.nu/path; """ \ + """font-src 'self' http://seclab.nu; """ \ + """connect-src 'self' https://example.com""" cspPolicy = PolicyParser().parse(duplicatePolicy) assert cspPolicy == Policy([ PolicyTest.sampleDirective5, Directive("font-src", [ PolicyTest.sampleSourceExpression1, PolicyTest.sampleSourceExpression2 ]) ]) def testPolicy_combinedPolicy_normal(self): pol1 = Policy([ PolicyTest.sampleDirective6, PolicyTest.sampleDirective2, PolicyTest.sampleDirective3 ]) pol2 = Policy( [PolicyTest.sampleDirective4, PolicyTest.sampleDirective7]) expected = Policy([ PolicyTest.sampleDirective6, PolicyTest.sampleDirective3, Directive("script-src", [ SourceExpression.UNSAFE_EVAL(), SourceExpression.UNSAFE_INLINE() ]) ]) assert pol1.combinedPolicy(pol1) == pol1 assert pol2.combinedPolicy(pol2) == pol2 assert pol1.combinedPolicy(pol2) == expected assert pol2.combinedPolicy(pol1) == expected def testPolicy_combinedPolicy_invalidPolicy(self): pol = Policy([ PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2, PolicyTest.sampleDirective3 ]) assert pol.combinedPolicy(Policy.INVALID()) == Policy.INVALID() assert Policy.INVALID().combinedPolicy(pol) == Policy.INVALID() def testPolicy_combinedPolicy_invalidDefaultSrcAndOtherDirective(self): pol1 = Policy( [PolicyTest.sampleDirective1a, PolicyTest.sampleDirective3]) pol2 = Policy([PolicyTest.sampleDirective9]) assert pol1.combinedPolicy(pol2) == Policy.INVALID() assert pol2.combinedPolicy(pol1) == Policy.INVALID() def testPolicy_combinedPolicy_invalidDefaultSrcInOnePolicyOnly(self): pol1 = Policy([PolicyTest.sampleDirective3]) pol2 = Policy([PolicyTest.sampleDirective9]) assert pol1.combinedPolicy(pol2) == Policy.INVALID() assert pol2.combinedPolicy(pol1) == Policy.INVALID() def testPolicy_combinedPolicy_validDefaultSrcOnly(self): """Combination of two policies with default directive is possible only if both policies contain only a default directive.""" pol1 = Policy([PolicyTest.sampleDirective1a]) pol2 = Policy([PolicyTest.sampleDirective9]) expected = Policy([ Directive("default-src", [ PolicyTest.sampleSourceExpression1, SourceExpression.UNSAFE_INLINE() ]) ]) assert pol1.combinedPolicy(pol2) == expected assert pol2.combinedPolicy(pol1) == expected def testPolicy_withoutPaths(self): withPaths = Policy([ PolicyTest.sampleDirective3, PolicyTest.sampleDirective5, PolicyTest.sampleDirective7 ]) withoutPaths = Policy([ PolicyTest.sampleDirective3, PolicyTest.sampleDirective5.withoutPaths(), PolicyTest.sampleDirective7 ]) assert withPaths.withoutPaths() == withoutPaths assert withoutPaths.withoutPaths() == withoutPaths assert Policy.INVALID().withoutPaths() == Policy.INVALID() def testPolicy_withoutPaths_schemeOnly(self): withPaths = Policy( [PolicyTest.sampleDirective3, PolicyTest.sampleDirective5]) withoutPaths = Policy([ PolicyTest.sampleDirective3, PolicyTest.sampleDirective5.withoutPaths(["http"]) ]) assert withPaths.withoutPaths(["http"]) == withoutPaths def testPolicy_asBasicPolicies_single(self): assert Policy.INVALID().asBasicPolicies() == set([]) assert Policy([PolicyTest.sampleDirective1a]).asBasicPolicies() == set( [Policy([PolicyTest.sampleDirective1a])]) def testPolicy_asBasicPolicies_multiple(self): assert Policy( [PolicyTest.sampleDirective1a, PolicyTest.sampleDirective2]).asBasicPolicies() == set([ Policy([PolicyTest.sampleDirective1a]), Policy([PolicyTest.sampleDirective2]) ]) def testPolicy_asBasicPolicies_recursive(self): expected = set( map(lambda direct: Policy((direct, )), PolicyTest.sampleDirective5.asBasicDirectives())) actual = Policy([PolicyTest.sampleDirective5]).asBasicPolicies() assert actual == expected def testPolicy_isBasicPolicy(self): assert Policy.INVALID().isBasicPolicy() == False assert Policy([PolicyTest.sampleDirective6]).isBasicPolicy() == False assert Policy([PolicyTest.sampleDirective1a]).isBasicPolicy() == True assert Policy( [PolicyTest.sampleDirective2, PolicyTest.sampleDirective4]).isBasicPolicy() == False def testPolicy_isBasicNonePolicy(self): assert Policy.INVALID().isBasicNonePolicy() == False assert Policy([PolicyTest.sampleDirective6 ]).isBasicNonePolicy() == False assert Policy([PolicyTest.sampleDirective1a ]).isBasicNonePolicy() == False assert Policy( [PolicyTest.sampleDirective2, PolicyTest.sampleDirective4]).isBasicNonePolicy() == False assert Policy([PolicyTest.sampleDirective4 ]).isBasicNonePolicy() == True def testPolicy_hasDefaultDirective(self): assert Policy.INVALID().hasDefaultDirective() == False assert Policy( [PolicyTest.sampleDirective2, PolicyTest.sampleDirective9]).hasDefaultDirective() == True assert Policy( [PolicyTest.sampleDirective5, PolicyTest.sampleDirective6]).hasDefaultDirective() == False def testPolicy_compareTo_invalid(self): assert Policy.INVALID().compareTo(Policy.INVALID()) == (set([]), set([]), set([])) pol = Policy([PolicyTest.sampleDirective9]) assert pol.compareTo(Policy.INVALID()) == (set([]), set([]), set([])) assert Policy.INVALID().compareTo(pol) == (set([]), set([]), set([])) def testPolicy_compareTo_regular(self): pol1 = Policy( [PolicyTest.sampleDirective7, PolicyTest.sampleDirective8]) pol2 = Policy( [PolicyTest.sampleDirective7, PolicyTest.sampleDirective9]) assert pol1.compareTo(pol2) == (set([ Policy([PolicyTest.sampleDirective7]) ]), set([Policy([PolicyTest.sampleDirective8]) ]), set([Policy([PolicyTest.sampleDirective9])])) assert pol2.compareTo(pol1) == (set([ Policy([PolicyTest.sampleDirective7]) ]), set([Policy([PolicyTest.sampleDirective9]) ]), set([Policy([PolicyTest.sampleDirective8])])) assert pol1.compareTo(pol1) == (set([ Policy([PolicyTest.sampleDirective7]), Policy([PolicyTest.sampleDirective8]) ]), set([]), set([])) def testPolicy_compareTo_recursive(self): pol1 = Policy([PolicyTest.sampleDirective6]) pol2 = Policy( [Directive("style-src", [SourceExpression.UNSAFE_INLINE()])]) assert pol1.compareTo(pol2) == ( set([pol2]), set([ Policy([Directive("style-src", [SelfSourceExpression.SELF()])]) ]), set([]))
def test_remove_path(self): """Checks that the path and query are properly removed from a URI object.""" inputURI = URI("https", "seclab.nu", 443, "/index.html", "query=value") expectedURI = URI("https", "seclab.nu", 443, None, None) assert inputURI.removePath() == expectedURI assert URI.INVALID().removePath() == URI.INVALID()