], 'font-src': [ 'self', 'fonts.googleapis.com', 'fonts.gstatic.com', ] } }) sh.update({'HSTS': { 'max-age': 15768000, 'includeSubDomains': True, }}) #don't set public key pins sh.rewrite({'HPKP': None}) @app.route('/logout') @oidc.oidc_logout def logout(): return "You've been successfully logged out." @app.route('/info') @sh.wrapper() @oidc.oidc_auth def info(): """Return the JSONified user session for debugging.""" return jsonify(id_token=session['id_token'], access_token=session['access_token'],
) sh.update( { 'HSTS': { 'max-age': 15768000, 'includeSubDomains': True, } } ) #don't set public key pins sh.rewrite( { 'HPKP': None } ) @app.route('/logout') @oidc.oidc_logout def logout(): return "You've been successfully logged out." @app.route('/info') @sh.wrapper() @oidc.oidc_auth def info(): """Return the JSONified user session for debugging.""" return jsonify( id_token=session['id_token'],
if 'DYNO' in os.environ: sslify = SSLify(app) # Load security headers. sh = Secure_Headers() sh.rewrite({ 'CSP': { 'connect-src': [ 'self', ], 'img-src': [ 'self', ], 'object-src': [ 'self', ], 'script-src': [ 'self', ], 'style-src': [ 'self', ], }, 'X-Permitted-Cross-Domain-Policies': None, 'HPKP': None, }) # Log in with a fake account if set up. This is an easy way to test # without requiring authentication. fake_account = None
class TestAppUseCase(TestHeaders): """ test header creation in flask app """ def setUp(self): self.app = Flask(__name__) self.sh = Secure_Headers() def test_defaults(self): """ test header wrapper with default headers """ @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-XSS-Protection'),'1; mode=block') self.assertEquals(result.headers.get('Strict-Transport-Security'),'includeSubDomains; max-age=31536000') self.assertEquals(result.headers.get('Public-Key-Pins'),'includeSubDomains; report-uri=/hpkp_report; max-age=5184000') self.assertEquals(result.headers.get('X-Content-Type-Options'),'nosniff') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('X-Download-Options'),'noopen') self.assertEquals(result.headers.get('X-Frame-Options'),'sameorigin') self.assertHeaderEquals(result.headers.get('Content-Security-Policy'),"report-uri /csp_report; default-src 'self'") def test_update_function(self): """ test config update function """ self.sh.update( { 'X_Permitted_Cross_Domain_Policies':{'value':'all'}, 'CSP':{'script-src':['self','code.jquery.com']}, 'HPKP':{'pins':[{'sha256':'test123'},{'sha256':'test2256'}]} } ) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'all') self.assertEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com; report-uri /csp_report; default-src 'self'") self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test123; pin-sha256=test2256; includeSubDomains; report-uri=/hpkp_report; max-age=5184000") def test_rewrite_function(self): """ test config rewrite function """ self.sh.rewrite( { 'CSP':{'default-src':['none']}, 'HPKP':{'pins':[{'sha256':'test123'}]} } ) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('Content-Security-Policy'),"default-src 'none'") self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test123") def test_wrapper_update_function(self): """ test updating policies from wrapper """ self.sh.rewrite( { 'CSP':{'default-src':['none']}, 'HPKP':{'pins':[{'sha256':'test123'}]} } ) @self.app.route('/') @self.sh.wrapper( { 'CSP':{'script-src':['self','code.jquery.com']}, 'X_Permitted_Cross_Domain_Policies':{'value':'none'}, 'X-XSS-Protection':{'value':1,'mode':False}, 'HPKP':{'pins':[{'sha256':'test2256'}]}, } ) def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertHeaderEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com; default-src 'none'") self.assertEquals(result.headers.get('X-XSS-Protection'),'1') self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test2256; pin-sha256=test123") @self.app.route('/test') @self.sh.wrapper({'CSP':{'script-src':['nonce-1234']}}) def test(): return "hi" with self.app.test_client() as c: result = c.get('/test') self.assertHeaderEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com 'nonce-1234'; default-src 'none'") def test_passing_none_value_rewrite(self): """ test removing header from update/rewrite """ self.sh.rewrite({'CSP':None,'X_XSS_Protection':None}) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('CSP'),None) self.assertEquals(result.headers.get('X-XSS-Protection'),None) def test_passing_none_value_wrapper(self): """ test removing policy from wrapper """ @self.app.route('/') @self.sh.wrapper({'CSP':None,'X-XSS-Protection':None}) def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('CSP'),None) self.assertEquals(result.headers.get('X-XSS-Protection'),None)
class TestAppUseCase(unittest.TestCase): """ test header creation in flask app """ def setUp(self): self.app = Flask(__name__) self.sh = Secure_Headers() def test_defaults(self): """ test header wrapper with default headers """ @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-XSS-Protection'),'1; mode=block') self.assertEquals(result.headers.get('Strict-Transport-Security'),'includeSubDomains; max-age=31536000') self.assertEquals(result.headers.get('Public-Key-Pins'),'includeSubDomains; report-uri=/hpkp_report; max-age=5184000') self.assertEquals(result.headers.get('X-Content-Type-Options'),'nosniff') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('X-Download-Options'),'noopen') self.assertEquals(result.headers.get('X-Frame-Options'),'sameorigin') self.assertEquals(result.headers.get('Content-Security-Policy'),"report-uri /csp_report; default-src 'self'") def test_update_function(self): """ test config update function """ self.sh.update( { 'X_Permitted_Cross_Domain_Policies':{'value':'all'}, 'CSP':{'script-src':['self','code.jquery.com']}, 'HPKP':{'pins':[{'sha256':'test123'},{'sha256':'test2256'}]} } ) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'all') self.assertEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com; report-uri /csp_report; default-src 'self'") self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test123; pin-sha256=test2256; includeSubDomains; report-uri=/hpkp_report; max-age=5184000") def test_rewrite_function(self): """ test config rewrite function """ self.sh.rewrite( { 'CSP':{'default-src':['none']}, 'HPKP':{'pins':[{'sha256':'test123'}]} } ) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('Content-Security-Policy'),"default-src 'none'") self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test123") def test_wrapper_update_function(self): """ test updating policies from wrapper """ self.sh.rewrite( { 'CSP':{'default-src':['none']}, 'HPKP':{'pins':[{'sha256':'test123'}]} } ) @self.app.route('/') @self.sh.wrapper( { 'CSP':{'script-src':['self','code.jquery.com']}, 'X_Permitted_Cross_Domain_Policies':{'value':'none'}, 'X-XSS-Protection':{'value':1,'mode':False}, 'HPKP':{'pins':[{'sha256':'test2256'}]}, } ) def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com; default-src 'none'") self.assertEquals(result.headers.get('X-XSS-Protection'),'1') self.assertEquals(result.headers.get('Public-Key-Pins'),"pin-sha256=test2256; pin-sha256=test123") @self.app.route('/test') @self.sh.wrapper({'CSP':{'script-src':['nonce-1234']}}) def test(): return "hi" with self.app.test_client() as c: result = c.get('/test') self.assertEquals(result.headers.get('Content-Security-Policy'),"script-src 'self' code.jquery.com 'nonce-1234'; default-src 'none'") def test_passing_none_value_rewrite(self): """ test removing header from update/rewrite """ self.sh.rewrite({'CSP':None,'X_XSS_Protection':None}) @self.app.route('/') @self.sh.wrapper() def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('CSP'),None) self.assertEquals(result.headers.get('X-XSS-Protection'),None) def test_passing_none_value_wrapper(self): """ test removing policy from wrapper """ @self.app.route('/') @self.sh.wrapper({'CSP':None,'X-XSS-Protection':None}) def index(): return "hi" with self.app.test_client() as c: result = c.get('/') self.assertEquals(result.headers.get('X-Permitted-Cross-Domain-Policies'),'none') self.assertEquals(result.headers.get('CSP'),None) self.assertEquals(result.headers.get('X-XSS-Protection'),None)