Skip to content

fix(enhance): strip trailing slashes without a backtracking regex (CodeQL #4) - #128

Merged
wave-av-agent[bot] merged 1 commit into
mainfrom
fix/enhance-base-url-redos
Sep 8, 2026
Merged

fix(enhance): strip trailing slashes without a backtracking regex (CodeQL #4)#128
wave-av-agent[bot] merged 1 commit into
mainfrom
fix/enhance-base-url-redos

Conversation

@wave-av-agent

@wave-av-agent wave-av-agent Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

What

Replaces the trailing-slash regex in the EnhanceAPI constructor with the repo's existing
linear helper:

-    this.baseUrl = info.baseUrl.replace(/\/+$/, '');
+    this.baseUrl = stripTrailingSlashes(info.baseUrl);

plus the matching import { stripTrailingSlashes } from './url-util';. That is the entire
production change — two lines in src/enhance.ts.

Why

CodeQL alert #4 (js/polynomial-redos) fires on src/enhance.ts:57:
https://github.com/wave-av/sdk/security/code-scanning/4

The pattern /\/+$/ is anchored at the end, so on an input shaped ////…x the engine restarts
the \/+ run at each successive slash position and re-scans to the end each time — quadratic in
the length of the slash run. The baseUrl here arrives from client.getConnectionInfo(), i.e.
caller-supplied SDK configuration rather than attacker-controlled wire data, so the practical
exposure is small. It is still worth removing at the source: it is the last live instance of a
shape this repo has already decided against, and leaving one behind keeps the alert open and
trains the next contributor to copy it.

Precedent — this is not a new pattern

src/url-util.ts already exports stripTrailingSlashes(input: string): string, a plain
charCodeAt loop that was written specifically to replace this regex, and its docblock names
the same CodeQL rule. It is already the way four other modules do this:

  • src/custody.ts:51this.baseUrl = stripTrailingSlashes(opts.baseUrl)
  • src/automations.ts:25this.endpoint = stripTrailingSlashes(opts.endpoint)
  • src/realtime.ts:47,127this.wsBase = stripTrailingSlashes(...)
  • src/runtime.ts:69this.baseUrl = stripTrailingSlashes(opts.baseUrl)

enhance.ts was simply the one caller that never got migrated. A grep of src/ for
replace(/\/+$/ now returns only the prose reference inside the url-util.ts docblock — there
are no remaining code sites.

Behaviour is identical for every input, including the edge cases already pinned by
src/__tests__/url-util.test.ts ('''', '////''', no-trailing-slash input returned
by identity). Only the scanning cost changes, from backtracking to linear.

Test evidence

One new case added to the existing src/__tests__/enhance.test.ts, mirroring how the file's
other tests build a mock WaveClient and stub global.fetch: a client configured with
baseUrl: "https://api.wave.online///" must still request
https://api.wave.online/v1/enhance?model=espcn.

This is a real guard, not a tautology — new URL() does not collapse duplicate path slashes, so
without the strip the SDK would call https://api.wave.online////v1/enhance.

npm run lint   → eslint src/ --max-warnings 0 — clean, 0 errors / 0 warnings
npm test       → Test Files 24 passed | 1 skipped (25)
                 Tests     227 passed | 3 skipped (230)
npm run build  → tsup: ESM + CJS + DTS all "Build success"

(The ::error::tag sdk-v9.9.9 … lines in the test output are asserted-on stderr from the
release-tag guard test, not failures.)

dist/ is tracked in this repo and the local npm run build churned it; that churn is
deliberately not included here — only src/enhance.ts and src/__tests__/enhance.test.ts
are staged, so the diff stays reviewable.

Merge

Public repo — needs one human CODEOWNER approval; wave-av-agent merges after that once the
exemption lands. Not merging from this branch, and no labels added.


Note

Low Risk
Small, behavior-preserving URL normalization change in SDK config handling; no auth or wire-format changes.

Overview
EnhanceAPI now normalizes baseUrl with the shared stripTrailingSlashes helper from url-util instead of replace(/\/+$/, ''), aligning with custody, automations, realtime, and runtime and clearing the CodeQL js/polynomial-redos alert on that regex.

Behavior is unchanged for typical URLs; the scan is linear instead of backtracking on long trailing-slash runs.

A new enhance.test.ts case asserts that a client configured with https://api.wave.online/// still POSTs to https://api.wave.online/v1/enhance?model=espcn (without duplicate path slashes in the request URL).

Reviewed by Cursor Bugbot for commit c68178e. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by Sourcery

Normalize EnhanceAPI base URLs with the shared linear helper and verify trailing-slash handling.

Bug Fixes:

  • Replace the EnhanceAPI trailing-slash regex with the shared linear URL normalization helper to eliminate the CodeQL polynomial-ReDoS finding while preserving URL behavior.

Enhancements:

  • Align EnhanceAPI base URL handling with the other SDK APIs by using the shared trailing-slash utility.

Tests:

  • Add coverage confirming caller-configured base URLs with multiple trailing slashes produce requests without duplicate path separators.

Review in cubic


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…deQL js/polynomial-redos #4)

CodeQL alert #4 flags `/\/+$/` applied to a caller-configured baseUrl in the
EnhanceAPI constructor: on inputs shaped `////...x` the pattern re-scans
quadratically. src/url-util.ts already carries the linear stripTrailingSlashes
loop written to close this exact finding, and custody/automations/realtime/runtime
already use it — enhance.ts was the last caller of the regex. Behaviour is
unchanged for every input; covered by a new test asserting a `///` baseUrl still
produces a single-slash /v1/enhance URL.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codeant-ai

codeant-ai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Skipping PR review because a bot author is detected.

If you want to trigger CodeAnt AI, comment @codeant-ai review to trigger a manual review.

@sourcery-ai

sourcery-ai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

EnhanceAPI now uses the repository’s linear stripTrailingSlashes helper instead of an end-anchored backtracking regex, eliminating the CodeQL polynomial- ReDoS finding while preserving URL behavior. A regression test verifies correctly formed enhancement request URLs for caller-configured base URLs with multiple trailing slashes.

Sequence diagram for normalized EnhanceAPI request URLs

sequenceDiagram
    participant Client
    participant EnhanceAPI
    participant stripTrailingSlashes
    participant Fetch

    Client->>EnhanceAPI: new EnhanceAPI(client)
    EnhanceAPI->>Client: getConnectionInfo()
    Client-->>EnhanceAPI: baseUrl with trailing slashes
    EnhanceAPI->>stripTrailingSlashes: stripTrailingSlashes(info.baseUrl)
    stripTrailingSlashes-->>EnhanceAPI: normalized baseUrl
    Client->>EnhanceAPI: enhance(model)
    EnhanceAPI->>Fetch: POST normalized baseUrl/v1/enhance?model=espcn
    Fetch-->>EnhanceAPI: response
Loading

File-Level Changes

Change Details Files
Replace EnhanceAPI’s trailing-slash regex with the shared linear URL normalization helper.
  • Import and apply stripTrailingSlashes when storing the configured base URL.
  • Avoid polynomial backtracking on long trailing-slash runs while preserving existing normalization behavior.
src/enhance.ts
Add regression coverage for base URLs containing multiple trailing slashes.
  • Mock a client configured with three trailing slashes.
  • Verify enhancement requests use the normalized endpoint without duplicate path separators.
src/__tests__/enhance.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@greptile-apps

greptile-apps Bot commented Sep 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces EnhanceAPI’s potentially quadratic trailing-slash regex with the existing linear URL utility.

  • Preserves trailing-slash normalization behavior for configured base URLs.
  • Adds request-level coverage for base URLs containing multiple trailing slashes.
  • Introduces no authentication, authorization, or wire-format changes.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness, security, or quality issues identified.

The helper preserves existing normalization semantics, uses an established import pattern, and the added test exercises the resulting request URL with isolated mock state.

Important Files Changed

Filename Overview
src/enhance.ts Reuses the established linear trailing-slash helper with behavior equivalent to the replaced regex.
src/tests/enhance.test.ts Adds deterministic coverage confirming normalized base URLs produce the expected enhancement endpoint.

Reviews (1): Last reviewed commit: "fix(enhance): strip trailing slashes wit..." | Re-trigger Greptile

@macroscopeapp

macroscopeapp Bot commented Sep 7, 2026

Copy link
Copy Markdown

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This is a small, behavior-preserving change that reuses existing linear URL normalization and adds focused regression coverage. Human review remains appropriate because it is explicitly a CodeQL polynomial-ReDoS security remediation and modifies files owned by the core team rather than the stated author.

Not approved because:

  • Credit balance exhausted. Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

@yakimoto yakimoto left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CODEOWNER approval for the exemption proof

@wave-av-agent
wave-av-agent Bot added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 3dc49de Sep 8, 2026
40 checks passed
@wave-av-agent
wave-av-agent Bot deleted the fix/enhance-base-url-redos branch September 8, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant