Skip to content

feat!: v0.2 hardening from the security and design reviews - #5

Merged
ETWOYA merged 2 commits into
mainfrom
feat/v0.2-hardening
Oct 11, 2026
Merged

ETWOYA merged 2 commits into
mainfrom
feat/v0.2-hardening

Conversation

@dankoverride

Copy link
Copy Markdown
Collaborator

v0.2: the fixes from the security code review and the design review (SYN-SP-001). No new features.

Limits no manifest can raise

  • run.maxCallsPerSecond at most 1000 (NaN and Inf rejected), run.interval at most 24h, 10,000 calls per pass, 1,000 distinct gRPC targets
  • manifests over 16 MiB are an error (stdin and files), never silently truncated
  • identical calls are made once; duplicates are listed as refused
  • -max-in-flight (default 64): a call beyond the cap is skipped and reported, never queued and never counted as unanswered

Input hardening

  • route paths with ../. segments, //, percent-encoding, ?, #, backslash, spaces or control characters are rejected (they could evade deny rules)
  • baseURL with credentials or a query string is rejected; the error never echoes the credentials
  • gRPC targets must be host:port (no unix: or dns:// resolver schemes)
  • deny rules fail closed on a bad glob

Egress guard: link-local and cloud metadata addresses are refused after DNS resolution, for HTTP and gRPC; -allow-link-local overrides. The test never dials a metadata address (GitHub runners have a live one).

Results and exit codes

  • 401/403 count as answered and are flagged needsAuth (founder ruling 2026-10-08)
  • detail truncated to 512 bytes; call lines gain needsAuth, skipped; pass lines gain skipped, interrupted
  • -once exits 3 when interrupted (previously could exit 0)
  • -once paces with jitter; -spread spreads a single pass across the interval (the mode the worker will use)
  • -insecure with headers is refused unless the endpoint is loopback (-allow-insecure-headers overrides)

Docs: README and DOCKERHUB.md updated for every behaviour change; the README results sample is regenerated from this build. The Docker Hub Overview needs re-pasting after merge.

BREAKING: manifests that parsed before can now be rejected (see input hardening); a 401/403 now counts as answered; an interrupted -once exits 3.

Tests: new tests for every behaviour above; full suite green 3 runs in a row locally (Windows), runner coverage 84% to 92%. The second commit widens three probe-test timeouts after one parallel-suite flake (1.06s against a 1s budget).

🤖 Generated with Claude Code

dankoverride and others added 2 commits October 10, 2026 17:37
Limits no manifest can raise:
- run.maxCallsPerSecond at most 1000 (NaN and Inf rejected), run.interval
  at most 24h, 10,000 calls per pass, 1,000 distinct gRPC targets.
- Manifests over 16 MiB are an error (stdin and files), never truncated.
- Identical calls are made once; duplicates are listed as refused.
- -max-in-flight (default 64): a call beyond the cap is skipped and
  reported, never queued and never counted as unanswered.

Input hardening:
- Route paths with dot segments, //, percent-encoding, ?, #, backslash,
  spaces or control characters are rejected.
- baseURL with credentials or a query string is rejected; the error
  never echoes the credentials.
- gRPC targets must be host:port (no resolver schemes).
- Deny rules fail closed on a bad glob.

Egress guard: connections to link-local and cloud metadata addresses are
refused after DNS resolution, for HTTP and gRPC; -allow-link-local
overrides.

Results:
- 401 and 403 count as answered and are flagged needsAuth.
- detail is truncated to 512 bytes.
- -once exits 3 when interrupted; pass lines carry skipped and
  interrupted.
- -once paces at the rate limit with jitter; -spread spreads a single
  pass across the interval.
- -insecure with headers is refused unless the endpoint is loopback
  (-allow-insecure-headers overrides).
- Defense in depth: the prober refuses any method but GET and HEAD.

BREAKING CHANGE: manifests that previously parsed may now be rejected
(credentials or a query in baseURL, unsafe route paths, gRPC targets
that are not host:port, rates above 1000, intervals above 24h); a 401
or 403 now counts as answered; an interrupted -once exits 3, not 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TestUnauthorizedAndForbiddenAreAnsweredAndNeedAuth failed once at 1.06s
against a 1s call budget when every package ran in parallel on Windows
and a first local connection was slow; it passes in under 10ms alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dankoverride
dankoverride requested a review from ETWOYA as a code owner October 10, 2026 21:39
@ETWOYA
ETWOYA merged commit a6a64c4 into main Oct 11, 2026
1 check passed
@ETWOYA
ETWOYA deleted the feat/v0.2-hardening branch October 11, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants