Attack Mode

Attack Mode is Temps's built-in proof-of-work challenge for bot traffic and application-layer (L7) request floods. When enabled, every visitor completes a browser-solved challenge before reaching your app — no third-party CAPTCHA services, no external dependencies, everything runs on your infrastructure. It does not absorb volumetric network DDoS — put a CDN or your provider's DDoS protection in front for that.

The other protections the Temps proxy applies, security headers, the IP access list and vulnerability scanning, are on Security Settings. For the full security overview, see Security. Guide: Replace reCAPTCHA with a proof-of-work CAPTCHA explains the technique behind the challenge.


Overview

Attack Mode is Temps's self-hosted alternative to Cloudflare's "Under Attack Mode." When enabled, every visitor must complete a proof-of-work (PoW) challenge before accessing your application. The challenge is solved automatically in the visitor's browser using a WebAssembly solver -- no user interaction required.

Key Features:

  • Zero dependencies -- no third-party CAPTCHA services or API keys
  • Automatic solving -- visitors see a brief checkpoint page while their browser solves the challenge (2-5 seconds)
  • 24-hour sessions -- once verified, visitors can browse freely for 24 hours
  • TLS fingerprinting -- sessions are tied to JA4 TLS fingerprints for stronger identity binding
  • WASM-powered -- Rust compiled to WebAssembly for 30-50x faster solving than JavaScript
  • Per-project and per-environment control -- enable or disable per project or per environment from the dashboard, CLI, or API

When to use Attack Mode:

  • Your application is getting an application-layer request flood
  • You're seeing suspicious bot traffic patterns
  • You want to protect a public-facing app during a critical event
  • You need immediate protection without external service setup

When not to use it:

  • For API endpoints consumed by other services (they can't solve PoW challenges)
  • Permanently on production -- it adds latency for first-time visitors
  • For applications that need to be crawled by search engines

How it works

When a visitor requests a page on a project with Attack Mode enabled, the Temps proxy intercepts the request (see Request flow for where this check sits) and runs through the following flow:

Challenge Flow

  1. Request arrives at the Pingora-based reverse proxy
  2. Session check -- the proxy looks up the visitor's JA4 TLS fingerprint (or IP address as fallback) in the challenge_sessions table
  3. If valid session exists -- the request passes through to your application normally
  4. If no valid session -- the proxy returns a 403 response with an HTML challenge page
  5. Browser solves challenge -- the embedded WASM solver finds a nonce such that SHA-256(challenge + nonce) has at least 20 leading zero bits (~1 million hash attempts, takes 2-5 seconds)
  6. Solution submitted -- the browser POSTs the solution to /api/_temps/captcha/verify
  7. Server verifies -- the proxy recomputes the hash and checks the leading zero bits
  8. Session created -- a 24-hour session is stored in the database, keyed to the visitor's TLS fingerprint
  9. Page loads -- the browser redirects to the original URL

Attack Mode requires HTTPS. HTTP requests return a 426 Upgrade Required response because JA4 TLS fingerprinting -- used to identify visitors across requests -- is only available on TLS connections.

Proof-of-Work Details

The challenge uses SHA-256 hashing with a difficulty of 20 leading zero bits, which requires approximately 1 million hash attempts on average. The WASM solver processes this in 2-5 seconds on modern hardware.

  • Name
    Algorithm
    Type
    SHA-256
    Description

    The solver concatenates the challenge string with a nonce and computes SHA-256(challenge + nonce). It increments the nonce until the hash has the required number of leading zero bits.

  • Name
    Difficulty
    Type
    20 bits
    Description

    20 leading zero bits means the hash must start with at least 5 hex zeros (e.g., 00000a3f...). This takes ~1M attempts on average -- enough to deter bots while remaining fast for browsers.

  • Name
    WASM Solver
    Type
    Rust → WebAssembly
    Description

    The solver is written in Rust and compiled to WebAssembly via wasm-bindgen. It uses the optimized sha2 crate and is 30-50x faster than the JavaScript fallback. Progress callbacks update the UI every 10,000 iterations.

  • Name
    Session Duration
    Type
    24 hours
    Description

    Once a challenge is solved, the session is valid for 24 hours. Sessions are keyed to the visitor's JA4 TLS fingerprint (or IP address if fingerprinting is unavailable). Disabling attack mode does not delete existing sessions: they stay valid until their 24 hours run out, so a visitor who already passed is not challenged again if you re-enable it within that window.

  • Name
    JavaScript Fallback
    Description

    If the WASM module fails to load (older browsers, disabled WebAssembly), the challenge page falls back to a pure JavaScript solver. It's slower but functional.


Enabling attack mode

Enable Attack Mode (project level)

  1. 1

    Go to Projects and select your project.

  2. 2

    Open Settings then Security.

  3. 3

    Toggle Enable Attack Mode in the Attack Mode card.

  4. 4

    Click Save Attack Mode Settings.

    Checkpoint: Confirm the orange "Attack Mode is enabled for this project" banner appears on the project detail page.

Enable Attack Mode (environment level)

  1. 1

    Go to Projects and select your project.

  2. 2

    Open Settings then Environments.

  3. 3

    Select the environment (for example production).

  4. 4

    Open the Security card.

  5. 5

    Toggle Attack Mode and click Save.

    Checkpoint: Confirm the environment detail page shows Attack Mode as enabled for that environment only.

Attack Mode can be enabled from the dashboard or API at both the project and environment level. Via CLI, only project-wide Attack Mode is available today (projects settings -p my-app --attack-mode) — there is no per-environment CLI subcommand yet.

Via Dashboard

  1. Go to Projects and select your project
  2. Open Settings → Security
  3. Toggle Enable Attack Mode in the Attack Mode card
  4. Click Save Attack Mode Settings

When enabled, an orange banner appears on the project detail page:

Attack Mode is enabled for this project -- with a quick-access Disable button to turn it off immediately.

Via CLI

CLI Commands

# Enable attack mode on a project (all environments inherit this)
bunx @temps-sdk/cli projects settings -p my-app --attack-mode

The environments CLI command group has no settings subcommand and no --attack-mode flag today — per-environment Attack Mode can only be toggled from the dashboard or the Via API section below. Only project-wide Attack Mode is available via CLI, with projects settings -p my-app --attack-mode / --no-attack-mode.

Via API

API Examples

# Enable attack mode at the project level
curl -X POST "https://your-temps-instance.com/api/projects/{project_id}/settings" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"attack_mode": true}'

# Disable attack mode at the project level
curl -X POST "https://your-temps-instance.com/api/projects/{project_id}/settings" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"attack_mode": false}'

Per-Environment Override

A common use case is keeping attack mode on for production while off for staging: your public traffic gets the PoW challenge, but internal CI runners and QA engineers are not blocked by it. See Environments for how environments are set up.

  1. Go to Project Settings → Environments
  2. Select the environment (production, staging, preview)
  3. Open the Security card
  4. Toggle Attack Mode for that specific environment

Environment-level settings override project-level settings -- they are not additive. If attack mode is enabled at the project level but explicitly disabled on staging, staging traffic bypasses the PoW challenge entirely. Likewise, if it is disabled at the project level but enabled on production, only production visitors must solve the challenge.


Configuration inheritance

Attack mode is read at two levels, project and environment. An environment-level value always wins over the project-level value (not additive); an environment with no value of its own inherits the project's. Security headers and the IP access list resolve differently; see Security Settings.

Last updated

Was this page helpful?