SlopScore
00 crowd

Phishing-Triage-Assistant

Bilingual (EN/ES) phishing-triage assistant built with Claude Code. Local, rule-based heuristic detection containing SPF/DKIM/DMARC checks, domain spoofing, BEC detection, all explained in plain English, and Spanish. No email content ever leaves your machine.
Open repo on GitHubgithub.com/Rojad09/Phishing-Triage-Assistant
Python · ★ 1 · 0 forks · MIT · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other🤖 claude-code
listed 2 hours ago by Rojad09 · last checked 2 hours ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-09-13: Bilingual (EN/ES) phishing-triage assistant built with Claude Code. Local, rule-based heuristic detection cont; its own README says "Bilingual (EN/ES) phishing-triage assistant built with Claude Code". 1 stars; MIT license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as Rojad09. There's no account to make: SlopScore only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
Bilingual (EN/ES) phishing-triage assistant built with Claude Code. Local, rule-based heuristic detection containing SPF/DKIM/DMARC checks, domain spoofing, BEC detection, all explained in plain English, and Spanish. No email content ever leaves your machine.
topics
claude-codecybersecurityemail-securityphishing-detectionpython
created
2026-09-03 · pushed 1 week ago · 10 commits · 1 contributor
languages
Python 100%
paperwork
licensereadme 42% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 2 hours ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
built_with
claude-code
language (detected)
python
topic (detected)
claude-codecybersecurityemail-securityphishing-detectionpython
license (detected)
mit

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: Bilingual (EN/ES) phishing-triage assistant built with Claude Code. Local, rule-based heuristic detection cont; its own README says "Bilingual (EN/ES) phishing-triage assistant built with Claude Code". It carries the MIT license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

Phishing Triage Assistant

Link to project: https://phishing-triage-assistant-eypuhgx99jea64kirwsrjb.streamlit.app/

A small local tool for triaging suspicious emails. Paste the raw email (headers + body) into the box, click Analyze, and get back:

  • a risk level — Low / Medium / High,
  • a list of specific red flags, each with the exact text that triggered it,
  • a plain-English explanation of the verdict (English or Spanish).

Everything runs on your machine. No email content is sent anywhere.


1. What it does and who it's for

The tool applies a set of rule-based heuristics to a pasted email and produces a triage verdict — the kind of quick "should I be worried about this?" check you'd do before clicking a link or replying. It looks at sender authentication headers (SPF / DKIM / DMARC), From / Reply-To / Return-Path alignment, display-name and look-alike-domain spoofing, urgency and credential-request language, deceptive links, risky attachments, and Business Email Compromise patterns.

It is aimed at:

  • individuals and small teams without a dedicated security team or mail gateway to lean on;
  • anyone who wants a structured second opinion on a suspicious message instead of eyeballing it;
  • bilingual staff (English/Spanish) who may need a structured, plain-language second opinion on a suspicious message.
  • individuals who are not tech-savvy, and would like assistance with deciding what to trust in their inbox, and wanting to know the "why" to do so.

It is not a replacement for enterprise email security, a sandbox, or a malware scanner. It is a triage aid, and the human still makes the call.


2. How it was built

I built this with Claude Code, working in iterative, tightly scoped prompts— one capability or fix per prompt, each followed by tests, rather than one large "build me a phishing detector" request.

Rather than relying on the AI to determine what constitutes a threat, I acted as the security architect and reviewer. I oversaw the development of the rule set, per-rule weights, severity levels, and risk thresholds, strictly verifying the AI's logic against real-world threat intelligence sources and principles from my CySA+ training. Claude Code's role was to scaffold the project structure and implement, refactor, and test the rules under my direct supervision. Every heuristic was sanity-checked against actual cybersecurity standards to ensure the AI did not hallucinate security principles, guaranteeing that the final tool reflects verified, industry-standard detection methods as close as possible.


3. Why local rule-based heuristics instead of an LLM call at runtime

Two reasons, both deliberate:

Privacy. The tool processes potentially sensitive personal and workplace email. With local heuristics, no email content ever leaves the machine or reaches a third-party API — not the headers, not the body, not the links. There is nothing to log, retain, or leak on someone else's server.

Determinism and auditability. Every score can be traced to the exact rules that fired and the exact substring of the email that triggered each one. Given the same input, the output is always identical. An LLM call would give neither guarantee: its reasoning isn't reproducible, isn't fully inspectable, and can't be pointed at as "this rule, this evidence, this weight." For a security triage tool, being able to explain why a message scored the way it did matters as much as the score.

The rules and scoring live in triage/rules.py and triage/scorer.py; those modules do no I/O and make no network calls.


