GitHub
10/17/2026, 7:34 AMPATCH /api/v1/environments/config/{env} (EnvironmentConfigPatchHandler) validated flags the same way as the JSON configuration sections. Flags are a plain-text osquery flagfile (--tls_hostname=...), which caused two bugs:
• Saving flags failed. Saving an environment's flags from the environment page always failed with section "flags" is not valid JSON.
• Clearing flags stored {}. Since #1089, the osctrld flags and verify endpoints serve the stored flags as-is. They fall back to the generated defaults only when the stored flags are blank, so osctrld nodes in such an environment would be sent {} as their flagfile.
What changes
• Flags are checked as a flagfile. The new environments.ValidateFlags requires every line to be blank, a # comment, or a flag (-flag or --flag, both of which osquery's gflags parser accepts). A bad line is refused with 400, naming the line number, and nothing is written.
• Empty flags stay empty, so osctrld nodes get the generated defaults.
• The JSON sections (options, schedule, packs, decorators, atc) are still checked as JSON, as before.
• environments.NodeFlags falls back to the generated defaults when the stored flags aren't a valid flagfile. This covers environments that already have {} stored.
Security and operational impact
• Operators can edit and save environment flags from the UI again.
• osctrld nodes no longer receive {}. An environment with {} stored now serves the generated default flags until its flags are saved again.
• The enroll scripts still embed the raw stored flags, so an environment that already has {} stored keeps it in its enroll script. Re-saving that environment's flags fixes both.
• No schema, configuration, permission or OpenAPI changes. The cache invalidation and audit of the PATCH handler are unchanged.
Validation
• `go test ./pkg/environments ./cmd/api/... ./cmd/tls/... -count=1`: passes
• `go vet`; gofmt -l pkg cmd (empty)
• New tests in `cmd/api/handlers/environments_flags_patch_test.go`:
• plain-text flags are stored, trimmed;
• empty flags are stored empty;
• non-flag lines are refused, with nothing written;
• # comments and -flag lines are accepted;
• the JSON sections are still checked.
The first two failed before the fix: the first with section "flags" is not valid JSON, the second by storing {}.
• New test in `cmd/tls/handlers/osctrld_flags_test.go`: TestOsctrldFlagsFallBackOverAStoredEmptyObject, which failed before the fallback was added.
jmpsec/osctrlGitHub
10/17/2026, 7:53 AM