Skip to content

Tako VM v0.3.0

Latest

Choose a tag to compare

@github-actions github-actions released this 02 Sep 03:33
e80de56

A security release, and the one that closes the hole the quickstart itself
published: docker compose up served an unauthenticated POST /execute on
every interface, plus PostgreSQL on 5432 with postgres/postgres. Anyone
who followed the README was running remote code execution open to their
network. Upgrade before anything else.

The minor bump is the max_timeout ceiling below, not the security fixes: a
deployment whose job_types declare a timeout above max_timeout is now
refused at startup instead of quietly exceeding its own limit.

Security

  • --host can no longer bypass the fail-closed bind guard. The config
    validator refused api_auth_enabled: false together with a non-loopback
    server_host, but tako-vm server --host 0.0.0.0 resolved the host after
    validation and handed it straight to uvicorn unchecked. The shipped
    docker/Dockerfile.server CMD does exactly that, over a baked-in config
    with authentication disabled, so docker compose up published an
    unauthenticated POST /execute code-execution endpoint on every interface.
    The CLI now re-applies the config's own rule (ensure_bind_host_allowed,
    one rule shared by the validator and the CLI) to the host it actually binds,
    and exits with a message naming all three ways out.
    TAKO_VM_ALLOW_UNAUTHENTICATED_NETWORK_ACCESS is a new environment override
    for the existing escape hatch, needed because container images bake in their
    config file.
  • docker-compose.yaml no longer publishes PostgreSQL on the host. The
    postgres service mapped 5432:5432 with postgres/postgres
    credentials; the API reaches it by service name over the compose network, so
    the mapping only exposed the database to anything that could route to the
    host. Credentials are now interpolated from TAKO_VM_POSTGRES_USER /
    TAKO_VM_POSTGRES_PASSWORD / TAKO_VM_POSTGRES_DB with a placeholder
    default. The API's own port is now published on 127.0.0.1:8000 only.
  • Rate limiting now runs before the authentication rejection. Failed-auth
    requests returned 401 before reaching the limiter, so API-key brute force was
    unmetered and the DoS control was inert against unauthenticated callers.
    Identity is still resolved first, so authenticated clients keep their
    per-key buckets.
  • A non-ASCII API key header no longer returns HTTP 500.
    hmac.compare_digest raises TypeError on non-ASCII str operands; that
    reached the middleware's catch-all, which logged a full traceback at ERROR
    and returned 500 — an unauthenticated log-flood amplifier. Keys are now
    compared as UTF-8 bytes.

Changed

  • BREAKING: a configured job type may no longer declare a timeout above
    max_timeout
    (#146). max_timeout is documented as the maximum allowed
    execution timeout, but it only bounded explicit per-request overrides: a
    request could name a job type whose default exceeded it and the worker would
    run the larger value. The ceiling is now enforced on the effective timeout
    at three layers — config validation, the API boundary, and the worker — so a
    deployment whose job_types declare a timeout above max_timeout is refused
    at startup instead of quietly exceeding its own limit. Raise max_timeout to
    cover the largest job type you run.
  • default_timeout now applies to requests that name no job type. Such
    requests previously resolved the built-in default job type's hardcoded 30s and
    ignored default_timeout entirely; they now use the configured value. Both
    are 30 out of the box, so this changes nothing unless the deployment sets
    default_timeout.
  • The timeout request field accepts values up to 86,400 seconds rather
    than being capped at 300 by the request schema (#146, fixes #143). This is an
    absolute schema ceiling only — the deployment's max_timeout (default 300)
    still applies and rejects anything above it with HTTP 422, so the accepted
    range is unchanged unless an operator raises max_timeout.