Skip to content

Nabil201-ctrl/phish-snare

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

phish-snare

URL risk scorer for phishing-style links.

I wanted something I could run offline, tweak the weights on, and still explain every point on the score. Python does the feature extraction and scoring. TypeScript is just a thin API/CLI that calls into that engine — I already use JS for small services, so this split felt natural.


Background

Most “is this link bad?” tools either:

  • call a third-party reputation API, or
  • dump you into a black box classifier

I went the other way: pull cheap signals out of the URL string itself (IP hosts, brand words in the path, shady TLDs, missing HTTPS, punycode, etc.), weight them, and return a label plus a short reason list.

Not perfect. Intentionally readable.


Scoring logic

Pipeline for one URL:

  1. Normalize (add http:// if someone pasted bare host).
  2. Parse host / path / query.
  3. Flag features.
  4. Add weighted points (cap at 100).
  5. Map to: benign · low_risk · suspicious · likely_phish.

Weights live in engine/scorer.py as a plain dict. If you disagree with “IP host = 25”, change it. That was the whole point.

Example of a brand trick I care about: path says paypal but the host is a random IP or junk domain.


Architecture

flowchart LR
    subgraph edge [TypeScript]
        A[POST /score or CLI]
        B[scorer_bridge.ts]
        A --> B
    end

    subgraph core [Python]
        C[engine/cli.py]
        D[features.py]
        E[scorer.py]
        C --> D --> E
    end

    B -->|spawn + stdin URLs| C
    E -->|JSON score + reasons| B
    B --> F[HTTP response / terminal]
Loading

Contract between the two sides is boring JSON over stdin/stdout. No shared runtime, no gRPC.


Layout

phish-snare/
  engine/          # scoring
    features.py
    scorer.py
    cli.py
  api/             # HTTP + TS CLI
    server.ts
    cli.ts
    scorer_bridge.ts
  sample_data/urls.txt
  tests/

Setup & run

Engine only

git clone https://github.com/Nabil201-ctrl/phish-snare.git
cd phish-snare

python3 engine/cli.py "http://203.0.113.50/paypal/login/verify"
python3 engine/cli.py -f sample_data/urls.txt --json

TypeScript side

cd api
npm install

npx ts-node cli.ts "https://github.com" "http://secure-paypal-update.tk/login"

# API on :3847
npx ts-node server.ts
curl -s http://127.0.0.1:3847/health
curl -s -X POST http://127.0.0.1:3847/score \
  -H 'content-type: application/json' \
  -d '{"url":"http://203.0.113.50/paypal/login"}'

Tests

python3 -c "
import sys
from pathlib import Path
sys.path.insert(0, str(Path('engine').resolve()))
sys.path.insert(0, str(Path('tests').resolve()))
from test_scorer import test_clean_site_low, test_ip_paypal_path_high
test_clean_site_low(); test_ip_paypal_path_high()
print('ok')
"

Notes from building this

  • First version treated words like login as brand tokens. That flagged github.com/login. Fixed by keeping brand list to real brands only.
  • I almost put Express in. Didn't need it. Node http is enough for a demo API.
  • Keeping Python pure (no Flask) made unit tests stupidly easy.

Possible next steps

  • Parse full email HTML and extract URLs first
  • Cache results
  • Optional local model later as one more feature, not a replacement for the rules

About

Explainable phishing URL risk scorer with a TypeScript API over a Python engine

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors