Skip to content

refactor: tunable limits against resource exhaustion#55

Open
sjinks wants to merge 2 commits into
trunkfrom
pltfrm-2254-unbounded-handshake-buffer-enables-memory-exhaustion
Open

refactor: tunable limits against resource exhaustion#55
sjinks wants to merge 2 commits into
trunkfrom
pltfrm-2254-unbounded-handshake-buffer-enables-memory-exhaustion

Conversation

@sjinks
Copy link
Copy Markdown
Member

@sjinks sjinks commented May 7, 2026

The remote auth handshake could previously accumulate bytes without a hard cap while extending read deadlines per packet, allowing slow-loris style clients to keep handshakes alive and grow memory usage over time.

This change hardens the handshake path and makes limits configurable.

What's changed

  • Added a maximum handshake payload size to prevent unbounded buffer growth.
  • Enforced both:
    • an absolute handshake timeout, and
    • an idle timeout between packets.
  • Added a concurrency gate for in-progress handshakes to avoid unbounded goroutine fanout.
  • Refactored handshake reading into a dedicated helper for clarity and testability.
  • Added setup options for handshake controls while preserving backward compatibility through the existing setup path.
  • Added safe default fallback behavior when invalid option values are provided.
  • Exposed handshake controls as CLI flags.
  • Documented new remote hardening options and production baseline guidance in the README.
  • Added tests for:
    • normal handshake reads,
    • oversized handshake rejection,
    • setup defaulting behavior on invalid values.

New defaults

  • Max handshake bytes: 65536
  • Initial handshake timeout: 15s
  • Handshake idle timeout: 200ms
  • Max concurrent handshakes: 256

Why

These controls mitigate unauthenticated resource-exhaustion vectors by bounding handshake memory, time, and concurrent admission pressure, while keeping operators able to tune for their environment.

The remote auth handshake could previously accumulate bytes without
a hard cap while extending read deadlines per packet, allowing
slow-loris style clients to keep handshakes alive and grow memory
usage over time.

This change hardens the handshake path and makes limits configurable.

#### What's changed

- Added a maximum handshake payload size to prevent unbounded buffer
growth.
- Enforced both:
  - an absolute handshake timeout, and
  - an idle timeout between packets.
- Added a concurrency gate for in-progress handshakes to avoid
unbounded goroutine fanout.
- Refactored handshake reading into a dedicated helper for clarity and
testability.
- Added setup options for handshake controls while preserving backward
compatibility through the existing setup path.
- Added safe default fallback behavior when invalid option values
are provided.
- Exposed handshake controls as CLI flags.
- Documented new remote hardening options and production baseline
guidance in the README.
- Added tests for:
  - normal handshake reads,
  - oversized handshake rejection,
  - setup defaulting behavior on invalid values.

#### New defaults
- Max handshake bytes: 65536
- Initial handshake timeout: 15s
- Handshake idle timeout: 200ms
- Max concurrent handshakes: 256

#### Why
These controls mitigate unauthenticated resource-exhaustion vectors by
bounding handshake memory, time, and concurrent admission pressure,
while keeping operators able to tune for their environment.
@sjinks sjinks self-assigned this May 7, 2026
@sjinks sjinks marked this pull request as ready for review May 7, 2026 21:48
Copilot AI review requested due to automatic review settings May 7, 2026 21:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Hardens the remote WP-CLI authentication handshake path to mitigate unauthenticated resource-exhaustion risks (slow-loris/memory growth) by adding configurable limits and exposing them via CLI flags and documentation.

Changes:

  • Added configurable handshake limits (max bytes, absolute timeout, idle timeout) and refactored handshake reading into a helper.
  • Introduced a concurrency gate intended to cap concurrent in-progress handshakes.
  • Exposed new controls via CLI flags and documented recommended production baselines; added tests for handshake reading and option defaulting.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
remote/remote.go Adds tunable handshake byte/time limits, handshake reader helper, and a semaphore-based concurrency gate.
remote/remote_test.go Adds unit tests for handshake reads, oversized rejection, and Setup option defaulting behavior.
readme.md Documents new remote handshake hardening flags and baseline recommendations.
main.go Wires new handshake limit options into CLI flags and passes them into remote.SetupWithOptions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread remote/remote.go
Comment thread remote/remote.go Outdated
Comment thread remote/remote.go Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Comment thread remote/remote.go
Comment on lines +340 to +344
log.Println("waiting for auth data")

bufReader := bufio.NewReader(conn)
data, err = readHandshakeData(conn, bufReader)
if nil != err {
Comment thread remote/remote.go
Comment on lines +289 to +297
if read > 0 {
if len(data)+read > maxHandshakeBytes {
return nil, fmt.Errorf("error handshake exceeds maximum size of %d bytes", maxHandshakeBytes)
}

data = append(data, buf[:read]...)
if data[len(data)-1] == '\n' {
break
}
Comment thread main.go
Comment on lines 31 to +35
eventsWebhookURL string
maxHandshakeBytes int
handshakeInitialTTL time.Duration
handshakeIdleTTL time.Duration
maxHandshakeSessions int
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.

2 participants