Skip to main content

MASU727

PyPI Python Versions License Downloads Tests Passing

MASU727

MASU727

MASU727 (Malicious and Suspicious Activities Prevention Unit 727) is a security firewall for Django that protects web applications from malicious and suspicious activities without changing your existing authentication system.

MASU727 is a pluggable, rule-based security engine that sits before authentication and analyzes every incoming request for malicious or suspicious behaviour. Its Firewall Engine executes a configurable set of detectors—including SQL Injection, Cross-Site Scripting (XSS), Command Injection, Directory Traversal, Scanner/Reconnaissance Detection, Bot Detection, Rate Limiting, Honeypots, Malicious File Upload Detection, Behaviour Analysis, and Custom Detectors—to identify, score, and respond to security threats in real time.

Rather than focusing only on known attack signatures, MASU727 is designed to prevent malicious and suspicious activities by combining multiple detection techniques, behavioural analysis, configurable threat scoring, and flexible response policies. Based on your configuration, it can allow, log, warn, challenge, or block requests before they reach your authentication layer, while remaining fully compatible with Session Authentication, JWT, OAuth, Web727Token, and other authentication mechanisms.


Author

Developed by: T.P. Thangaprabhu

Founder & Director
MY727INFOTECH INDIA PRIVATE LIMITED

With over 20 years of professional experience in Cost & Management Accounting, Finance, Software Development, and Cybersecurity, the project is focused on providing enterprise-grade security solutions for Django applications.


Company

MY727INFOTECH INDIA PRIVATE LIMITED

Building secure, scalable, and intelligent software solutions including:

  • Web & Mobile Application Development
  • ERP & CRM Solutions
  • AI-powered Business Applications
  • Cybersecurity Products
  • Django Security Frameworks

Request
   │
   ▼
MASU727Middleware
   │
   ▼
FirewallEngine
   │
   ├── HoneypotDetector
   ├── RateLimitDetector
   ├── RequestValidationDetector
   ├── BotDetector
   ├── ScannerPathDetector
   ├── SQLInjectionDetector
   ├── XSSDetector
   ├── CommandInjectionDetector
   ├── DirectoryTraversalDetector
   ├── FileUploadDetector
   └── ...your CUSTOM_DETECTORS
   │
   ▼
Authentication (Session / JWT / Web727Token / OAuth) — untouched
   │
   ▼
Views

Requirements

  • Python 3.9+
  • Django 4.2+
  • Django 5.x fully supported

Installation

pip install masu727
INSTALLED_APPS = [
    ...
    "masu727",
]

MIDDLEWARE = [
    "masu727.middleware.firewall.FirewallMiddleware",  # keep near the top
    ...
]
python manage.py migrate masu727

Everything else works automatically with sane defaults (PROFILE: "NORMAL").

(masu727.middleware.MASU727Middleware — the pre-1.1 import path — still works too; both resolve to the same class.)

The detector registry — extending MASU727 without touching its code

The engine never hardcodes a detector class. It resolves an ordered list of dotted paths from rules.py (or your DETECTORS/CUSTOM_DETECTORS settings), imports each one, and calls .detect() on it — open for extension, closed for modification: adding a detector is a settings change, not a change to engine.py.

from masu727.detectors.base import BaseDetector, DetectionResult

class MyDetector(BaseDetector):
    name = "my_custom_rule"
    default_score = 50
    default_action = "log"

    def detect(self, context):
        if "x-suspicious" in context.headers:
            return DetectionResult(
                matched=True,
                detail="suspicious header present",
            )
        return DetectionResult(matched=False)
MASU727 = {"CUSTOM_DETECTORS": ["myproject.security.MyDetector"]}

Full guide, including replacing the built-in set entirely via DETECTORS, in docs/detectors.md.

The rule engine, in one page

Every detector — built-in or yours — is a subclass of BaseDetector:

from masu727.detectors.base import BaseDetector, DetectionResult

