Intellidwell Logo Docs
IntelliSignup App ↗

🛡️ Security & Anti-Spam Hardening

Because public signup forms and open user registration portals are primary targets for automated bots, scrapers, and credential-stuffing attacks, IntelliSignup implements an aggressive multi-layered cyber security architecture designed to prevent abuse while ensuring zero friction for human users.

💡 Defensive Philosophy

IntelliSignup pairs silent deception (honeypots that waste bot computational resources) with deterministic defenses (curated disposable email blocklists, IP rate-limiting, and constant-time cryptographic checks) to keep server databases clean and deliverability reputations high.

1. Invisible Registration Honeypot Trap

Automated registration bots parse DOM structures to fill in all discovered input tags. IntelliSignup deploys a deceptive trap field named phone_confirm inside app/templates/register.html:

HTML (Honeypot Client Trap)
<!-- Honeypot anti-spam trap: Hidden from legitimate humans, populated by automated bots -->
<div style="position: absolute; left: -9999px; top: -9999px; opacity: 0; pointer-events: none;" aria-hidden="true">
    <label for="phone_confirm">Do not fill this field</label>
    <input type="text" name="phone_confirm" id="phone_confirm" tabindex="-1" autocomplete="off">
</div>

Deception Defense Mechanism

When an automated bot fills this invisible field, the server intercepts the request inside app/routes.py:

  • Logs a high-priority security warning containing the attacker's IP and submitted email.
  • Zero Database Writes: No user record is inserted.
  • Zero Outbound Emails: No verification emails are dispatched, preserving SMTP quotas and reputation.
  • Deceptive Success Flash: Redirects the bot to /login with the message: "Account created. Check your email to verify your address...". The bot assumes its automated task succeeded and stops attempting form bypasses.

2. Disposable Email & Tag Filtering

Implemented inside app/security.py, registration validation enforces two strict email integrity checks:

A. Curated Disposable Email Blocklist

IntelliSignup maintains an in-memory set of over 50 temporary and disposable email providers (including mailinator.com, tempmail.com, guerrillamail.com, yopmail.com, 10minutemail.com, and sharklasers.com). Attempts to register with these domains are instantly blocked with an explanatory error:

Python (Disposable Filter Excerpt)
def is_disposable_email(email):
    if not email:
        return False
    parts = email.strip().lower().split('@')
    if len(parts) != 2:
        return False
    return parts[1] in DISPOSABLE_DOMAINS

B. Email Sub-Addressing Block (+)

Spammers frequently bypass single-email limits using "plus-aliasing" (e.g. user+bot1@gmail.com). IntelliSignup rejects registration emails containing the + symbol, preventing attackers from multiplying accounts through a single primary mailbox.

3. Sliding-Window Rate Limiting

To defend against brute-force attacks and volumetric request flooding, IntelliSignup tracks events dynamically in the RateLimitEvent database table. The system automatically trims audit rows older than 48 hours to conserve disk space.

Rate Limit Scope Key Format Threshold Window Security Objective
register_ip Client IP 5 attempts 3,600s (1 hour) Prevents single-IP botnets from mass-registering different accounts.
register Email Address 5 attempts 3,600s (1 hour) Blocks spam flooding targeting a specific inbox.
login Client IP + Email 8 attempts 900s (15 min) Thwarts brute-force password guessing and credential stuffing.
verification_resend Client IP + Email 5 attempts 3,600s (1 hour) Prevents abuse of verification email dispatch mechanisms.
password_reset_request Client IP + Email 5 attempts 3,600s (1 hour) Shields SMTP relays against password reset harassment attacks.
public_claim Client IP 20 claims 900s (15 min) Prevents malicious script claim hoarding on public event pages.
Python (Sliding-Window Calculation Excerpt)
def rate_limit_hit(scope, key, limit, window_seconds):
    now = datetime.utcnow()
    window_start = now - timedelta(seconds=window_seconds)

    count = RateLimitEvent.query.filter_by(scope=scope, key=key)\
        .filter(RateLimitEvent.created_at >= window_start).count()
        
    if count >= limit:
        latest = RateLimitEvent.query.filter_by(scope=scope, key=key)\
            .filter(RateLimitEvent.created_at >= window_start)\
            .order_by(RateLimitEvent.created_at.asc()).first()
        retry_after = max(int((latest.created_at + timedelta(seconds=window_seconds) - now).total_seconds()), 1)
        return True, retry_after

    db.session.add(RateLimitEvent(scope=scope, key=key))
    db.session.commit()
    return False, None

4. Cloudflare Turnstile CAPTCHA

IntelliSignup integrates Cloudflare's privacy-focused Turnstile service to detect non-human traffic passively without irritating users with image puzzles or distorted text challenges.

  • Graceful Degradation: If TURNSTILE_SITE_KEY or TURNSTILE_SECRET_KEY are not defined in .env (such as in local development), the verification step automatically returns True without failing requests.
  • Managed Production Mode: When active, the client widget generates a cryptographic response token submitted with the registration payload.
  • Server-Side Verification: The Flask backend validates the token directly against https://challenges.cloudflare.com/turnstile/v0/siteverify via POST request with a 5-second socket timeout.

5. Passwords & Cryptographic Verification

User accounts are secured with industrial-grade cryptographic implementations:

  • Password Hashing: Passwords are hashed using Werkzeug's secure hashing suite (scrypt/pbkdf2:sha256) with salted iterations. Passwords are never stored in plaintext.
  • Cryptographic Email Verification: Uses itsdangerous.URLSafeTimedSerializer with a dedicated email-verify salt. Verification links expire automatically after 24 hours (configurable via EMAIL_VERIFICATION_MAX_AGE).
  • Password Reset Workflows: Time-sensitive reset tokens carry an embedded purpose: password-reset payload that self-invalidates after 1 hour (PASSWORD_RESET_MAX_AGE = 3600).
  • Complete Account Deletion: Users can trigger /account/delete from their settings, executing a cascading purge that deletes all owned signups, items, claims, custom forms, and encrypted OAuth tokens.

6. AES-256 Fernet Encryption at Rest

Third-party integration credentials (such as Google OAuth refresh tokens and access tokens stored in GoogleCalendarConnection) must be safeguarded against database dumps or snapshot compromises.

Python (Fernet Token Encryption)
# Encrypted fields in the database carry an explicit prefix
ENCRYPTED_PREFIX = 'enc::'

def encrypt_value(value):
    if not value or value.startswith(ENCRYPTED_PREFIX):
        return value
    fernet = _fernet() # Initialized with APP_ENCRYPTION_KEY
    if not fernet:
        return value
    encrypted = fernet.encrypt(value.encode('utf-8')).decode('utf-8')
    return f'{ENCRYPTED_PREFIX}{encrypted}'

def decrypt_value(value):
    if not value or not value.startswith(ENCRYPTED_PREFIX):
        return value
    fernet = _fernet()
    return fernet.decrypt(value[len(ENCRYPTED_PREFIX):].encode('utf-8')).decode('utf-8')

7. CSRF & Open-Redirect Protections

Every mutating HTTP POST request (claim creation, event updates, form modifications, account actions) is validated against a session-stored CSRF token:

  • Constant-Time Verification: Evaluated using hmac.compare_digest(expected, provided) to prevent timing attacks.
  • Open-Redirect Mitigation: All post-login or post-action redirects pass through is_safe_redirect(target), ensuring target URLs match the exact hostname and scheme of the host server and blocking external phishing redirections.