Skip to content

Post-1.0 hardening: CI gaps and deferred code-scanning findings #605

Description

@therealbrad

Follow-ups deferred from the v1.0.0 release (#604). None of these blocked the release; they surfaced when the beta tree merged to main and the whole diff read as added lines, so the scanners saw this code for the first time.

CI gaps

a11y-smoke.yml has no push trigger. It fires only on workflow_dispatch and pull_request. Anything landing directly on beta (or main) never runs the gate — which is how a critical button-name violation sat on the release candidate through several pre-releases before #604 caught it. Adding push: branches: [main, beta] closes the hole.

Eight workflows declare no permissions: block: a11y-smoke, cli-release, db-integration, docs-release, e2e-smoke, packages-release, release-selfhost, release. The repository default is already read (gh api repos/TestPlanIt/testplanit/actions/permissions/workflow), so this is documentation of an existing guarantee rather than a live exposure — but it silences a recurring CodeQL finding and pins the guarantee against a future change to the repo default.

Code scanning

OfficeDocumentPreview.tsx — incomplete URL scheme check. CodeQL notes the check does not consider data: and vbscript:. This is the one finding from the batch I'd treat as a plausible real bug; it needs a look at whether the URL reaches an href/src.

Polynomial ReDoS on uncontrolled datalib/llm/adapters/anthropic.adapter.ts and app/api/admin/llm/available-models/pricing.ts (x2). URL-normalisation regexes that degrade on inputs with many / repetitions. The input is an admin-supplied base URL, so the blast radius is small.

Externally-controlled format stringservices/forecastService.ts (x2) and services/testRunService.ts. Not investigated; needs triage to confirm or dismiss.

Assessed and dismissed — recorded so they are not re-litigated

utils/stripHtmlTags.ts (double escaping; incomplete multi-character sanitization) — not exploitable. Its output feeds plainText for truncated display and as a sort key. The adjacent HTML path uses DOMPurify.sanitize with an explicit ALLOWED_TAGS allow-list. CodeQL is flagging a plain-text extractor as though it were the sanitizer.

SSRF in app/api/admin/llm/available-models/ (x3) — the route rejects anything but session.user.access === "ADMIN". An administrator pointing TestPlanIt at an LLM endpoint is the feature, not a bypass.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions