- Notifications
You must be signed in to change notification settings - Fork85
HTTP security headers for Flask
License
GoogleCloudPlatform/flask-talisman
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Talisman is a small Flask extension that handles setting HTTP headersthat can help protect against a few common web application securityissues.
The default configuration:
- Forces all connects to
https, unless running with debug enabled. - EnablesHTTP Strict TransportSecurity.
- Sets Flask's session cookie to
secure, so it will never be set ifyour application is somehow accessed via a non-secure connection. - Sets Flask's session cookie to
httponly, preventing JavaScriptfrom being able to access its content. CSRF via Ajax uses a separatecookie and should be unaffected. - SetsX-Frame-Optionsto
SAMEORIGINto avoidclickjacking. - SetsX-XSS-Protectionto enable a cross site scripting filter for IE and Safari (note Chrome hasremoved this and Firefox never supported it).
- SetsX-Content-Type-Optionsto prevent content type sniffing.
- Sets a strictContent SecurityPolicyof
default-src: 'self'. This is intended to almost completelyprevent Cross Site Scripting (XSS) attacks. This is probably the onlysetting that you should reasonably change. See theContent Security Policy section. - Sets a strictReferrer-Policyof
strict-origin-when-cross-originthat governs which referrer information should be included withrequests made.
In addition to Talisman, youshould always use a cross-site requestforgery (CSRF) library. It's highly recommended to useFlask-SeaSurf,which is based on Django's excellent library.
Install viapip:
pip install flask-talisman
After installing, wrap your Flask app with aTalisman:
fromflaskimportFlaskfromflask_talismanimportTalismanapp=Flask(__name__)Talisman(app)
There is also a fullExample App.
feature_policy, default{}, see theFeature Policy section.force_https, defaultTrue, forces all non-debug connects tohttps.force_https_permanent, defaultFalse, uses301instead of302forhttpsredirects.frame_options, defaultSAMEORIGIN, can beSAMEORIGIN,DENY, orALLOWFROM.frame_options_allow_from, defaultNone, a string indicatingthe domains that are allowed to embed the site via iframe.strict_transport_security, defaultTrue, whether to send HSTSheaders.strict_transport_security_preload, defaultFalse, enables HSTSpreloading If you register your application withGoogle's HSTS preload list,Firefox and Chrome will never load your site over a non-secureconnection.strict_transport_security_max_age, defaultONE_YEAR_IN_SECS,length of time the browser will respect the HSTS header.strict_transport_security_include_subdomains, defaultTrue,whether subdomains should also use HSTS.content_security_policy, defaultdefault-src: 'self', see theContent Security Policy section.content_security_policy_nonce_in, default[]. Adds a per-request noncevalue to the flask request object and also to the specified CSP header section.I.e.['script-src', 'style-src']content_security_policy_report_only, defaultFalse, whether to setthe CSP header as "report-only" (as Content-Security-Policy-Report-Only)to ease deployment by disabling the policy enforcement by the browser,requires passing a value with thecontent_security_policy_report_uriparametercontent_security_policy_report_uri, defaultNone, a stringindicating the report URI used forCSP violation reportsreferrer_policy, defaultstrict-origin-when-cross-origin, a stringthat sets the Referrer Policy header to send a full URL when performing a same-originrequest, only send the origin of the document to an equally secure destination(HTTPS->HTTPS), and send no header to a less secure destination (HTTPS->HTTP).session_cookie_secure, defaultTrue, set the session cookietosecure, preventing it from being sent over plainhttp.session_cookie_http_only, defaultTrue, set the sessioncookie tohttponly, preventing it from being read by JavaScript.force_file_save, defaultFalse, whether to set theX-Download-Optionsheader tonoopento prevent IE >= 8 to from opening file downloadsdirectly and only save them instead.
Sometimes you want to change the policy for a specific view. Theforce_https,frame_options,frame_options_allow_from, andcontent_security_policy options can be changed on a per-view basis.
fromflaskimportFlaskfromflask_talismanimportTalisman,ALLOW_FROMapp=Flask(__name__)talisman=Talisman(app)@app.route('/normal')defnormal():return'Normal'@app.route('/embeddable')@talisman(frame_options=ALLOW_FROM,frame_options_allow_from='*')defembeddable():return'Embeddable'
The default content security policy is extremely strict and willprevent loading any resources that are not in the same domain as theapplication. Most web applications will need to change this policy.
A slightly more permissive policy is available atflask_talisman.GOOGLE_CSP_POLICY, which allows loading Google-hosted JSlibraries, fonts, and embeding media from YouTube and Maps.
You can and should create your own policy to suit your site's needs.Here's a few examples adapted fromMDN:
This is the default policy. A web site administrator wants all contentto come from the site's own origin (this excludes subdomains.)
csp= {'default-src':'\'self\''}talisman=Talisman(app,content_security_policy=csp)
A web site administrator wants to allow content from a trusted domainand all its subdomains (it doesn't have to be the same domain that theCSP is set on.)
csp= {'default-src': ['\'self\'','*.trusted.com' ]}
A web site administrator wants to allow users of a web application toinclude images from any origin in their own content, but to restrictaudio or video media to trusted providers, and all scripts only to aspecific server that hosts trusted code.
csp= {'default-src':'\'self\'','img-src':'*','media-src': ['media1.com','media2.com', ],'script-src':'userscripts.example.com'}
In this example content is only permitted from the document's originwith the following exceptions:
- Images may loaded from anywhere (note the
*wildcard). - Media is only allowed from media1.com and media2.com (and not fromsubdomains of those sites).
- Executable script is only allowed from userscripts.example.com.
A web site administrator for an online banking site wants to ensure thatall its content is loaded using SSL, in order to prevent attackers fromeavesdropping on requests.
csp= {'default-src':'https://onlinebanking.jumbobank.com'}
The server only permits access to documents being loaded specificallyover HTTPS through the single origin onlinebanking.jumbobank.com.
A web site administrator of a web mail site wants to allow HTML inemail, as well as images loaded from anywhere, but not JavaScript orother potentially dangerous content.
csp= {'default-src': ['\'self\'','*.mailsite.com', ],'img-src':'*'}
Note that this example doesn't specify ascript-src; with theexample CSP, this site uses the setting specified by thedefault-srcdirective, which means that scripts can be loaded only from theoriginating server.
A web site administrator wants to allow embedded scripts (which mightbe generated dynamicially).
csp= {'default-src':'\'self\'','script-src':'\'self\'',}talisman=Talisman(app,content_security_policy=csp,content_security_policy_nonce_in=['script-src'])
The nonce needs to be added to the script tag in the template:
<scriptnonce="{{ csp_nonce() }}">//...</script>
Note that the CSP directive (script-src in the example) to which the nonce-...source should be added needs to be defined explicitly.
A web site adminstrator wants to override the CSP directives via anenvironment variable which doesn't support specifying the policy asa Python dictionary, e.g.:
export CSP_DIRECTIVES="default-src 'self'; image-src *"python app.py
Then in the app code you can read the CSP directives from the environment:
importosfromflask_talismanimportTalisman,DEFAULT_CSP_POLICYtalisman=Talisman(app,content_security_policy=os.environ.get("CSP_DIRECTIVES",DEFAULT_CSP_POLICY),)
As you can see above the policy can be defined simply just like the officialspecification requires the HTTP header to be set: As a semicolon separatedlist of individual CSP directives.
The default feature policy is empty, as this is the default expected behaviour.Note that the Feature Policy is still a drafthttps://wicg.github.io/feature-policy/but issupported in some form in most browsers.Please note this has beenrenamed Permissions Policyin the latest draft by at this writing, browsers and this extension onlysupports the Feature-Policy HTTP Header name.
Disable access to Geolocation interface.
feature_policy= {'geolocation':'\'none\''}talisman=Talisman(app,feature_policy=feature_policy)
This is not an official Google product, experimental or otherwise.
There is no silver bullet for web application security. Talisman canhelp, but security is more than just setting a few headers. Anypublic-facing web application should have a comprehensive approach tosecurity.
- Apache 2.0 - SeeLICENSE
About
HTTP security headers for Flask
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.