Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ https://github.com/user-attachments/assets/6f25324c-f765-45a0-8658-d4e4c4e4ec1e
Capture and export control data for learning and analysis

- **Frontend-Only Architecture**
Zero backend dependencies — works out of the box
Zero backend dependencies — works out of the box. The browser demo is not a
security boundary for scored tasks or rewards; production deployments must
verify task completion on a trusted backend.

- **Modular Design**
Easy to extend with new tasks, checkers, and robot models
Expand Down Expand Up @@ -190,6 +192,11 @@ The platform includes a demonstration task where the robot must push a box lid c

## Adding New Tasks

> Security note: task definitions, checker configuration, trajectory exports,
> and completion flags are client-visible in this demo. If completion affects
> accounts, leaderboards, payouts, rewards, or reputation, follow the backend
> verification contract in [Task Completion Verification](docs/task-completion-verification.md).

### Step 1: Create Scene File

Create an MJCF XML scene in `public/mujoco-assets/scenes/`:
Expand Down
36 changes: 36 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Security Policy

## Supported Scope

AxisWebInfra is a frontend-only MuJoCo teleoperation demo. It records and exports
trajectories in the browser and can automatically mark a local task as complete
when the configured checker reports success.

That local completion state is not a security boundary. Do not use a browser
completion flag, client-supplied `is_completed`, client-supplied
`goal_achieved`, or downloadable trajectory JSON as the source of truth for
accounts, leaderboards, payouts, rewards, or reputation.

## Production Completion Verification

Production systems must verify task completion on a trusted backend:

- issue a server-side attempt id and one-time submit nonce before each run
- bind the nonce to the authenticated user, task id, task version, checker
version, scene version, and randomized initial state
- reject replays, expired nonces, duplicate trajectory hashes, oversized
payloads, and malformed samples
- replay or evaluate the submitted trajectory in a controlled server environment
using the canonical checker configuration
- ignore client-supplied completion booleans and compute the completion result
server-side
- compute points, rewards, ranks, and badges only after backend verification

See [Task Completion Verification](docs/task-completion-verification.md) for the
recommended contract.

## Reporting Vulnerabilities

If you find a vulnerability in a production deployment, avoid public exploit
details and report it privately to the project maintainers. Include the affected
endpoint, impact, a minimal non-destructive reproduction, and the expected fix.
107 changes: 107 additions & 0 deletions docs/task-completion-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Task Completion Verification

This document defines the security contract for deployments that use MuJoCo task
completion for accounts, leaderboards, rewards, payouts, or reputation.

## Threat Model

All browser state is attacker-controlled. A user can edit JavaScript, replace
callbacks, forge exported trajectory JSON, replay an old payload, change local
storage, alter timing metadata, and submit arbitrary request bodies.

The frontend may provide useful evidence, but it must never be trusted as the
authority for task completion.

## Required Backend Contract

1. Create an attempt before the simulation starts.

The backend returns an `attempt_id` and one-time `submit_nonce` only to an
authenticated user. The attempt must be bound to:

- user id
- task id and task version
- scene asset version
- checker version
- deterministic randomization seed
- expiration time

2. Make randomization deterministic and server-owned.

If the client needs a nonce or seed to render the same scene, treat that
value as public but signed or server-recorded. On submit, the backend must
reconstruct the same initial state from server records.

3. Accept trajectories as evidence, not proof.

The submit endpoint should accept trajectory samples and metadata, but it
must ignore client-supplied fields such as `is_completed`, `goal_achieved`,
`points`, `score`, `rank`, `bonus`, and `reward`.

4. Validate payload shape before simulation.

Reject payloads that violate:

- maximum compressed and decompressed size
- maximum sample count and duration
- monotonic timestamps
- finite numeric values only
- expected joint, control, object, and action schema
- joint limits, velocity limits, and control limits
- task id and nonce consistency

5. Verify completion in a controlled backend worker.

The backend should replay or evaluate the submitted trajectory against the
canonical MJCF, initial state, domain randomization, and checker config. The
verifier returns `verified`, `failed`, or `needs_review` with a reason.

6. Store immutable verification evidence.

Store the trajectory hash, verifier version, checker version, task version,
result, failure reason, and timing. Use idempotency so repeated submissions
for the same attempt cannot produce multiple rewards.

7. Award only after verification.

Points, rewards, badges, leaderboard entries, referrals, and progress should
be computed exclusively from backend-verified attempts.

## Submit Endpoint Behavior

Recommended behavior for `POST /api/tasks/{task_id}/complete`:

- require an authenticated session
- require an active attempt owned by the user
- require a valid one-time `submit_nonce`
- reject already-consumed or expired nonces
- reject task id mismatches
- enqueue verification for large trajectories
- return a pending or verified attempt id
- never mark completion solely because the request body says it is complete

## Example Verification Flow

```text
client: GET /api/tasks/{task_id}
server: returns task data plus attempt_id and submit_nonce
client: runs MuJoCo locally and exports trajectory
client: POST /api/tasks/{task_id}/complete with attempt_id, submit_nonce, trajectory
server: validates auth, nonce, payload limits, and schema
server: replays/evaluates trajectory with canonical checker
server: stores verified/failed result and consumes nonce
server: awards progress only for verified attempts
```

## Frontend Responsibilities

The frontend should still help users and reduce accidental bad submissions:

- include attempt id and nonce in trajectory metadata
- send task id, task version, checker version, and scene version
- preserve monotonic timestamps and sampling interval metadata
- avoid showing rewards until backend verification succeeds
- display failed or pending verification states clearly

These checks improve user experience but are not security controls by
themselves.