[Ortus Community General] Still Getting 403 Errors When Updating Posts

Last week I was getting 403 response errors when trying to create a post with sample code. I heard reports on Slack that other users were experiencing something similar.

This week, I no longer get 403 errors when creating a new post. However, when I try to edit a post that has code in it, I get the dreaded 403 error again. I’m not sure if this is a cloudflare issue, or something internal with the Ortus Community app.

To replicate:

  1. Create a new post with some CFML code in it.
  2. Save the post
  3. Edit the post by clicking on the pencil. Make any change.
  4. Try to save again.

Result: You will get a 403 error popup.

// test

Can you post a screenshot of the error you get so we can see where it’s coming from?

@bdw429s
It seems to depend on the post content. I think some words or code combinations are triggering the 403.

Screenshot:

image

What is in the HTTP response body? Any additional information or errors? If you can find a specific bit of text that causes it, let us know. Discourse has a handful of spam filters and I assume you’re hitting one of them, but it’s hard to say. It’s still not clear if you’re being blocked by Discourse or by a CloudFlare firewall setting. The HTTP response headers on the 403 may also provide information.

Payload:

curl ^"https://community.ortussolutions.com/posts/42317^" ^
  -X ^"PUT^" ^
  -H ^"accept: */*^" ^
  -H ^"accept-language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7^" ^
  -H ^"cache-control: no-cache^" ^
  -H ^"content-type: application/x-www-form-urlencoded; charset=UTF-8^" ^
  -b ^"cfid=2e7fc1e2-c5b4-485c-8f1f-ebb8c9a7247c; cftoken=0; _ga=GA1.1.895443904.1732144089; _gcl_au=1.1.1598248588.1742503621; _ga_GWPRZ7PQV6=GS1.1.1742528571.3.0.1742528571.60.0.0; _ga_663JFQ7YGX=GS1.1.1742528571.11.0.1742528571.0.0.0; _t=Erp6fP0RPZdC9JzLlwxTPi^%^2FtD776lS^%^2B1HxZ5V1UzKEOTOaWKUC5kemFUtVmMKsLP^%^2B^%^2FlTYiTlnWeYVrX3NELi1Am5CYM34y4VEQtfNLzZJB4GS9TDIQxwg3alQga3gtLC5vBdnQIakXfsIU7cPGui06YGnKIJnE51p35ZM0tkbbgVtYOklLks7Bg8UPML9aFAw1z3YHYqb1hRwOc757B72^%^2FDzU2arzdgZaGI^%^2FkIZ8QWsV32TfpMxJBYsT^%^2FdTHSPBSBTD6bMZdjTxbVtbBrgmAz^%^2FPILPqFRVEJXnX3YEDqTr^%^2Bute0lDVutCw^%^3D^%^3D--ZBZHsfgvl25feEUC--Q2jUJVB24dxs^%^2BV8m6YvdQQ^%^3D^%^3D; cf_clearance=bhdU6mv6SeNUz8wkIBNdEBFOUFYd2JQ118pSX2vtLTE-1743448972-1.2.1.1-RQ36p_WK6xODkG_F45BAbVGwqcYp2TOCccP9wuEsKQcnuzEDXmSDY325ZMULVJFLMXJE3d.LSbeeRtatK2t.cWbhn_Qz8BACMKLxJbt_TAirOdjf__10ONTGEI4qnweFYjwPXuRISpJObtY2JP72oAyKFef8FQKHURI2cNuJVpYmwje9yHHnRkihy9yfdKDpZo3BBUpLCm.Xo_R36ZMbxdBirXIkR1yAkS47gieYtAKqzhZJ1r5gxU1Pc4pJrYfPEaSu3nMljjIhETu8NuC1DIzKI.kQzmPFMfXNMg5yG.OUl0G3J98lmwnjbiCWe4qOW2YRKKm43NS3cWFzvyNLjXIzZJdy0JcZRRdXF3Jvbh0; _forum_session=x36COr^%^2BkrQ7ly7RXbSlJGBwPhTlOiVd9lzOJSRKKsP6P99CD^%^2FD2nWHgw^%^2BmD9crDl8j4^%^2F9wU11xha8tt6oPE2tO5MsDmGzygZ90GDQ8UX2IVQILDz1FiChlYN07W1J9^%^2FeGtb7O8uDBUFDHOAZtAEtuw7THDzpGsVpO6w6^%^2B^%^2B9gtZgVEDs3uQVzkVIbIem5t5hKYzoqlxQwubW7QqtgHUt6d4BzZU1ScTDpun6gZoHWOJ6lDBLIbnNLZDGX6CAzV2tNDeMS5MhS3B55qwblarXg0Rav4vZZnJ5bDMJpWS^%^2FNoeIhZLjw8rQN1MbUASmnlQy8FqhGgt8cl5Ap9K5qeGfJh06apzKCDTqaT9oiVAE8GAsaS^%^2B0BW1^%^2FXOm2uRc8UcA^%^3D^%^3D--9^%^2FY34LInLPka11uS--dcQ5yQUCN7QycCcdCi4MtQ^%^3D^%^3D^" ^
  -H ^"discourse-logged-in: true^" ^
  -H ^"discourse-present: true^" ^
  -H ^"dnt: 1^" ^
  -H ^"origin: https://community.ortussolutions.com^" ^
  -H ^"pragma: no-cache^" ^
  -H ^"priority: u=1, i^" ^
  -H ^"referer: https://community.ortussolutions.com/t/coldbox-7-optimal-way-to-get-current-http-status-code/10632^" ^
  -H ^"sec-ch-ua: ^\^"Chromium^\^";v=^\^"134^\^", ^\^"Not:A-Brand^\^";v=^\^"24^\^", ^\^"Google Chrome^\^";v=^\^"134^\^"^" ^
  -H ^"sec-ch-ua-mobile: ?0^" ^
  -H ^"sec-ch-ua-platform: ^\^"Windows^\^"^" ^
  -H ^"sec-fetch-dest: empty^" ^
  -H ^"sec-fetch-mode: cors^" ^
  -H ^"sec-fetch-site: same-origin^" ^
  -H ^"user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36^" ^
  -H ^"x-csrf-token: cf05csl3WNndIlxtkoJjUboSW7xzqcHE_SMA4J2y7UilK0sqNocdtpDiaSRtquQFD7-JwKEt3xTrKKBQeji_2Q^" ^
  -H ^"x-requested-with: XMLHttpRequest^" ^
  --data-raw ^"post^%^5Bedit_reason^%^5D=^&post^%^5Bcooked^%^5D=^%^0A++++++++^%^3Cp^%^3EIn+Coldbox+7^%^2C+what+is+the+optimal+way+to+get+the+current+HTTP+status+code+from+within+a+layout^%^3F^%^3C^%^2Fp^%^3E^%^0A^%^3Cp^%^3EI+know+handlers+can+set+HTTP+status+codes+like+this^%^3A^%^3C^%^2Fp^%^3E^%^0A^%^3Cpre^%^3E^%^3Ccode+class^%^3D^%^22hljs+language-csharp^%^22+data-highlighted^%^3D^%^22yes^%^22^%^3E^%^3Cspan+class^%^3D^%^22hljs-keyword^%^22^%^3Eevent^%^3C^%^2Fspan^%^3E.setHTTPHeader(+^%^3Cspan+class^%^3D^%^22hljs-string^%^22^%^3E^%^22400^%^22^%^3C^%^2Fspan^%^3E^%^2C+^%^3Cspan+class^%^3D^%^22hljs-string^%^22^%^3E^%^22Bad+Request^%^22^%^3C^%^2Fspan^%^3E+)^%^3B+^%^0A^%^3C^%^2Fcode^%^3E^%^3C^%^2Fpre^%^3E^%^0A^%^3Cp^%^3EHowever^%^2C+once+it^%^E2^%^80^%^99s+set^%^2C+how+can+you+get+it^%^3F^%^3C^%^2Fp^%^3E^%^0A^%^3Cp^%^3ECalling+^%^3Ccode^%^3Eevent.getHttpHeader(+^%^22statusCode^%^22+)^%^3C^%^2Fcode^%^3E+only+returns+an+empty+string.^%^3C^%^2Fp^%^3E^%^0A^%^3Cp^%^3EIf+it+doesn^%^E2^%^80^%^99t+already+exist^%^2C+I+feel+like+there+should+be+a+convenience+method+within+^%^3Ccode^%^3Eevent^%^3C^%^2Fcode^%^3E+called+^%^3Ccode^%^3EgetHttpStatusCode()^%^3C^%^2Fcode^%^3E+which+could+tap+into+the+^%^3Ccode^%^3EpageContext()^%^3C^%^2Fcode^%^3E+to+get+the+currently+set+^%^3Ccode^%^3EstatusCode^%^3C^%^2Fcode^%^3E^%^3C^%^2Fp^%^3E^%^0A++++^&post^%^5Braw^%^5D=In+Coldbox+7^%^2C+what+is+the+optimal+way+to+get+the+current+HTTP+status+code+from+within+a+layout^%^3F+^%^0A^%^0AI+know+handlers+can+set+HTTP+status+codes+like+this^%^3A^%^0A^%^60^%^60^%^60^%^0Aevent.setHTTPHeader(+^%^22400^%^22^%^2C+^%^22Bad+Request^%^22+)^%^3B+^%^0A^%^60^%^60^%^60^%^0A^%^0AHowever^%^2C+once+it's+set^%^2C+how+can+you+get+it^%^3F^%^0A^%^0ACalling+^%^60event.getHttpHeader(+^%^22statusCode^%^22+)^%^60+only+returns+an+empty+string.^%^0A^%^0AIf+it+doesn't+already+exist^%^2C+I+feel+like+there+should+be+a+convenience+method+within+^%^60event^%^60+called+^%^60getHttpStatusCode()^%^60+which+could+tap+into+the+^%^60pageContext()^%^60+to+get+the+currently+set+^%^60statusCode^%^60^&post^%^5Btopic_id^%^5D=10632^&post^%^5Braw_old^%^5D=In+Coldbox+7^%^2C+what+is+the+optimal+way+to+get+the+current+HTTP+status+code+from+within+a+layout^%^3F+^%^0A^%^0AI+know+handlers+can+set+HTTP+status+codes+like+this^%^3A^%^0A^%^60^%^60^%^60^%^0Aevent.setHTTPHeader(+^%^22400^%^22^%^2C+^%^22Bad+Request^%^22+)^%^3B+^%^0A^%^60^%^60^%^60^%^0A^%^0AHowever^%^2C+once+it's+set^%^2C+how+can+you+get+it^%^3F^%^0A^%^0ACalling+^%^60event.getHttpHeader(+^%^22statusCode^%^22+)+only+returns+an+empty+string.^%^0A^%^0AIf+it+doesn't+already+exist^%^2C+I+feel+like+there+should+be+a+convenience+method+within+^%^60event^%^60+called+^%^60getHttpStatusCode()^%^60+which+could+tap+into+the+^%^60pageContext()^%^60+to+get+the+currently+set+^%^60statusCode^%^60^"

