11

I test my website using https://observatory.mozilla.org/analyze and I got F score.

The reasons are:

Content Security Policy (CSP) header not implemented X-XSS-Protection header not implemented X-Frame-Options (XFO) header not implemented ... 

I serve my website using CloudFront.

Where I put those missing headers to CloudFront?

enter image description here

1

4 Answers 4

16

Update 23 June 2021

Just found out that while the solution below seems great, it may not be good enough especially for adding security headers because if Cloudfront gets an error from the origin, the function will not be invoked

HTTP status codes CloudFront does not invoke edge functions for viewer response events when the origin returns HTTP status code 400 or higher.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html


As of May 2021, it seems the better option would be the newly introduced Cloudfront functions which comes at a 1/6th the price of Lambda@Edge as per this blog entry https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/

An example from the documentation at https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-security-headers.html

function handler(event) { var response = event.response; var headers = response.headers; // Set HTTP security headers // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; headers['content-security-policy'] = { value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}; headers['x-content-type-options'] = { value: 'nosniff'}; headers['x-frame-options'] = {value: 'DENY'}; headers['x-xss-protection'] = {value: '1; mode=block'}; // Return the response to viewers return response; } 
Sign up to request clarification or add additional context in comments.

Comments

14

If you are implementing this now then you are in luck. It is much simpler from Nov 2021. Amazon has added security header natively via response header policies ie we don't have to create a lambda for just adding response headers to the application. Details https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-cloudfront-introduces-response-headers-policies/.

Terraform AWS provider have started supporting aws_cloudfront_response_headers_policy from 3.64.0 https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md#3640-november-04-2021.

Here is an example to add security headers to aws cloudfront response via terraform aws provider.

resource "aws_cloudfront_response_headers_policy" "security_headers_policy" { name = "my-security-headers-policy" security_headers_config { content_type_options { override = true } frame_options { frame_option = "DENY" override = true } referrer_policy { referrer_policy = "same-origin" override = true } xss_protection { mode_block = true protection = true override = true } strict_transport_security { access_control_max_age_sec = "31536000" include_subdomains = true preload = true override = true } content_security_policy { content_security_policy = "frame-ancestors 'none'; default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'" override = true } } } 

Comments

7

You can now use CloudFront Response Headers Policies instead of CloudFront Functions to configure CORS, security, and custom HTTP response headers

Edit your CloudFront behaviour and add a response header policy.

You can use the existing SecurityheadersPolicy or create your own policy if you want a different security header configuration.

enter image description here

1 Comment

Is there some magic to make this work? can you look at my question: stackoverflow.com/questions/73751084/…
0

I would recommend using Lambda@Edge to append any headers that you're looking for to your origin response before it is returned to the viewer.

It can be done as simply as the below example when added as a Origin Response event.

 import json def lambda_handler(event, context): response = event["Records"][0]["cf"]["response"] headers = response["headers"] headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload'}]; headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}]; headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}]; headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}]; headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}]; headers['referrer-policy'] = [{key: 'Referrer-Policy', value: 'same-origin'}]; response['headers'] = headers return response 

For more information take a look at the Adding HTTP Security Headers Using Lambda@Edge and Amazon CloudFront blog post.

5 Comments

can I use lambda with this code to run only when request to index.html? Because I don't want to execute this function in other request made such mynewfile.html.
You sure can, although you should maintain security headers for all relevant pages. There is a value of event['Records'][0]['cf']['request']['uri']. You would do an id to check if it was equal to index.html first :)
But I will be charged for the use of this function even though in some cases it will do nothing right?
That's correct, it will charge $0.60 per 1 million requests
@JonSud you would want to create multiple Cache Behaviors in CloudFront and only configure the trigger on behaviors matching pages that need it to run.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.