Skip to content

v0.4.0

Latest

Choose a tag to compare

@gl0bal01 gl0bal01 released this 23 Jun 07:03

Security

  • Dependency advisories — override transitive undici to ^6.27.0
    (GHSA-vxpw-j846-p89q) and ws to ^8.21.0 (GHSA-96hv-2xvq-fx4p), both high
    severity, reached via discord.js. bun audit --audit-level=high is clean.
  • No raw error text to usersformatInteractionError no longer echoes
    arbitrary error messages to Discord replies (could leak filesystem paths,
    remote URLs, or git command lines); full errors stay in the logs.

Added

  • Typed CTFd errorsCtfdAuthError / CtfdApiError in core, thrown by the
    CTFd client and matched via instanceof (with cause-chain unwrapping)
    instead of brittle message-string sniffing.
  • Shared Discord reconcilerensureChallengeThreads,
    textChannelsUnderCategory, and fetchThreadNames consolidate the
    category-channel + per-challenge thread logic used by /ctf start,
    /ctf refresh, and the poller. Dedup includes archived threads.
  • RepoManager.countChallenges() — parallel repo walk counting
    .challenge-id markers; /ctf status now reports CTFd / Git / Discord counts.
  • Operator toolingscripts/install-vps.sh hardened systemd installer,
    make verify-live smoke-test checklist, and grouped make help.

Changed

  • Bot requires SSH remotesvalidateGitRemoteUrl({allowHttps}); the bot
    rejects HTTPS git remotes (it runs non-interactively and can't supply
    credentials). Behavior change for bot users on HTTPS remotes. The CLI
    still allows HTTPS for interactive use.
  • /ctf status responsiveness — defers the reply, runs per-CTF cache load,
    repo walk, and Discord fetch concurrently, and counts threads via a live API
    fetch (restart-safe; no longer reports 0 from a cold gateway cache).
  • ensureChallengeThreads contract — requires a defined categoryId; the
    poller guards an unset category so it can no longer create orphan channels at
    the guild root.

Fixed

  • Duplicate threads after auto-archive — the dedup set now includes archived
    threads, so a thread that auto-archived (7-day default) is not recreated on the
    next refresh/poll.
  • Partial-init visibility/ctf start surfaces a shortfall warning when
    some challenge threads fail to create, instead of reporting success.

Removed

  • docs/migration.md (pre-v0.3.0 upgrade path) and docs/release.md
    (internal release checklist).

Fixed (anti-slop cleanup pass)

  • Slug-collision guard correctness.challenge-id now written with O_EXCL;
    EACCES/EIO/EISDIR on read no longer silently bypass the collision check.
  • Lock acquire error classification — non-EEXIST errors (EACCES, ENOSPC,
    EROFS, EISDIR) surface immediately instead of busy-looping until timeout.
  • Bot commit-push lock cascadecommitAndPush now acquires + releases
    the FileLock per closure; chained pushes no longer hit a 5s lock-acquire
    timeout when commits land within the debounce window.
  • Poller resilience — reschedule moved into finally so a synchronous
    throw cannot kill polling; each thread-create is wrapped per-iteration so one
    bad challenge no longer poisons forward progress.
  • Poller TOCTOUmeta is plumbed into createThreadsForNewChallenges
    instead of refetched via getActiveCTF (which would throw if the CTF was
    archived between the loop start and the call).
  • ctf-start ordering and cleanup — guild check runs before lock.acquire;
    Discord channel creation block is wrapped so a mid-loop failure deletes the
    partial category instead of leaving orphans.
  • ctf-start download error visibility — download phase failure now appears
    in the user-facing reply instead of being silently logged.
  • CTFd auth-redirect detectionisAuthRedirect parses the location as a
    URL and checks pathname/searchParams.has("next") instead of brittle
    substring matches (?nextpage= no longer false-positives; CTFd installs at
    non-root paths like /ctf/login are correctly detected).
  • DNS-rebinding mitigation TTLvalidatedOrigins cache is bounded to 60s
    so a one-time public-IP lookup cannot defeat the SSRF guard forever.
  • CLI password prompt SIGINT — Ctrl-C / Ctrl-D in the raw-mode prompt now
    restores terminal state instead of leaking raw mode.
  • CLI writeup editor exit — non-zero editor exit (e.g. :cq) logs a warning
    instead of producing an unhandled promise rejection.
  • CLI refresh auth-error hint — adds a session-expiry hint when the error
    looks auth-related.
  • Bot active-CTF resolutiongetActiveCTF no longer silently falls back
    to active[0]. Behavior change: /ctf-refresh and /ctf-archive
    invoked outside a challenge thread now require currentCTF to be set (via
    /ctf-use or per-thread context); previously they would pick the first
    active CTF found. Intended as a safety improvement — prevents writes to a
    random CTF when the caller's context fails to resolve.

Fixed (follow-up cleanup)

  • /claim race-safety — team-mapping and claim writes for the same CTF
    now run under a per-CTF FileLock. Concurrent /claim invocations no longer
    drop the loser's team mapping or interleave their writes.
  • /ctf start ordering — commit happens first, then registerCTF, then
    push. A push failure no longer leaves a remote scaffold without a local
    record; the user can recover with a manual git push.
  • Auth-resolver input narrowedresolveAuthAndClient now accepts a
    structural AuthInput ({url, name?, token, sessionCookie, username})
    instead of a full CTFMeta. init and ctf start no longer fabricate
    placeholder repo: "" / repoPath: "" / status: "active" fields.
  • Shared download-summary formatterformatDownloadSummary() in core
    produces the headline/lines/overflow shape consumed by both CLI init and
    bot /ctf start.
  • Shared Discord rate-limit constantDISCORD_THREAD_CREATE_DELAY_MS
    exported from bot/index.ts and used by both poller and ctf-start.

Added

  • Persistent active CTF pointer for CLIctfd use <name> now writes
    currentCTF in global config and command resolution honors it.
  • CTF Discord routing metadata — CTF meta now stores Discord guild/category
    identifiers so poller and thread commands can target the correct CTF context.
  • Download summary plumbingdownloadChallengeFilesForCTF() now returns
    downloaded/skipped counts with skip reasons; callers surface/report skips.
  • Challenge slug-collision guardRepoManager now writes and validates
    per-directory .challenge-id markers to prevent silent overwrite when
    different challenges map to the same slug path.

Changed

  • Poll scheduling model — bot poller now runs serialized recursive ticks
    (no overlapping setInterval async executions).
  • CLI and bot repo path consistency — CLI init/join now use
    repoPathFor(ctfName) under data root, matching bot behavior.
  • Service install semanticsmake service-install no longer errors on an
    existing /etc/ctfd-warboard/bot.env; deployment docs updated accordingly.
  • Challenge markdown file links — generated links now strip query/hash
    components (e.g. token query parameters) before writing to git.

Fixed

  • Critical lock raceFileLock.acquire() now uses atomic wx lockfile
    creation, preventing concurrent contenders from both acquiring a fresh lock.
  • CLI credential durability — init persists the actual username for
    password-based auth; refresh now uses shared auth resolver and persists
    refreshed session cookies.
  • CLI writeup editor flowctfd writeup now waits for editor process exit.
  • Bot /solve CTF mismatch — solve now resolves CTF from thread context and
    requires the challenge to exist in the active CTF cache before submission.
  • Cross-process git safety for bot writes — bot commit/push path now acquires
    the same file lock family used by CLI operations.
  • /ctf start race window — per-CTF lock is acquired before Discord/channel
    creation and initialization workflow.
  • Poller channel misrouting — new-thread creation is scoped to stored
    guild/category instead of matching category names across all guilds.
  • Cache diff blind spot — challenge file list changes are now detected as
    updates.
  • Validation side effect — removed console.warn from URL validation.