GitHub
10/27/2026, 10:12 AMhttp was re-sent there with its body, which contains the enrollment secret. This affected every osctrl endpoint (flags, cert, verify, script, extensions, extension download, status, osctrld-osquery).
• A plain http:// baseurl or osqueryPackage was accepted without any warning, although the secret and the extension manifest then travel in cleartext.
• HTTPS_PROXY was ignored for HTTPS, and every request built a new transport whose idle connections never closed.
Change
• Redirect policy (redirectPolicy in http-utils.go). Requests that carry the secret follow redirects only to the same scheme, host and port (default ports count as equal), or from http to https on the same host name with any ports. They refuse any other redirect: other host, https to http, other scheme, or more than 10 hops. A refused redirect error names only the scheme and host, never the path or query.
• Package downloads (downloadStream, install and upgrade) carry no secret and are verified by SHA-256. They may follow https redirects to another host (for example a CDN) but never downgrade to http.
• Warning. warnCleartextURLs logs one warning per option at startup (baseurl, osqueryPackage) when the scheme is http. check-config shows it too. Plain http is still accepted so existing fleets keep working.
• Transport. newHTTPClient honours HTTP_PROXY, HTTPS_PROXY and NO_PROXY and closes idle connections after 90 seconds. TLS behaviour is unchanged: system cert pool, InsecureSkipVerify only with --insecure, and the official package server certificate is always verified.
• README: short note under the configuration table.
Security / operational impact
• Closes secret leakage through cross-host and downgrade redirects.
• Behaviour changes:
• A redirect from osctrl to another host, an https to http redirect, or a redirect to another scheme now fails the request.
• Package downloads can no longer be redirected from https to http.
• Proxy environment variables now apply to HTTPS traffic.
• An http baseurl or osqueryPackage logs a warning at every start.
• Plain http requests now use the same transport as https, so --insecure applies when an http URL redirects to a self-signed https server. They lose the default transport's 30-second dial and handshake timeouts; the 10-minute whole-request timeout still bounds them.
• An http osquery package URL gives little protection from its SHA-256, because the digest comes from the server over the same channel when baseurl is http. The baseurl warning covers this.
• No refusal rule was added for http osqueryPackage, because downloadPackage already refuses an empty digest unless allowUnverified is set.
Validation
• go test ./... -count=1, go vet for linux, darwin and windows, gofmt, golangci-lint.
• Tests, each seen failing first:
• an https to http redirect on another host receives the body;
• a cross-host https redirect succeeds;
• a package download downgrades to `http`;
• a nil proxy on the https transport;
• the http warning is missing;
• a table test of same-origin and http to https rules, with 7 cases failing before the fix.
• Guards kept: same-origin 307 still delivers the body, a redirect loop is bounded, a package download follows a cross-host https redirect, and an http to https upgrade on the same host works.
• The proxy test inspects the transport instead of running a live proxy, because ProxyFromEnvironment caches the environment per process and never proxies loopback addresses.
Not in this PR
• Config handling (precedence, strict keys, interval cap, URL normalisation, sample config): separate PR.
• Windows secret ACL, atomic file writes, macOS deployment checks.
jmpsec/osctrldGitHub
10/27/2026, 10:14 AM