4. How it was verified

  • Per-rule evidence checks. For each rule I built an isolated synthetic email that triggers only that rule, then asserted three things: the right rule fired, its severity matched what the rule documents, and the evidence field contained a verbatim slice of my input — proving evidence is pulled from the actual matched text, not a hardcoded placeholder. This covers every branch of the multi-variant rules (look-alike domain, display-name spoof, deceptive link host, suspicious attachment). One test deliberately breaks a single rule and confirms the rest of the analysis still completes with a "Rule error (ignored)" flag for just that rule.

  • Mixed-severity emails. I tested emails that trip several rules at once to confirm the "top flags" selection (which findings surface first in the explanation) ranks by severity then weight correctly.

  • iCloud Phishing Email — false Low. A real, iCloud phishing email that I utilized came back as low, which means that it was not seen as a scam. after doing more research, I figured out that the source message was encrypted with base64, which is done to bypass email phishing detectors, so it can go straight to one's inbox. I made Claude Code build a Base64 decoder, straight into the assistant, as a way to still read the red flags, and judge the email properly.

  • Steam gift email — false High. A real, fully-authenticated Steam gift email scored High because the lexical "brand name inside the sending domain" rules (steam inside steampowered.com) fired without checking authentication. Fixed by adding a check: when SPF, DKIM, and DMARC all pass and align to the sending domain, those lexical-only rules drop to low severity with an explanation noting the domain is authenticated. steampowered.com now scores Low.

  • LinkedIn notification email — false Medium. A real LinkedIn digest scored Medium because the credential-request rule matched the substring otp inside an otpToken= URL tracking parameter — a URL artifact, not a request to the reader. Fixed in the parsing step: URLs are stripped from the body text (each replaced with [link]) before any keyword rule runs. The link-based rules still work from the parsed link objects, which keep the real URLs.

  • Dedicated BEC rule. Business Email Compromise often has no spoofed domain, no bad link, and no attachment — just words. I added a rule that fires only when urgency/secrecy language and financial language both appear, and capped it at Medium on purpose, with explanation text that tells the reader to verify the request through a separate known channel (call the person back on a number you already have) before acting. It's a prompt for human judgment, not an automated verdict.

  • Fail-closed input handling. The tool distinguishes genuinely unparseable input — a wall of text with no header-like lines and no blank-line body separator — which blocks analysis and returns an error, from a valid headerless body someone pasted without headers, which is analyzed but marked "limited" (sender-authentication and domain-spoofing checks are skipped and the result says so). The failure mode is "refuse or caveat," never "silently score Low."


5. Known limitations

Stated plainly:

  • No live reputation data. No domain-reputation, WHOIS, blocklist, or DNS lookups. A brand-new malicious domain with clean-looking headers can pass.
  • No attachment content scanning. It flags risky attachment types and names (executables, double extensions, macro-enabled Office docs, archives), but never opens or inspects attachment contents.
  • False positives on legitimate senders. Real small businesses, nonprofits, and solo operators sometimes send from free webmail; legitimate marketing email routinely uses link shorteners. Those rules are intentionally weighted as weak signals, but they can still contribute to a Medium on an otherwise benign message.
  • Static heuristics only. If an attack doesn't match an existing rule, the tool won't catch it. It has no ability to generalize to novel patterns.
  • A pure database Although I fixed many, many bugs, there are still bound to be more, as it is a pure database scanner that has to be checked, patched, and fixed, each time a new problem arises.

Treat a Low result as "no known patterns matched," not "safe."


6. Running it locally

Requires Python 3.10+.

pip install -r requirements.txt
streamlit run app.py

Then open the URL Streamlit prints (usually http://localhost:8501). Paste an email — or use the Load buttons to try the examples in sample_emails/ — and click Analyze. A language toggle (English / Español) switches the displayed text without re-running the analysis.

You can also call the scorer directly:

from triage.scorer import analyze_email

result = analyze_email(raw_email_text)
print(result.risk_level, result.score)
for flag in result.red_flags:
    print(flag.severity, flag.rule_id, "-", flag.evidence)

7. Running the tests

python -m pytest

The suite is split across:

  • tests/test_scorer.py — end-to-end scoring, sample emails, the Steam and LinkedIn regression fixtures, fail-closed behavior.
  • tests/test_rule_explanations.py — one isolated email per rule/variant, asserting rule id, severity, and verbatim evidence.
  • tests/test_localization.py — the English/Spanish output layer never changes the score, severity, or evidence, only the displayed text.

Real emails used as test fixtures have had all personal and recipient-identifying data replaced with synthetic values.


Project layout

phishing-triage-assistant/
├── app.py                       # Streamlit UI + language toggle
├── triage/
│   ├── parsing.py               # raw text -> structured email; URL stripping for keyword rules
│   ├── rules.py                 # the heuristic rules -> RedFlag list  (security logic lives here)
│   ├── scorer.py                # analyze_email(), weights -> score -> risk level, fail-closed logic
│   ├── messages.py              # EN/ES presentation layer (titles, explanations, UI strings)
│   └── __init__.py
├── sample_emails/               # paste-ready examples (benign + malicious)
├── tests/
│   ├── test_scorer.py
│   ├── test_rule_explanations.py
│   ├── test_localization.py
│   └── fixtures/                # scrubbed real emails used as regression fixtures
├── requirements.txt
└── README.md

Built by a trilingual cybersecurity graduate, and student, (EN / ES / 日本語) as part of a Forward Deployed Engineer portfolio.

Read the rest on GitHub

Scan report · 2026-09-13
  • Prohibited terms or links
  • Repository eligibility
  • slopscore.md paperwork
  • Content policy
  • Risk review

0 comments

log in to comment.

report this listinglog in to report