Parsed Payload:

You asked me about the response body. My mistake. I can’t post it here without triggering another 403 error.

https://pastecode.io/s/6t5810rw

yeah, that 403 page looks like a CloudFlare robot challenge. But since it’s hitting the Ajax call, the browser doesn’t display it to you, it just causes a JS error. I’ve seen CloudFlare throwing more of these recently. @lmajano did you crank down some sort of setting in cloud flare recently? We’ve got to back it off a little so people can use the forums.

I tried to look in CF’s logs to see if it showed why it was blocking these requests, but I wasn’t able to find anything using the last IP address you logged in from.

Ok, that last post was able to reproduce this. The ironic thing is there is a “report” header coming from CloudFlare

{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=QfcFOuXAl53%2BVU133Cynv5y%2F5ODGJFG56nkcwh24JN8WSffw5MR%2FV8NgPcYzKB3P9M4Gn4uwhFo8nZtpCX8Y7L99GwXFUPYFsrPNYaTcbP%2BFUzYzOZMlEsobjVt8DZj5yaXe910U2OVdm6NL7p8%3D"}],"group":"cf-nel","max_age":604800}

but when I visit that URL, I get a 405 :roll_eyes:

Ok, I relaxed the CloudFlare WAF rules on ortussolutions.com to not apply to the community subdomain and I’m able to post your example text which was blocked before. Can you please test now as well?

1 Like

That seems to have worked! I was able to make an edit to the post, which triggered the original 403.

Thank you!

Cool, CloudFlare showed the “managed rule set” was updated 12 days ago, though I’m not clear if someone at Ortus modified it, or if CloudFlare simply updated it to be more strict. I was able to find some CF logs that showed my test requests being blocked, but it didn’t tell me what specific rule was being triggered. Simple that it was a “managed rule” in the WAF. Whatever that means, lol.

1 Like