Open source on GitHub

Keep your repo
🤬 Potty Mouth
free.

A drop-in GitHub Action that scans issues, pull requests, and comments for profane content — then replaces it with the strategy of your choice. Built with .NET Native AOT for instant, dependency-free runs.

MIT licensed · No registration · Works with the built-in GITHUB_TOKEN

.github/workflows/profanity-filter.yml yaml
# .github/workflows/profanity-filter.yml
name: Profanity filter

on:
  issues:
    types: [opened, edited, reopened]
  pull_request:
    types: [opened, edited, reopened]
  issue_comment:
    types: [created, edited]

permissions:
  issues: write
  pull-requests: write

jobs:
  apply-filter:
    runs-on: ubuntu-latest
    steps:
      - name: Scan for profanity
        if: github.actor != 'dependabot[bot]'
        uses: IEvangelist/profanity-filter@main
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          replacement-strategy: emoji
6,500+
Curated words
across the dictionary
28
Languages
globally inclusive
14
Replacement strategies
for every taste
Native AOT
.NET 10 powered
instant cold starts
239K+
Container pulls
trusted from GHCR
See it in action

Live filtering, every keystroke.

A typewriter pours a sentence into the input below — the same logic that runs in the WebApi container then redacts each profane word, side-by-side, in every strategy. No backend, no SignalR — just JavaScript mirroring MatchEvaluators.cs.

potty-mouth · live filter
Input

All 14 strategies — updating live, every keystroke

Identical logic to MatchEvaluators in the WebApi.

  • asterisk

    Asterisk Classic asterisks

  • random-asterisk

    Random asterisk Random count, 1–N

  • middle-asterisk

    Middle asterisk Keep first + last

  • first-letter-then-asterisk

    First letter + asterisk Keep first only

  • vowel-asterisk

    Vowel asterisk Asterisk the vowels

  • emoji

    Emoji Random expressive emoji

  • anger-emoji

    Anger emoji Random anger emoji

  • middle-swear-emoji

    Middle swear emoji First + 🤬 + last

  • bleep

    Bleep Literal "bleep"

  • redacted-rectangle

    Redacted rectangle Solid █ blocks

  • strike-through

    Strike through Wraps in <del>

  • underscores

    Underscores Underscores match length

  • grawlix

    Grawlix Comic-book symbols

  • bold-grawlix

    Bold grawlix Grawlix, but louder

Live, in-browser demonstration of every replacement strategy. A sample sentence containing profane words is typed character-by-character into the input field, and each of the fourteen strategy panels below updates in real time to show how that strategy filters the matched words.
Text alternative — what the live demo shows
  1. A typewriter animation enters a sample sentence (e.g. This shit is broken, what the hell are we doing here?) into the input panel at the top, one character at a time.
  2. Beneath the input is a grid of 14 cards, one per replacement strategy. Each card shows the strategy's slug, a friendly label, and a one-line description.
  3. On every keystroke, every card re-renders the input with that card's strategy applied. Profane words are matched as whole words (case-insensitive).
  4. The moment the input contains a completed profane word, a GitHub-style profane content 🤬 label appears above the input — emulating the label the GitHub Action applies to flagged issues and pull requests. It links to the label documentation, and disappears again if the input clears to something clean.
  5. For example: asterisk turns shit into ****, middle-asterisk turns it into s**t, bleep replaces it with the literal word bleep, and middle-swear-emoji turns it into s🤬t.
  6. When the sentence finishes typing, the demo pauses briefly, clears, and starts typing a new sentence. The toggle button in the top-right lets you pause or resume the animation.
  7. The filtering logic is a faithful port of MatchEvaluators.cs in the .NET library — the same code that powers the GitHub Action and the WebApi container.

Prefer the original SignalR-driven recording? It now lives next to the WebApi container README — same Aspire AppHost in playground/apphost.cs, streaming text over a SignalR hub and client.

Why bother?

Not every contributor is sunshine and rainbows .

Open source is a public-facing space, and the tone of a project sets the tone of its community. Potty Mouth quietly catches the rough edges — rewriting profane content, flagging the issue, and leaving a clean audit trail behind — so you can keep building without playing comment-thread cop.

With this action in your workflow, your repo can be 🌈 inviting and 🐎 swift.

  • Live rewrite — comments stay readable
  • Auto-label issues for triage
  • Audit-friendly job summaries
DV @grumpy-dev · 2m
raw

this shit broke prod again — what the hell is going on with this damn CI 🙄

DV @grumpy-dev · 2m · edited by bot
filtered

this 💩 broke prod again — what the 🤬 is going on with this 😡 CI 🙄

profane needs-review
What's inside

Everything you need. Nothing you don't.

One step in your workflow, fourteen strategies, twenty-eight languages, and a clean job summary on every run.

🌍

28 languages, 6,500+ words

Curated word lists across 28 languages — English, Spanish, French, German, Italian, Portuguese, Russian, Dutch, Polish, Turkish, Japanese, Korean, Arabic, Chinese, Hindi, and more — kept up to date in plain text files anyone can audit.

🎨

14 replacement strategies

Pick the vibe — from classic **** asterisks to playful 😡 anger emojis or full ████ redactions.

Native AOT performance

Built with .NET 10 and Native AOT — instant cold starts, tiny binaries, and no .NET runtime to install on the runner.

🧩

Drop-in step

A single GitHub Action step. Add it to a new workflow or paste it into an existing one — no scripts, no infrastructure, no maintenance.

📊

Workflow job summaries

Every run produces a clean, detailed summary table showing exactly what was found and how it was replaced — perfect for audits.

🔧

Bring your own words

Extend the dictionary with a comma-separated list or pull from your own URL. Works alongside the built-in filters automatically.

Replacement strategies

14 ways to say that word.

Pick the strategy that fits your project's tone — from buttoned-up to playful.

asterisk ****

Classic asterisks — the safe default.

emoji 💩

A random expressive emoji per match.

grawlix #%$!

Comic-book style symbol soup.

bold-grawlix #%$!

Grawlix, but louder.

bleep bleep

Replaces with the literal word "bleep".

redacted-rectangle ████

Top-secret redaction blocks.

anger-emoji 😡

A random anger-themed emoji.

middle-asterisk f**k

Keeps first and last letters intact.

middle-swear-emoji f🤬k

A swear emoji in the middle.

random-asterisk * — ****

Random number of asterisks.

first-letter-then-asterisk f***

Keep the first letter only.

vowel-asterisk sh*t

Replaces only the vowels.

strike-through shit

Wraps content in &lt;del&gt; tags.

underscores ____

Replaces with underscores.

Also for Aspire

More than a GitHub Action.

The same engine ships as a containerized Aspire resource. Drop AddProfanityFilter into your AppHost — in C# or TypeScript — and you have a fast, local-first HTTP filter alongside the rest of your services.

// apphost.cs
var builder = DistributedApplication.CreateBuilder(args);

var filter = builder.AddProfanityFilter("profanity-filter")
    .WithCustomDataBindMount("./CustomData");

builder.AddProject<Projects.MyApi>("api")
    .WithReference(filter)
    .WaitFor(filter);

builder.Build().Run();

Ready to clean up your repo?

Two minutes from this page to a working workflow. No registration, no infrastructure, no excuses.