mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-07 19:21:30 +00:00
fix: catch punctuation-separated slurs in username censor
Re-add skipNonAlphabeticTransformer to both matcher chains so bypass attempts like "n.i.g.g.e.r" are detected.
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
|||||||
pattern,
|
pattern,
|
||||||
resolveConfusablesTransformer,
|
resolveConfusablesTransformer,
|
||||||
resolveLeetSpeakTransformer,
|
resolveLeetSpeakTransformer,
|
||||||
|
skipNonAlphabeticTransformer,
|
||||||
toAsciiLowerCaseTransformer,
|
toAsciiLowerCaseTransformer,
|
||||||
} from "obscenity";
|
} from "obscenity";
|
||||||
import countries from "resources/countries.json";
|
import countries from "resources/countries.json";
|
||||||
@@ -71,15 +72,21 @@ export function createMatcher(bannedWords: string[]): RegExpMatcher {
|
|||||||
];
|
];
|
||||||
// substringMatcher: literal patterns, no collapse — catches "niggertesting" as a substring
|
// substringMatcher: literal patterns, no collapse — catches "niggertesting" as a substring
|
||||||
// collapseMatcher: deduped patterns + collapse transformer — catches "niiiigger", "hiiitler"
|
// collapseMatcher: deduped patterns + collapse transformer — catches "niiiigger", "hiiitler"
|
||||||
|
// skipNonAlphabeticTransformer is applied last to catch punctuation-separated bypasses
|
||||||
|
// like "n.i.g.g.e.r".
|
||||||
const substringMatcher = new RegExpMatcher({
|
const substringMatcher = new RegExpMatcher({
|
||||||
...buildDataset(bannedWords, false),
|
...buildDataset(bannedWords, false),
|
||||||
blacklistMatcherTransformers: baseTransformers,
|
blacklistMatcherTransformers: [
|
||||||
|
...baseTransformers,
|
||||||
|
skipNonAlphabeticTransformer(),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
const collapseMatcher = new RegExpMatcher({
|
const collapseMatcher = new RegExpMatcher({
|
||||||
...buildDataset(bannedWords, true),
|
...buildDataset(bannedWords, true),
|
||||||
blacklistMatcherTransformers: [
|
blacklistMatcherTransformers: [
|
||||||
...baseTransformers,
|
...baseTransformers,
|
||||||
collapseDuplicatesTransformer(),
|
collapseDuplicatesTransformer(),
|
||||||
|
skipNonAlphabeticTransformer(),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
|||||||
+16
-5
@@ -114,11 +114,9 @@ describe("UsernameCensor", () => {
|
|||||||
expect(matcher.hasMatch("MyChairName")).toBe(true);
|
expect(matcher.hasMatch("MyChairName")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("detects banned words with underscores/dots/numbers mixed in", () => {
|
test("detects banned words with non-alphabetic characters mixed in", () => {
|
||||||
// These should NOT bypass the filter (skipNonAlphabetic was intentionally removed)
|
expect(matcher.hasMatch("n.i.g.g.e.r")).toBe(true);
|
||||||
// Words separated by non-alpha chars are treated as separate tokens
|
expect(matcher.hasMatch("hi_tler")).toBe(true);
|
||||||
expect(matcher.hasMatch("n.i.g.g.e.r")).toBe(false); // dots break the word
|
|
||||||
expect(matcher.hasMatch("hi_tler")).toBe(false); // underscore breaks it
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("allows clean usernames", () => {
|
test("allows clean usernames", () => {
|
||||||
@@ -141,6 +139,19 @@ describe("UsernameCensor", () => {
|
|||||||
expect(matcher.hasMatch("kkklover")).toBe(true);
|
expect(matcher.hasMatch("kkklover")).toBe(true);
|
||||||
expect(matcher.hasMatch("ilovekkkboys")).toBe(true);
|
expect(matcher.hasMatch("ilovekkkboys")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("catches slurs separated by periods (bypass attempt)", () => {
|
||||||
|
expect(matcher.hasMatch("n.i.g.g.e.r")).toBe(true);
|
||||||
|
expect(matcher.hasMatch("N.I.G.G.E.R")).toBe(true);
|
||||||
|
expect(matcher.hasMatch("n.i.g.g.a")).toBe(true);
|
||||||
|
expect(matcher.hasMatch("h.i.t.l.e.r")).toBe(true);
|
||||||
|
expect(matcher.hasMatch("hello n.i.g.g.e.r world")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("censor replaces period-separated slur usernames", () => {
|
||||||
|
const result = checker.censor("n.i.g.g.e.r", null);
|
||||||
|
expect(shadowNames).toContain(result.username);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("censor", () => {
|
describe("censor", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user