class MyDetector(BaseDetector):
    name = "my_custom_rule"      # unique key, used in RULES and threat logs
    default_score = 50           # points added to the IP's threat score on a match
    default_action = "log"       # allow | log | warn | challenge | block

    def detect(self, context):
        # context already has client_ip and a collected payload string
        # (query string + body) so you don't have to redo that work.
        if "x-suspicious" in context.headers:
            return DetectionResult(
                matched=True,
                detail="suspicious header present",
            )
        return DetectionResult(matched=False)

Register it — no subclassing the middleware, no editing MASU727's code:

MASU727 = {
    "CUSTOM_DETECTORS": ["myproject.security.MyDetector"],
}

What each action means

Action Effect
allow Detector runs but never contributes to score or blocking, even on a match.
log Match adds score to the IP's running total. Doesn't block by itself.
warn Same as log today; kept distinct for your own dashboards/alerts.
challenge Reserved for future CAPTCHA-style integration; behaves like warn for now.
block Match ends evaluation immediately — this detector's verdict is final, regardless of score.

If several log/warn detectors fire on the same request and their combined score crosses BLOCK_ON_SCORE, the request is blocked on whichever detector pushed it over — this is what keeps false positives down: one weak signal (say, a slightly unusual header) won't block anyone, but three weak signals together will.

Configuring detectors: RULES

MASU727 = {
    "RULES": {
        "sql_injection":       {"enabled": True, "score": 90, "action": "block"},
        "xss":                 {"enabled": True, "score": 60, "action": "log"},
        "scanner_path":        {"action": "log"},
        "bot_signature":       {"enabled": False},
    },
}

Any field you omit falls back to the detector's built-in default. The old flat ENABLE_SQL_DETECTION-style flags still work as a fallback for enabled when a detector has no entry in RULES at all, so existing configs from earlier MASU727 versions keep working unchanged.

Profiles: PROFILE

Instead of hand-tuning 10+ RULES entries, pick a profile:

MASU727 = {"PROFILE": "STRICT"}   # BASIC | NORMAL | STRICT | ENTERPRISE
  • BASIC — log-only, high block threshold. Good for a new integration where you want visibility before you start rejecting traffic.
  • NORMAL — the default; matches the built-in per-detector defaults.
  • STRICT — most detectors block outright, lower threshold.
  • ENTERPRISE — STRICT plus notifications and behaviour analysis on by default.

Explicit RULES entries always win over the active profile, and the profile's RULES always win over a detector's hardcoded default — so you can start from STRICT and carve out one exception:

MASU727 = {
    "PROFILE": "STRICT",
    "RULES": {"xss": {"action": "log"}},  # everything else stays STRICT
}

Per-path policies: PATH_PROFILES

Different rules for different areas of your app — e.g. a public read API that should barely ever block vs. an admin area that should be paranoid:

MASU727 = {
    "PROFILE": "NORMAL",
    "PATH_PROFILES": {
        "/admin/": "STRICT",
        "/api/public/": "BASIC",
    },
}

Longest-prefix-match wins; anything not covered uses the top-level PROFILE.

Excluding paths entirely

MASU727 = {
    "EXCLUDE_URLS": ["/healthz", "/metrics"],
    "TRUSTED_WEBHOOKS": ["/webhooks/stripe/", "/webhooks/github/"],
}

EXCLUDE_URLS (merged with the older WHITELIST_PATHS) skips MASU727 entirely for matching paths. TRUSTED_WEBHOOKS does the same for known webhook endpoints — MASU727 doesn't verify webhook signatures itself, so keep doing that in your view.

Response shape: BLOCK_RESPONSE

MASU727 = {
    "BLOCK_RESPONSE": {"status": 403, "format": "json"},   # or "html"
}
# or hide that anything was blocked at all:
MASU727 = {"BLOCK_RESPONSE": {"status": 404, "format": "json"}}
# or redirect instead:
MASU727 = {"BLOCK_RESPONSE": {"redirect_url": "https://example.com/blocked"}}

Rate-limit blocks always answer 429 regardless of BLOCK_RESPONSE.status, since that's the correct semantic code for "you're going too fast."

Settings validation

