0

I'm toying with a honeypot to catch form spammers. I've hidden a link to a non-existent page in the footer. What I'm attempting to do now is, when they visit that link, to display a form that looks to be a normal WP page for that site. What I have below does that with one exception. I'm getting a lot CORS errors No 'Access-Control-Allow-Origin' errors. So apparently I'm missing something in the wp loading sequence to display a page. Pages loaded the normal way on the site do not display this CORS error.

I've tried adding

  header("Access-Control-Allow-Origin: *");

without success.

Any ideas?

    add_action('parse_request', array($this, 'Check_Incoming'));

    public function Check_Incoming() {
        global $wp;
        $current_url = add_query_arg($wp->query_string, '', home_url($wp->request));
        $parsed = parse_url($current_url);
        if ($parsed['path'] == '/myhiddenform') {
            include_once 'My_Request.php';
            $form = new Form_Show();            
            get_header();
            wp_head();
            $form->show_form();
            get_footer();
            wp_footer();
            die();
        }
    }

Here's the exact errors I'm getting. All seem to be trying to load fontawesome webfonts..


Failed to load resource: net::ERR_FAILED   fontawesome-webfont.ttf:1 

Access to font at 'https://example.com/wp-content/themes/melos/lib/extentions/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0' from origin 'https://www.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
7
  • So the hidden URL looks like https://example.com/myhiddenform? And wp_head() is normally called in the header template, so it's kinda weird you're doing get_header(); wp_head();.. same goes with the get_footer(); wp_footer();..
    – Sally CJ
    Commented Aug 4, 2021 at 15:12
  • Yea, I started with wp_head and wp_footer. They didn't include the template so I added them back in after I found get_header did hoping I'd missed something but I didn't notice any difference. Still had the CORS error. And yes, the actual link to the hidden form looks like <a href="example.com/myhiddenform" /></a> with the theory that bots will find it. I just echo that out in a wp_footer hook. Somewhere in the parsing the trailing slash gets stripped.
    – uPrompt
    Commented Aug 5, 2021 at 1:38
  • Well, looks like stack exchange stripped a lot of that url out. It has https:// and a trailing slash.
    – uPrompt
    Commented Aug 5, 2021 at 1:45
  • How did you find out about the CORS errors? If you do if ($parsed['path'] == '/myhiddenform') { echo 'test'; die(); }, are you still getting the same errors? Have you tried clearing your caches and disabling caching just for a while?
    – Sally CJ
    Commented Aug 5, 2021 at 10:05
  • 1
    I THINK I've found the problem. The font is located at example.com/path and the origin is apparently www.example.com/path. I was using www.example.com/path to access it and I'm guessing the browser is seeing the www as a subdomain. Since it's not in the .htaccess, it's blocking it as being cross domain, which is damned silly. As soon as I got chrome to actually use example.com without the www, the errors went away. Thanks for helping me noodle through this! This was not the solution I was expecting. I was sure there was some wp event I was failing to load.
    – uPrompt
    Commented Aug 5, 2021 at 13:39

1 Answer 1

1

So apparently I'm missing something in the wp loading sequence to display a page.

Not exactly, or that your code is good in terms of parsing the request.

And I don't know why you need the add_query_arg() below, but this:

public function Check_Incoming() {
    global $wp;
    $current_url = add_query_arg($wp->query_string, '', home_url($wp->request));
    $parsed = parse_url($current_url);
    if ($parsed['path'] == '/myhiddenform') {

Could be simplified like so:

public function Check_Incoming( $wp ) {
    if ( 'myhiddenform' === $wp->request ) {

Now here's why are you getting the CORS error

  1. Font Awesome uses web fonts (loaded via @font-face), and web font requests are subject to the same-origin policy; and

  2. You accessed the page with the www prefix (https://www.example.com/myhiddenform) and yet the web font URL did not have that prefix (https://example.com/.../fontawesome-webfont.ttf?v=4.7.0), which means the hostname didn't match, i.e. www.example.com and example.com do not match — yes, they actually pointed to the same domain, but in CORS context, they are different.

    And because the resource did not have the Access-Control-Allow-Origin header, then that consequently caused the browser to not load the font and instead throw the CORS error.

How to solve the problem

Any of these would work, but you should use functions like get_template_directory_uri() to output the link to your CSS file.

  • The CORS error says, No 'Access-Control-Allow-Origin' header is present on the requested resource, hence just set the header on the requested web font. :)

    I.e. Make sure the server sets the header when the example.com/.../fontawesome-webfont.ttf (with or without the www) is requested.

    And with .htaccess, you can do it like so (credits to this answer on Stack Overflow):

    <FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
        <IfModule mod_headers.c>
            Header set Access-Control-Allow-Origin "*"
        </IfModule>
    </FilesMatch>
    
  • Redirect all requests to www.example.com/* to example.com/*, or vice-versa depending on your canonical domain, i.e. whether your "Site Address (URL)" setting has the www prefix or not.

    And with .htaccess, you can do it like so (credits to this answer on Stack Overflow):

    # Add at the top in your .htaccess file. I.e. Above the BEGIN WordPress line.
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{HTTP_HOST}#%{HTTPS}s ^www\.(.+?)\.?#(?:on(s)|)
        RewriteRule ^ http%2://%1%{REQUEST_URI} [R=301,L]
    </IfModule>
    

    But actually, WordPress has a redirect_canonical() function which will do the above redirection, however, that won't happen in your case since the function is hooked onto template_redirect which runs after (but not immediately after) the parse_request hook.

Another possible solution

  • Use absolute path (i.e. without the domain) when linking to your (Font Awesome) CSS files.

    So for example:

    <!-- Use this: -->
    <link rel="stylesheet" href="/wp-content/themes/melos/.../your-file.css" />
    
    <!-- And not this: -->
    <link rel="stylesheet" href="https://example.com/wp-content/themes/melos/.../your-file.css" />
    

    But in WordPress, CSS files should be loaded using wp_enqueue_style(), and although you can use absolute paths, WordPress will actually turn the URL into a fully-qualified one (with the domain) when WordPress generates the <link> tag, hence the same problem would still happen.

    Therefore you should just set the CORS header, or redirect the www to non-www (or vice-versa), or both.

Additional Notes

  • When outputting the hidden link, you should use WordPress functions like home_url() like so: <a href="<?php echo home_url( '/myhiddenform/' ); ?>">...</a>.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.