Skip to content

Commit

Permalink
Merge pull request #24 from juerkkil/basic_unittests
Browse files Browse the repository at this point in the history
basic unittests
  • Loading branch information
juerkkil authored Oct 24, 2024
2 parents 13a3110 + 5195a56 commit 78380e9
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 0 deletions.
Empty file added tests/__init__.py
Empty file.
30 changes: 30 additions & 0 deletions tests/mock_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class MockHTTPResponse:
def __init__(self, sock=None, debuglevel=0, method=None, url=None):
pass

def getheaders(self):
return [
('x-xss-protection', '1;'),
('server', 'nginx')
]

def getsomething(self):
pass


class MockHTTPSConnection:
def __init__(self, h, context, timeout):
pass

def request(self, method, url, headers):
pass

def headers(self):
return "content-type", "accept"

def getresponse(self):
a = MockHTTPResponse()
return a

def close(self):
pass
41 changes: 41 additions & 0 deletions tests/test_securityheaders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from unittest import mock, TestCase
from urllib.parse import ParseResult

from secheaders.securityheaders import SecurityHeaders

from .mock_classes import MockHTTPSConnection


@mock.patch("http.client.HTTPSConnection", MockHTTPSConnection)
class TestSecurityHeaders(TestCase):

def test_init(self) -> None:
secheaders = SecurityHeaders("https://www.example.com", 0)
assert secheaders.target_url == ParseResult(
scheme='https', netloc='www.example.com', path='', params='', query='', fragment='')

def test_fetch_headers(self) -> None:
secheaders = SecurityHeaders("https://www.example.com", 0)
expected_value = {
'server': 'nginx',
'x-xss-protection': '1;',
}
secheaders.fetch_headers()
assert secheaders.headers == expected_value

def test_eval_headers(self) -> None:
secheaders = SecurityHeaders("https://www.example.com", 0)
expected_value = {
'x-frame-options': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'strict-transport-security': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'content-security-policy': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'x-content-type-options': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'x-xss-protection': {'defined': True, 'warn': True, 'contents': '1;', 'notes': []},
'referrer-policy': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'permissions-policy': {'defined': False, 'warn': True, 'contents': None, 'notes': []},
'server': {'defined': True, 'warn': False, 'contents': 'nginx', 'notes': []},
}

secheaders.fetch_headers()
res = secheaders.check_headers()
assert res == expected_value
74 changes: 74 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from unittest import TestCase
from secheaders import utils
from secheaders.constants import EVAL_OK, EVAL_WARN


class TestUtils(TestCase):

def test_csp_parser(self) -> None:
example_csp = (
"default-src 'none' *.example.com; script-src 'self' src.example.com 'unsafe-inline'; connect-src 'self';"
"img-src *; style-src 'self'; base-uri 'self';form-action 'self'"
)
expected_value = {
"default-src": ["'none'", "*.example.com"],
"script-src": ["'self'", "src.example.com", "'unsafe-inline'"],
"connect-src": ["'self'"],
"img-src": ["*"],
"style-src": ["'self'"],
"base-uri": ["'self'"],
"form-action": ["'self'"],
}
res = utils.csp_parser(example_csp)
assert res == expected_value

def test_eval_csp(self) -> None:
unsafe_csp = (
"default-src 'none' *.example.com; script-src 'self' src.example.com 'unsafe-inline'; connect-src 'self';"
"img-src *; style-src 'self'; base-uri 'self';form-action 'self'"
)
res = utils.eval_csp(unsafe_csp)
expected_value = (
EVAL_WARN,
["Unsafe source 'unsafe-inline' in directive script-src"]
)
assert res == expected_value

safe_csp = "default-src 'self'; img-src 'self' cdn.example.com;"
expected_value = (EVAL_OK, [])
res = utils.eval_csp(safe_csp)
assert res == expected_value

def test_eval_version_info(self) -> None:
nginx_banner_warn = 'nginx 1.17.10 (Ubuntu)'
nginx_banner_ok = 'nginx'
res = utils.eval_version_info(nginx_banner_warn)
assert res == (EVAL_WARN, [])
res = utils.eval_version_info(nginx_banner_ok)
assert res == (EVAL_OK, [])

def test_permissions_policy_parser(self) -> None:
example_pp = (
'geolocation=(src "https://a.example.com" "https://b.example.com"), picture-in-picture=(), camera=*;'
)
expected_value = {
'geolocation': ['src', '"https://a.example.com"', '"https://b.example.com"'],
'picture-in-picture': [],
'camera': ['*'],
}
res = utils.permissions_policy_parser(example_pp)
assert expected_value == res

def test_eval_permissions_policy(self) -> None:
unsafe_pp = 'geolocation=(src "https://a.example.com"), picture-in-picture=(), camera=*;'
expected_value = (EVAL_WARN, [
"Privacy-sensitive feature 'camera' allowed from unsafe origin '*'",
"Privacy-sensitive feature 'microphone' not defined in permission-policy, always allowed.",
"Privacy-sensitive feature 'payment' not defined in permission-policy, always allowed.",
])
res = utils.eval_permissions_policy(unsafe_pp)
assert res == expected_value
safe_pp = "geolocation=(src), camera=(), microphone=(), payment=()"
expected_value = EVAL_OK, []
res = utils.eval_permissions_policy(safe_pp)
assert res == expected_value

0 comments on commit 78380e9

Please sign in to comment.