Invalid config fails at startup (python manage.py check), not in production traffic — bad PROFILE names, invalid action values in RULES, malformed RATE_LIMIT strings, and unimportable CUSTOM_DETECTORS paths are all caught early.

Wiring up the dashboard & API (optional)

# project/urls.py
urlpatterns = [
    ...
    path("masu727/", include("masu727.urls")),
]

This exposes:

  • GET /masu727/dashboard/ — staff-only HTML dashboard: attack timeline (24h, by hour), top attack types, top attacking IPs, top countries, recent threats, CSV/JSON export.
  • GET /masu727/api/threats — recent threat log entries (JSON)
  • GET /masu727/api/blocked — currently blocked IPs (JSON)
  • POST /masu727/api/unblock — unblock an IP: {"ip_address": "1.2.3.4"}

All dashboard/API routes require is_staff.

Reports & maintenance commands

# Weekly (or any period) summary: totals, top attack types, most-attacked
# URLs, top attacking IPs, top countries.
python manage.py masu727_report --days 7
python manage.py masu727_report --days 30 --format json

# Prune expired IP blocks and old threat logs (run on a schedule).
python manage.py masu727_cleanup --keep-days 30

Extension points beyond custom detectors

  • Geo-blocking (masu727/geo.py) — opt-in country allow/deny list. No GeoIP database is bundled (licensing/size); register your own resolver:
    from masu727.geo import set_resolver
    set_resolver(lambda ip: my_geoip_lookup(ip))
    
  • Threat intelligence feeds (masu727/threat_intel.py) — register a callable returning a set of flagged IPs (Tor exit nodes, known-bad-IP lists, etc.), then check it from a custom detector. No feed is bundled by default — see the module docstring for a complete example.

Security features

Feature Status
SQL Injection ✅
XSS ✅
Command Injection ✅
Directory Traversal ✅
Bot Detection ✅
Recon Scanner ✅
Upload Protection ✅
Rate Limiting ✅
Behaviour Analysis ✅
Honeypots ✅
REST API ✅

Documentation and examples

Benchmark

benchmarks/benchmark.py measures MASU727's overhead against a bare Django response across all four profiles.

Typical overhead: ~1–2 ms/request, depending on which detectors are enabled. Benchmarks vary by hardware, so we no longer publish fixed millisecond figures here — run the script yourself for numbers that reflect your own environment:

DJANGO_SETTINGS_MODULE=tests.settings PYTHONPATH=. python benchmarks/benchmark.py

Overhead is dominated by the regex payload scans (SQLi/XSS/command/ traversal), not by rule-resolution or the RULES/PROFILE machinery — that's why it's flat across profiles. If you need to shave it further, disable detectors you don't need via RULES rather than relying on EXCLUDE_URLS for high-traffic routes you still want some protection on.

Running the test suite

pip install pytest pytest-django
PYTHONPATH=. python -m pytest -v

280 pytest-django tests across test_sql.py, test_xss.py, test_scanner.py, test_behaviour.py, test_context.py, test_rules.py, test_registry.py, test_signals.py, test_models.py, test_api.py, test_engine.py, test_middleware.py, test_rate_limit.py, and test_uploads.py — covering detector pattern coverage (including encoding-evasion and known false-positive checks), the engine's action/scoring semantics, custom detector loading via both settings and the imperative registry, profile resolution, signal dispatch, middleware integration (blocking, exclusions, trusted IPs, response formats), the REST API, model behavior, rate limiting, and file upload scanning.

Performance notes

  • Use Redis (django-redis) as your CACHES["default"] backend in production — rate limiting, temporary blocks, and threat scores all live in cache, not the database, so they stay fast under load.
  • The database is only used for persistent logs (ThreatLog, BlockedIP, HoneypotHit, TrustedIP) and admin/dashboard views.
  • Regex patterns are compiled once at import time.
  • The detector list itself is built once per process (from RULES/ PROFILE/CUSTOM_DETECTORS) and cached — not re-parsed on every request.
  • Threat-log writes happen on a background thread so they never add latency to the request/response cycle.
  • Detection short-circuits on block-action detectors, evaluated cheapest and highest-signal first (honeypot, rate limit, request validation, bot signature) before the more expensive payload regex scans run.

