GitHub
10/16/2026, 9:24 PMPOST /{env}/osctrld-flags and POST /{env}/osctrld-verify rebuilt the flags from the built-in template (GenerateFlags) on every request. They ignored env.Flags, the flags operators edit in the UI and through the API, which the enroll scripts already use.
As a result, osctrld service overwrote operator flag changes on each node with the generated defaults and restarted osqueryd. Any custom flag was lost on the next sync, for example --extensions_autoload or a changed logger setting.
What changes
• environments.NodeFlags: the flagfile a node runs with.
• It returns the environment's stored flags, with the __SECRET_FILE__ and __CERT_FILE__ placeholders filled from the paths osctrld sends.
• It falls back to the generated defaults when the environment has no stored flags.
• environments.FillFlagPaths: the shared placeholder replacement.
• An empty path keeps its placeholder, the same contract as GenerateFlags.
• FlagsHandler and VerifyHandler use NodeFlags, so both serve the same flags and osctrld verify compares against what osctrld flags writes.
• The API's per-OS flags download (substitutePlatformPaths) now uses FillFlagPaths. Its output is unchanged.
Security and operational impact
• Restart on first sync: nodes running osctrld service get the stored flags on their next sync. Where these differ from the generated defaults, osqueryd restarts once on that node.
• Stale values: stored flags reflect the environment as it was when they were last generated or edited. An environment whose hostname or intervals changed afterwards, without regenerating its flags, now serves the stored values instead of freshly generated ones. Regenerate or edit the flags to update them.
• Unchanged:
• authentication: the environment secret is still checked in constant time;
• body limits and route registration: the endpoints are still only enabled with `osctrld.enabled`;
• the response formats.
• No schema, configuration or OpenAPI changes.
Validation
• `go test ./... -count=1`: all 55 packages pass
• go vet ./..., gofmt -l pkg cmd (empty)
• `golangci-lint run ./pkg/environments/... ./cmd/tls/... ./cmd/api/...`: 0 issues
• New handler tests in cmd/tls/handlers/osctrld_flags_test.go. These are the first tests for these handlers.
• Stored flags are served, with paths filled, by both the flags and the verify endpoints. Failed before the change.
• Placeholders are kept when no path is sent. Failed before the change.
• The fallback to generated flags for environments with none stored. Passes before and after.
• A wrong secret is rejected with 403 on both endpoints. Passes before and after.
jmpsec/osctrlGitHub
10/16/2026, 9:29 PM