Skip to content

feat(xtcp2): credentials off the command line, S3 over TLS (FP-2) - #294

Merged
randomizedcoder merged 4 commits into
mainfrom
sec/fp2-secrets-s3-tls
Nov 12, 2026
Merged

randomizedcoder merged 4 commits into
mainfrom
sec/fp2-secrets-s3-tls

Conversation

@randomizedcoder

Copy link
Copy Markdown
Owner

Phase F1, FP-2 of the focused container hardening plan (#291). Based on FP-1.

  • Production (slim) flavors refuse -s3AccessKey, -s3SecretKey and the four -listener* secret flags with exit 64, naming the _FILE variable to use. The full flavor warns instead, now for the S3 flags too, and also when the flag and the env are both set.
  • "Production" is a link-time constant (-X main.flavorProduction=true) set for every slim flavor.
  • _FILE secrets: a missing or unreadable path (silently ignored before), a non-regular file, or a group/world-readable one stops startup with exit 64.
  • The flag and config dumps print <redacted>; a descriptor-walking test fails if a new key/token/secret field is not redacted.
  • S3: a bare host:port endpoint now uses TLS (it was plaintext); http:// needs -s3AllowInsecure (gauge xtcp2_s3_insecure); TLS 1.2 minimum; -s3CAFile / S3_CA_FILE. The test S3 fixture and VMs pass -s3AllowInsecure.
  • checks.flavor-tags checks the production mark by behavior: each slim binary refuses -s3SecretKey with 64, the full one does not (-trimpath keeps -ldflags out of the recorded build settings).

🤖 Generated with Claude Code

randomizedcoder and others added 4 commits November 11, 2026 17:53
The netlink capture writer (-writeFiles / -capturePath) writes raw
inet_diag replies, every socket's addresses, to disk; the file:
destination writes records wherever configuration points it. Both were
compiled into every binary, including the production slim flavors.

- capture writer behind //go:build capture, with a no-op stub; no flavor
  or image carries the tag, only the new xtcp2-capture attr
- file: destination behind //go:build dest_file, compiled into the full
  (development) flavor only; stderr split into its own untagged file
- xtcp.CheckBuildSupport: -writeFiles > 0 or -dest file: on a build
  without the tag exits 64 before anything binds, naming the tag;
  ConfigService.Set refuses it with FailedPrecondition
- armed capture logs a warning and sets xtcp2_debug_capture_enabled;
  a capture build reports +capture in its version line
- nix: debugDestinations / optInOnlyTags in versions.nix, extraTags in
  mkGoBinary, test-go-flavor-{file,capture} legs, and a flavor-tags
  check that no slim flavor carries either tag (go version -m)

Focused container hardening FP-1 (A5).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The debug writers moved behind -tags capture and -tags dest_file, so no
lint tier type-checked them. All three tiers now set both tags, matching
the `all` leg of the Go test flavor matrix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…fault

Secrets
- production (slim) flavors link -X main.flavorProduction=true and refuse
  -s3AccessKey, -s3SecretKey and the four -listener* secret flags with
  exit 64, naming the _FILE variable; dev builds warn, now for the S3 flags
  too and even when the env var is also set (flag.Visit on the flag itself)
- one _FILE reader for every credential: a missing/unreadable path, a
  non-regular file or one with group/other permission bits is exit 64;
  it used to be ignored (listener) or logged (S3), leaving it empty
- TestRedactSecretsCoversSecretLikeFields walks the config descriptor and
  fails if a key/token/secret-named field escapes RedactSecrets

S3 transport
- xtcp.S3Endpoint: https:// and bare host:port use TLS (bare was
  plaintext); http:// needs -s3AllowInsecure (S3_ALLOW_INSECURE), which
  warns and sets xtcp2_s3_insecure; other schemes refused
- CheckS3Transport at startup (exit 64) and in ConfigService.Set
- TLS 1.2 floor pinned on the minio transport; -s3CAFile / S3_CA_FILE
- proto: s3_allow_insecure = 107, s3_ca_file = 108
- in-VM Garage fixtures pass -s3AllowInsecure; flavor-tags check asserts
  the production mark on every slim flavor and its absence on full

Focused container hardening FP-2 (A3, A4).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
startupConfig holds the steps that produce the config the daemon runs
(flags and env, _FILE secrets, the soft-restart carry, the build and S3
transport checks), taking runMain back under Tier 2's funlen limit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@randomizedcoder

Copy link
Copy Markdown
Owner Author
  • Addressed in 5328f1b: startup checks moved from runMain into startupConfig; comprehensive lint clean.

@randomizedcoder
randomizedcoder changed the base branch from sec/fp1-debug-writer-tags to main November 12, 2026 06:18
@randomizedcoder
randomizedcoder merged commit 8a26a87 into main Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant