1

I am having trouble implementing CSP with nonce and I'm not understanding what I am doing wrong. I am able to execute local scripts which I'm assuming is allowed the the 'self' parameter. However when I try to submit a contact form which onsubmit execute a return on a js function that sends a post request to a php file to send a email it apparently qualifies as an inline script execution and get blocked by CSP. I have tried to implement nonce in various ways but I'm just not understanding how to enable its execution without using 'unsafe-inline'. Any help would be appreciated. I'm using the following code:

I am specifically getting an error for inline executing from the 'script-src' policy

.htaccess

Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-12345678' https://example.com; style-src 'self' 'unsafe-inline'; base-uri 'self'; script-src-elem 'self'; img-src 'self' data:; form-action 'self'; report-to csp-endpoints"

contact.html

<form id="contact_form" onsubmit="return submitForm()" class="form_grid" nonce="12345678>
<script src="/js/contact.js" nonce="12345678"></script>

contact.js

function submitForm(e) { 
    
    // do stuff
    
    const request = new XMLHttpRequest();
    request.open("POST", "php/email.php", true);
    request.setRequestHeader("Content-type", "application/json");
    request.onload = function () {
        if (request.status >= 200 && request.status < 400) {
            const resp = request.responseText;
            const data = JSON.parse(resp);
            alert(`Thank you ${data.name} for your message. We will get back to you at ${data.email} as soon as possible.`);
        } else {
            alert("Something went wrong. Please try again later.");
            console.log(request.responseText);
        }
    };
    request.onerror = function () {
        alert("An error occured. Please try again later.");
    };

    const data = JSON.stringify({
        name,
        email,
        goal,
        itsatrap,
        requirements,
        integrations,
        features,
        guidelines
    });
    request.send(data);
    return false;
  }
}

email.php

<?php
   // do stuff
   header('Content-Type: application/json');
   if (mail($recipient, $subject, $email_content, $email_headers)) {
     http_response_code(200);
     $json = array("success" => true, "message" => "Thank You! Your message has been sent.", "name" => $name, "email" => $email);
     echo json_encode($json, JSON_PRETTY_PRINT);
     exit;
   } else {
     http_response_code(500);
     $json = array("success" => false, "message" => "Oops! Something went wrong and we couldn't send your message.", "reason" => error_get_last());
     echo json_encode($json, JSON_PRETTY_PRINT);
     exit;
   }
1

1 Answer 1

1

Thank you @Sebastian Simon. I am now able to use 'strict-dynamic' I realize now why I was getting the errors. I made the following changes to avoid inline execution.

.htaccess

Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'strict-dynamic' https://example.com; style-src 'self' 'unsafe-inline'; base-uri 'self'; script-src-elem 'self'; img-src 'self' data:; form-action 'self'; report-to csp-endpoints"

contact..html

<form id="contact_form" class="form_grid">
<script src="/js/contact.js"></script>

contact.js

async function submitForm() {
// do stuff 

  const response = await fetch("php/email.php", {
          method: "POST",
          headers: {
              "Content-Type": "application/json"
          },
          body: JSON.stringify(data)
      });
  if (response.ok) {
      const data = await response.json();
      alert(`Thank you ${data.name} for your message. We will get back to you at ${data.email} as soon as possible.`);
      return true;
  } else {
      alert("Something went wrong. Please try again later.");
      console.log(response);
      return false;
  }
}

document.getElementById('contact_form').addEventListener('submit', (e) => {
  e.preventDefault();
  const submitted = submitForm();
  if (submitted) {
      document.getElementById('contact_form').reset();
  }
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.