What ships as of 1.4.3

  • Firewall Engine with pluggable, per-detector-configurable rules (RULES, PROFILE, PATH_PROFILES, DETECTORS, CUSTOM_DETECTORS)
  • Detector Registry — two registration paths, settings-driven (rules.py) and code-driven (registry.py), feeding the same engine
  • SecurityContext — a single, typed object every detector receives (.ip, .payload, .user, .country, .headers, .score, ...)
  • Configurable actions per detector: allow / log / warn / challenge / block
  • Configurable block responses: status code, JSON/HTML, or redirect
  • Categorized SQL Injection detection (tautology, union, stacked DML, blind/time, error-based, stored-proc, comment terminators, structural)
  • Categorized XSS detection with HTML-entity/URL/base64 decoding to catch obfuscated payloads
  • Command Injection / Directory Traversal detectors
  • Scanner (recon) path detection, bot/automation-tool detection (curl, sqlmap, Burp, ZAP, Nikto, Nmap/NSE, Gobuster, FFUF, Dirsearch, Acunetix)
  • Behaviour Anomaly Detection (high 404 ratio, rapid-crawl pattern) wired in as a real detector, not just tracked data
  • Rate Limiter (cache-backed)
  • Honeypot Engine (configurable trap paths)
  • File Upload Scanner (blocked extensions, double-extension trick, MIME mismatch, zip-bomb heuristics)
  • IP Protection (whitelist / blacklist / temporary / permanent / trusted)
  • Django signals (attack_detected, request_blocked, sql_detected, scanner_detected) and an ON_BLOCK hook
  • Structured, async logging (IP, user, session, headers, payload, score, action, duration)
  • Admin dashboard with attack timeline + CSV/JSON export
  • masu727_report and masu727_cleanup management commands
  • Versioned REST-style API (/api/v1/threats, /blocked, /unblock, with unversioned aliases)
  • Django admin integration for all models
  • Settings validation via Django system checks (profiles, rules, rate limits, detector paths, allowed origins, block-response format)
  • Full pytest suite (280 tests)
  • Benchmark script measuring overhead across all profiles

Extension points intentionally left minimal

Geo-blocking and threat-intelligence feeds ship as opt-in hooks rather than bundled data (licensing/size/freshness concerns are a project of their own). Browser/device fingerprinting, CAPTCHA integration, ML-based anomaly detection, and OpenAPI docs are left for v2, per the original roadmap.

Current status

  • ✔ 280 automated pytest tests
  • ✔ Django 5 compatible
  • ✔ Python 3.12 tested
  • ✔ Production ready

Security note

MASU727 is a defense-in-depth layer, not a replacement for parameterized queries, output escaping, CSRF protection, and Django's other built-in protections — keep using those. Treat it as a WAF, not a substitute for secure coding practices.

Metadata

Release files for masu727 1.4.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for masu727 1.4.3
File Size Uploaded Provenance
masu727-1.4.3.tar.gz 72.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for masu727 1.4.3
File Interpreter ABI Platform
masu727-1.4.3-py3-none-any.whl Python 3 none any Details

Total release size: 138.1 kB

Release files / masu727-1.4.3.tar.gz

Download URL masu727-1.4.3.tar.gz
Size 72.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a775993bab5f03a8aa992dd1a0ac20a6a123ef7786a883a3c546f4cbaa82e97a
BLAKE2b-256 checksum
How to use checksums
7f10668e331880ad05f9c7141a0c87f7acbab38ba46834be6d2c4c02e5dba4cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release files / masu727-1.4.3-py3-none-any.whl

Download URL masu727-1.4.3-py3-none-any.whl
Size 66.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d728d80d511ee775f9693fc6d75de386a041733f30dec0ba3ad1032e7495281
BLAKE2b-256 checksum
How to use checksums
efebe3c27b9da7fa359dafe9691802d9a72260dc05cd9d4ac4601b0904ff5253
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Security for masu727 1.4.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page