Security by design. Not by bolt-on.

Footfall is built with defense in depth — from bcrypt hashing and tenant isolation to CSP headers and container hardening. Every layer is documented, testable, and turned on by default.

Security stack at a glance

bcrypt Hashing

password storage

Tenant Isolation

business_id scoped

CSRF Tokens

all POST forms

Rate Limiting

per-route rules

SSRF Protection

public IPs only

Container Hardening

pinned images

Secret Validation

required at boot

Vulnerability Reporting

security@ email

01

Authentication & Session Management

5 failed attempts30-min default sessionNo placeholder secrets

The Challenge

Guest WiFi platforms handle PII, RADIUS credentials, and integration secrets. Weak auth or leaked sessions put every tenant at risk.

The Mechanism

Footfall uses bcrypt password hashing, enforces account lockout after 5 failed attempts, and issues HttpOnly / Secure / SameSite=Lax session cookies. The app refuses to start without a strong SECRET_KEY.

What it does

  • bcrypt password hashing
  • Account lockout with 15-minute window
  • HttpOnly / Secure / SameSite=Lax cookies
  • SESSION_LIFETIME_MINUTES based expiry
  • SECRET_KEY required at startup
02

Authorization & Tenant Isolation

100% tenant-scopedRole-based accessNAS secret enforcement

The Challenge

In a multi-tenant SaaS, the worst breach is one tenant seeing another's data — locations, customers, campaigns, or analytics.

The Mechanism

Every dashboard query is scoped to the current user's business_id. Portal success pages verify sessions belong to the requested business and access point. Admin routes require superadmin role.

What it does

  • business_id scoping on all dashboard queries
  • superadmin-only admin routes
  • Portal session verification per AP
  • NAS secret required for AP API endpoints
  • RADIUS auth validates NAS identity
03

Input Validation & Output Encoding

XSS protectedSSTI protectedOpen-redirect protected

The Challenge

Captive portals accept user input. Campaigns render templates. Custom CSS runs on the page. Every one of these is an injection vector if not handled.

The Mechanism

CSRF tokens protect POST forms. Campaign templates run in a sandboxed Jinja2 environment. Custom CSS is parsed and normalized. Redirect URLs are validated, and search terms escape SQL LIKE wildcards.

What it does

  • CSRF tokens on all forms
  • Sandboxed campaign templates
  • cssutils parsing for custom CSS
  • Validated next / redirect URLs
  • SQL LIKE wildcard escaping
04

Rate Limiting & Abuse Prevention

Per-route limitsBrute-force resistantProxy-aware

The Challenge

Login, OTP, voucher, and API endpoints are attractive targets for brute-force and abuse. A platform without rate limits is an easy target.

The Mechanism

Flask-Limiter applies default limits to public routes and stricter limits to auth, registration, OTP, buy/redeem, and API endpoints. The key function respects X-Forwarded-For behind a trusted proxy.

What it does

  • 200/day default public limit
  • 10/min auth limits
  • 5/min OTP request limits
  • 10/min portal buy/redeem
  • X-Forwarded-For aware keying
05

Transport Security & Headers

CSP enforcedClickjacking blockedTLS hardened

The Challenge

Without strict transport headers and CSP, even a well-coded app can be compromised by clickjacking, MIME sniffing, or malicious inline scripts.

The Mechanism

Flask-Talisman sets Content-Security-Policy with nonces, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy, and a restrictive Permissions-Policy. HSTS is added in non-test environments.

What it does

  • CSP with nonces
  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • Strict Referrer-Policy
  • HSTS in production
06

Integration & Outbound Request Safety

Private IPs blocked10s timeoutSSRF protected

The Challenge

Webhook and CRM integrations accept user-supplied URLs. Without validation, they can become SSRF tunnels into internal services.

The Mechanism

Webhook, Zapier, Salesforce, and Zoho integrations validate that URLs are public http(s) endpoints and do not resolve to private or reserved IP ranges. Outbound requests time out after 10 seconds.

What it does

  • Public http(s) URL validation
  • Private/reserved IP rejection
  • 10-second outbound timeout
  • SSRF prevention on webhooks
  • Timeout on all outbound requests
07

Container & Infrastructure Hardening

Pinned imagesSecret enforcementNo weak defaults

The Challenge

Docker images and compose files often ship with weak defaults, outdated base images, or leaked secrets. Production deployments need hardening by default.

The Mechanism

.dockerignore excludes .env, .git, venv, and tests. FreeRADIUS is pinned to a specific version. Redis requires a password. RADIUS refuses to start if RADIUS_DEFAULT_SECRET is missing or still a placeholder.

What it does

  • .dockerignore for secrets and cache
  • Pinned FreeRADIUS 3.2.3
  • Redis requirepass
  • RADIUS secret validation
  • No weak production fallbacks
08

Secrets & Vulnerability Reporting

8 secret categoriesResponsible disclosureChecklist validated

The Challenge

Even the best controls fail if secrets are weak or reused. And when researchers find issues, there needs to be a clear, safe way to report them.

The Mechanism

A production secrets checklist covers SECRET_KEY, REDIS_PASSWORD, DB_PASSWORD, RADIUS_DEFAULT_SECRET, RADIUS_CLIENT_NET, and all integration credentials. Security issues can be reported to security@app.footfall.cloud.

What it does

  • 48+ byte SECRET_KEY required
  • Unique RADIUS_DEFAULT_SECRET
  • Narrow RADIUS_CLIENT_NET CIDR
  • OAuth and mail credential checklist
  • security@app.footfall.co reporting

Need a security questionnaire filled out? We have the answers.