Skip to content

fix: close the findings of the final pre-release review - #22

Merged
Vonng merged 7 commits into
mainfrom
fix/pre-release-review-0831
Aug 31, 2026
Merged

fix: close the findings of the final pre-release review#22
Vonng merged 7 commits into
mainfrom
fix/pre-release-review-0831

Conversation

@Vonng

@Vonng Vonng commented Aug 31, 2026

Copy link
Copy Markdown
Member

Six independent adversarial reviewers went over everything between RELEASE.2026-08-06T00-00-00Z and bae97f94 (credential redaction, checksum verify, behavior changes, release chain and CI, the module-path sweep, and a black-box differential run against the 0806 binary on a live SILO server). No blocker was found; this PR closes every code finding they did report.

Credential redaction

  • Default admin trace printed the raw query string, error, message and annotations of every traced request — a presigned URL's signature, an STS session token, a proxy token= of any client the server traced — in both the text and the JSON rendering. Only the verbose path went through redactTraceText. Both renderings now work on redacted copies of those fields; the shared event is never mutated.
  • The verbose path passed the raw query without its leading ?, so the query shape (anchored on [?&]) missed a credential in the first parameter. redactTraceQuery puts the anchor back.
  • Three free-text shapes matched ordinary prose and were applied to every error message: AWS S3 compatibleAWS **REDACTED** compatible, token has expiredtoken **REDACTED** expired, Basic auth is disabledBasic **REDACTED** is disabled, bufio.Scanner: token too longtoken **REDACTED** long. The SigV4 shape now requires its Credential= field, the SigV2 shape the key:signature colon, and the scheme shape a payload that looks like a token rather than the next word of a sentence. Every echoed-credential case the shapes covered is pinned by tests.
  • The registry no longer records placeholder values (auth_token=off, client_secret=true) that turned every later off/true into a marker; admin config set now registers and masks credentials embedded in values whose key names none (a DSN password=, a URL's userinfo, a webhook ?token=); an Authorization payload after a doubled space is registered trimmed.
  • checksum verify scrubs transport read/close errors before writing them into a record, like server errors.

Behavior

  • admin user svcacct set --policy refused an empty document, and an empty document is the only way to clear an inline policy and return the account to its inherited one (the server treats {"Statement":[]} as a reset). The shape is still validated strictly; emptiness is allowed on set.
  • A malformed --custom-header, --resolve or --limit-* value was printed twice, the first copy on stdout (the CLI library echoes a Before error to its writer). It is now reported once, on stderr, or as a JSON error document under --json, at both the app and the command level.

Tests and CI

  • The functional test asserting that explicit --quiet silences checksum verify could not fail (the harness swallows stdout); it now captures the command's own stdout.
  • The Windows CI step runs under bash so a failed go build fails the step (pwsh only propagated the last command's exit code and left %GOPATH% unexpanded).
  • A comment in check-release-commit.sh no longer claims exclude_pull_requests filters runs; the event/head_branch filter does.

Verified on the branch: go test ./..., go test -race on the redaction set, make verifiers (vet, golangci-lint, brand, credits, all five release fixture suites), actionlint, shellcheck (no new warnings), and real-binary probes of both flag levels and --json.

Follow-ups from the review of this branch

  • checksum verify no longer labels an SSE-C refusal as UNKNOWN_SSEC_KEY_MISSING when a key was supplied (SSE-C over plain HTTP): with a key the server's complaint is about the request, so it is a read error carrying the message. --max-size rejects a bad value with the value and the expected form, and its help says 0 means no limit.
  • The strict policy parser answered an empty document with "EOF"; write paths say "policy input cannot be empty" again.
  • A percent-encoded URL password in an admin config set value (url=amqp://user:p%40ss@host) is registered and masked as written, not only decoded; quoted DSN payloads are recognized; password=password (the documentation's placeholder) is not registered.
  • max-keys, key-marker, continuation-token stay visible in trace output and --debug URLs; the query shape's key/token fragments had blanked them.
  • The SigV2 shape requires a base64 signature after the colon and scheme words match in header spelling, so "AWS https://s3.amazonaws.com" and "digest SHA256:..." remain prose.
  • docs: an endpoint must report x-amz-checksum-type; otherwise every checksummed object is UNKNOWN_CHECKSUM_TYPE.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW

Vonng and others added 7 commits August 31, 2026 19:25
… prose

The non-verbose admin trace rendering printed the raw query string, error,
message and annotations of every traced request unredacted, in both the
text and the JSON form: a presigned URL's signature, an STS session token
or a proxy token= parameter of any client the server traced reached the
operator's terminal. Only the verbose path went through redactTraceText.
Both renderings now work on redacted copies of those fields.

The verbose path passed the raw query without its leading "?", so the
query shape - anchored on the [?&] before a parameter name - missed a
credential in the first parameter. redactTraceQuery puts the anchor back.

Three free-text shapes matched ordinary prose and were applied to every
error message: "AWS S3 compatible" became "AWS **REDACTED** compatible",
"token has expired" became "token **REDACTED** expired", "Basic auth is
disabled" became "Basic **REDACTED** is disabled". The SigV4 shape now
requires its Credential field, the SigV2 shape the access-key:signature
colon, and the scheme shape a payload that looks like a token rather than
the next word of a sentence.

The registry no longer records placeholder values such as auth_token=off
or client_secret=true, which turned every later "off" and "true" into a
marker, and admin config set now registers and masks credentials embedded
in values whose key names none: a DSN password, a URL's userinfo, a
webhook ?token=. An Authorization payload after a doubled space is
registered trimmed.

Found by the pre-release adversarial review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
admin user svcacct set --policy refused an empty document, and an empty
document is the only way to clear a service account's inline policy and
return it to the inherited one: the server treats {"Statement":[]} as a
reset. The shape is still validated strictly; emptiness is allowed on set.

A malformed --custom-header, --resolve or --limit-* value was printed
twice, and the first copy went to stdout: the CLI library echoes a Before
error to its writer before the process reports it. The parse failure is
now reported through fatalIf - once, on stderr, or as a JSON error document
under --json - at both the app and the command level.

checksum verify scrubbed the server's error text but not a transport
read or close error before writing it into a record; both go through the
scrubber now. The functional test that claimed explicit --quiet silences
checksum verify could not fail, because the harness swallows stdout; it
now captures the command's own stdout. The Windows CI step runs under
bash so a failed go build fails the step, and a comment in the release
gate no longer claims exclude_pull_requests filters runs.

Found by the pre-release adversarial review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
…y and size messages clear

checksum verify labelled the server's refusal of SSE-C over plain HTTP as
UNKNOWN_SSEC_KEY_MISSING although a key had been supplied; with a key the
complaint is about the request, so it is a read error carrying the server's
message. --max-size rejects a bad value with the value and the expected
form instead of strconv's text, and its help says that 0 means no limit.

The strict policy parser answers an empty document with "EOF"; the write
paths say "policy input cannot be empty" again, as the permissive parser
did. docs record that an endpoint must report x-amz-checksum-type, and the
prose test pins the server's "security token included in the request"
message, which the old shapes mangled.

Found by the pre-release adversarial review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
…ble in traces

A password with an "@" or ":" travels percent-encoded in a URL, so an
admin config set value such as url=amqp://user:p%40ss@host registered only
the decoded form and a failed command still echoed the encoded one. The
raw userinfo password is registered and masked as well; a quoted DSN
payload (password='p@ss word') is recognized; a placeholder equal to its
own key (password=password, the documentation's example) is not a secret.

max-keys, key-marker and continuation-token carry the fragments the query
shape keys on, and hiding them blanked every ListObjects line of the
default trace. Those names are never secrets and stay visible in trace
output and in --debug URLs alike.

The SigV2 shape now needs a base64 signature after the colon, so "AWS
https://s3.amazonaws.com" and "AWS us-east-1:GetObject" stay readable,
and scheme words match in the spelling a header uses, so "digest
SHA256:..." is prose. The dead error check after setGlobalsFromContext
in registerBefore is gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
The unit table exercised applyChecksumVerifyError directly; this case runs
verifyChecksumCandidate with and without a matching --enc-c prefix against
a backend that refuses SSE-C, so the sseSupplied wiring itself is covered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
…insensitively

libpq allows ";", "," and "&" in an unquoted connection-string value, so
the DSN rule now runs to the next whitespace; the URL-query rule still
stops at "&". Scheme names are case-insensitive on the wire and a proxy
may echo "bearer <jwt>", so Bearer, Basic, Negotiate and NTLM match in
any spelling again; Digest and Token, which are also English words, match
only as a header spells them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
…DSN payload too

An ODBC-style connection string has no whitespace, so the DSN rule
captures the whole tail after Password=; a later echo carries only the
password, so the part before the first ";" or "," is registered as well.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VX7dtHJ4q7GJ1YDYeXLmjW
Signed-off-by: Feng Ruohang <rh@vonng.com>
@Vonng
Vonng merged commit 5a800c0 into main Aug 31, 2026
8 checks passed
@Vonng
Vonng deleted the fix/pre-release-review-0831 branch August 31, 2026 12:03
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