I’ve had at least two sites get hit with a wave of spam that looks like it’s designed to poison LLMs. The same attack has also been reported here at least once (Anyone else currently undergoing mass spam attack?). The best solution is to set up Discourse AI - Spam detection, which I do recommend, but it’s a bit of a bother. Here’s a stopgap you can implement that will take just a few minutes.
It assumes that you have a unix-like operating system (e.g., linux or mac). If you use Windows and can copy/paste into a terminal, you can ssh to your Discourse server and paste this in.
What it does is create a set of watched words generated from a recent attack that I saw. If you’re handy with nano
or similar, you can edit it before you run it. If not, you can run this script and then delete the words you don’t like with one click per word.
The block words are potentially very annoying since they’ll keep legitimate users from creating posts with those words in them, so take a look to make sure none of those words are likely to appear in legitimate posts on your forum!
Put your site URL, api key, and api user in the boxes below (they’ll be only on your browser–but you can just paste it as it is and edit the file if you prefer) and then copy/paste the code block into a terminal. It will create upload_watched_words_full.sh
and make it executable. You can then run it with ./upload_watched_words_full.sh
.
cat <<'EOF' > upload_watched_words_full.sh
#!/usr/bin/env bash
# Usage: ./upload_watched_words_full.sh
DISCOURSE_URL="=URL="
API_KEY="=API_KEY="
API_USERNAME="=API_USERNAME="
# High-confidence block words
BLOCK_WORDS=(
"customer service number"
"contact number"
"support number"
"refund phone number"
"toll free"
"24/7 support"
"helpline"
"call us"
"live representative"
"technical support"
"lufthansa"
"royal caribbean"
"coinbase"
"robinhood"
"reservation number"
"booking number"
"flight cancellation"
"name change fee"
"║"
"⇆"
"★"
"®️"
"™️"
)
# Medium-risk flag words
FLAG_WORDS=(
"customer service"
"customer support"
"support team"
"help desk"
"hotline"
"agent"
"representative"
"contact us"
"phone support"
"service center"
)
# Require-approval words
REQUIRE_APPROVAL_WORDS=(
"urgent"
"immediate action"
"act now"
"limited time"
"exclusive offer"
"approve this"
"verify account"
)
# Function to send words in batch
add_words () {
local ACTION="$1"
shift
local WORDS=("$@")
# Build words[] parameters
local DATA=""
for w in "${WORDS[@]}"; do
DATA+="words%5B%5D=$(printf '%s' "$w" | jq -s -R -r @uri)&"
done
DATA+="replacement=&action_key=${ACTION}&case_sensitive=false&html=false"
echo "Uploading ${ACTION} words..."
curl -s -X POST "${DISCOURSE_URL}/admin/customize/watched_words.json" \
-H "Api-Key: ${API_KEY}" \
-H "Api-Username: ${API_USERNAME}" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "$DATA"
echo -e "\nDone."
}
# Upload block words
add_words "block" "${BLOCK_WORDS[@]}"
# Upload flag words
add_words "flag" "${FLAG_WORDS[@]}"
# Upload require-approval words
add_words "require_approval" "${REQUIRE_APPROVAL_WORDS[@]}"
EOF
# Make the script executable
chmod +x upload_watched_words_full.sh
echo "Script 'upload_watched_words_full.sh' created and made executable."