Skip to content

Cache *http.Client on PresetLoader; share TransportFactory in slack.go #630

@CybotTM

Description

@CybotTM

Surfaced during the DRY/sibling review of #624. Two follow-ups to the preset-loader transport hardening that PR #624 left for a future change.

A. Per-call client construction

`middlewares/preset.go::loadFromURL` constructs `&http.Client{Transport: TransportFactory()}` on every call. `TransportFactory()` returns a fresh `*http.Transport` per call (see `webhook_security.go::NewSafeTransport`), so each preset fetch gets its own connection pool with no idle-conn reuse. For the cache-miss path this is fine (one-shot fetch), but bursts wouldn't share connections.

Fix: cache the `*http.Client` on the `PresetLoader` struct in `NewPresetLoader`. Document that `SetTransportFactoryForTest` must run before `NewPresetLoader` to influence the cached client.

B. `slack.go` doesn't share TransportFactory

`middlewares/slack.go:94` constructs `&http.Client{Timeout: 5 * time.Second}` with no custom transport when the config doesn't supply one. So Slack notifications inherit the same risk PR #624 fixed for presets — implicit `http.DefaultTransport` posture, no convergence with the webhook stack's TLS-aware transport.

Fix: change the slack.go fallback to `&http.Client{Transport: TransportFactory(), Timeout: 5 * time.Second}`. The Slack middleware is deprecated in favor of the generic webhook system, but operators are still using it; defense-in-depth applies.

Severity

Low — defense-in-depth and minor performance. No CVE.

Acceptance

  • `PresetLoader` holds a cached `*http.Client` (or a function that returns one).
  • `slack.go` fallback client uses `TransportFactory()`.
  • Regression test for slack: assert the fallback client's transport is the one returned by `TransportFactory()`.

Related

  • #615 — preset loader TLS posture
  • #624 — the fix that left these as follow-ups

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions