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
4,900+
Curated words
across the dictionary
9
Languages
globally inclusive
14
Replacement strategies
for every taste
Native AOT
.NET 10 powered
instant cold starts
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. 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.
  5. 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.
  6. 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, nine languages, and a clean job summary on every run.

🌍

9 languages, 4,900+ words

Curated word lists across English, Spanish, French, German, Italian, Portuguese, Russian, Arabic, and Chinese — 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.