Skip to main content
Anubis supports custom challenge types through the challenge.Impl interface. This allows you to create specialized bot detection mechanisms beyond the built-in proof-of-work, meta-refresh, and Preact challenges.

Challenge Interface

All challenge implementations must satisfy the challenge.Impl interface:
Source: lib/challenge/interface.go:59-68

Input Structures

IssueInput

Provided when issuing a new challenge:

ValidateInput

Provided when validating a challenge response:

Challenge Metadata

Source: lib/challenge/challenge.go:6-15

Implementation Example: Proof-of-Work

Here’s how the built-in proof-of-work challenge is implemented:
Source: lib/challenge/proofofwork/proofofwork.go

Implementation Example: Meta Refresh

The meta-refresh challenge validates timing constraints:
Source: lib/challenge/metarefresh/metarefresh.go:51-64

Registration

Register your challenge implementation in an init() function:
The registry is thread-safe and uses sync.RWMutex for concurrent access. Source: lib/challenge/interface.go:15-32

Error Handling

Use the challenge error constructors for consistent error reporting:
Source: lib/challenge/error.go:9-22

Best Practices

  1. Security-first: Use constant-time comparison for secrets (crypto/subtle.ConstantTimeCompare)
  2. Difficulty scaling: Honor in.Rule.Challenge.Difficulty from the policy configuration
  3. Localization: Use localization.GetLocalizer(r) for internationalized UI
  4. Metrics: Emit Prometheus metrics for observability (see lib/challenge/metrics.go)
  5. Structured logging: Use the provided *slog.Logger for diagnostic output
  6. Templ components: Return templ.Component for HTML rendering consistency

Configuration

Once registered, reference your challenge in policy files:

Available Challenge Methods

Query registered challenges at runtime:
Source: lib/challenge/interface.go:27-42