Repository navigation
feat: let AI moderation trust links to configured domains - #299
Open
hiteshkava wants to merge 1 commit into
Open
hiteshkava wants to merge 1 commit into
hiteshkava wants to merge 1 commit into
Conversation
Alam-2U
approved these changes
Oct 16, 2026
The classifier only sees the text of a post, never the course it was posted in, so links that are on topic in a course, such as a learner sharing their pen in a CSS course, read to it as link spam, and the post is flagged and deleted. AI_MODERATION_TRUSTED_LINK_DOMAINS lists domains whose links, including links to their subdomains, are removed from a post before it is classified. A post whose links are all trusted is not classified at all, unless the rest of it offers another way to be contacted or redirected: a link to another domain, an email address, a phone number or a messaging app. Such a post is classified without its trusted links, so a scam that adds a trusted link is still caught. Every skipped post is logged, since it gets no audit log entry. The setting is empty by default, so nothing changes until a deployment lists domains. Links are handled in linear time, because moderation runs inside the request that creates a post and posts have no size limit.
hiteshkava
force-pushed
the
ai-moderation-trusted-links
branch
from
October 20, 2026 07:00
bebd89f to
6b2fefa
Compare
hiteshkava
marked this pull request as ready for review
October 20, 2026 07:02
Author
|
@taimoor-ahmed-1 can you please review this PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds an
AI_MODERATION_TRUSTED_LINK_DOMAINSsetting to the AI moderation from #288. It lets a deployment keep links its learners legitimately share from being classified as spam.The problem
The classifier only sees the text of a post, never the course it was posted in. On edx.org, learners in a CSS course share their work as CodePen links, and those posts were classified as spam and deleted. To the classifier, a post that is mostly a link to another site looks like link spam. Changing the prompt can't fix this reliably, because the classifier doesn't know which links are on topic in a course and its verdicts vary from run to run.
Removing the trusted link isn't always enough. A short post such as
Use this link for registration: <a href="https://zoom.us/meeting/register/…">URL</a>reaches the classifier asUse this link for registration: URL, which it reads as a lure.What this PR does
When a post is moderated:
Links to a trusted domain or its subdomains are removed, whether written as plain URLs (with or without
https://) or as<a href>anchors. An anchor is replaced by its text. The host must end exactly at the trusted domain, socodepen.iomatcheswww.codepen.iobut notcodepen.io.example.comornotcodepen.io.If the post had trusted links and nothing else in it gives readers another way to be contacted or redirected, it is not classified. Any of the following counts as such a way:
http(s)://orwww., a bare domain followed by a path under any TLD (discord.gg/…), or a bare domain under a common TLD (bestessays.com)<img>,<iframe>, …)tutor at gmail dot comHTML entities, full-width letters and invisible characters are undone before this check, so
evil.comandWhat\u200bsApp(with a zero-width space) are still caught.Otherwise, the post is classified as before, without its trusted links. A scam that adds a trusted link next to a phone number is still caught.
Posts without trusted links are unaffected. Links to untrusted domains, including lookalikes such as
codepen.oi, are still judged by the classifier. A false risk match only means the post is classified as it would be today.Every post that skips classification is logged as
AI moderation skipped, only trusted links: <id>, because it gets no audit log entry.The setting is empty by default, so nothing changes until a deployment lists domains.
Linear-time link handling
Moderation runs inside the request that creates a post, and posts have no size limit, so every pattern stays linear on hostile input:
<.With Python 3.12, the whole link handling (stripping plus the risk check) takes:
<a href="https://codepen.io/x">yrepeated, never closed<a href="x"repeated, no>a.repeatedChanges
src/forum/ai_moderation/links.py(new):strip_trusted_links(),is_blank()andhas_risk_signals().src/forum/ai_moderation/service.py: removes trusted links before classification, skips classification as described above, and logs each skip.src/forum/settings/common.py: declaresAI_MODERATION_TRUSTED_LINK_DOMAINS, defaulting to[].docs/how-tos/configure_ai_moderation.rst: documents the setting.Supporting information
The same change is running on edx.org in edx/forum#66 and edx/forum#67. The code is identical, apart from one slice rewritten to satisfy this repository's
pycodestyle(E203). The tests useStubProviderBackendfrom #288 instead of edx.org's provider backend.Testing instructions
docs/how-tos/configure_ai_moderation.rst, with any backend, and add:discussions.enable_ai_moderationanddiscussions.enable_ai_auto_delete_spamfor a test course.My solution: https://codepen.io/<user>/pen/<id> why is the footer not sticky?. The backend is not called, the post stays visible with noModerationAuditLogentry, and the LMS log showsAI moderation skipped, only trusted links: <id>.Guaranteed A grades! WhatsApp +1-555-0199 https://codepen.io/<user>/pen/<id>. The backend is called withGuaranteed A grades! WhatsApp +1-555-0199(the CodePen link removed), and the post is flagged if the backend says spam.https://example.com/offer. It is classified as before.Unit tests:
tests/test_ai_moderation_links.py(90 tests) covers:has_risk_signals(): bare links on any TLD, spelled-out and entity-encoded contacts, zero-width and full-width characters, plus everyday CSS, JavaScript and file paths that must not count as a riskTestAIModerationTrustedLinksintests/test_ai_moderation.py(11 tests) covers the service's behavior.pylint,pycodestyle,pydocstyle,mypy,doc8and the Sphinx build pass.Deadline
None. #288 is merged, and this PR is rebased onto
master.Other information
github.io.Merge checklist:
Check off if complete or not applicable:
Conventional Commits type — they determine the
release:
fix:→ patch,feat:→ minor,!/BREAKING CHANGE:→ major