Skip to content

fix(release): close pre-tag v0.9.11 truthfulness and tool-output gaps - #5559

Merged
Hmbown merged 1 commit into
mainfrom
codex/v0911-pretag-fixes-20260823
Aug 23, 2026
Merged

fix(release): close pre-tag v0.9.11 truthfulness and tool-output gaps#5559
Hmbown merged 1 commit into
mainfrom
codex/v0911-pretag-fixes-20260823

Conversation

@Hmbown

@Hmbown Hmbown commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Summary

Same-version follow-up to #5542, to land on main before the v0.9.11 tag (the tag is the release anchor; the version surface is unchanged).

  • Model-bound tool output redaction ([redacted] output from tools impairs editing #5546, @ronohara): read/shell results reaching the model now use a credential-shaped policy (redact_model_bound_secrets): only values that look like secrets (known prefixes, JWTs, bearer tokens, PEM private-key blocks, long opaque strings) are masked; password: credentials?.password, "password-validator": "^5.3.0", token = make_token() and short JSON literals stay byte-exact so exact-match edits and read-back work. Exact configured credential values are still always replaced; logs/previews/exports keep the broad key-based redact_secrets unchanged. Tests: model_bound_redaction_keeps_code_and_config_byte_exact, model_bound_redaction_masks_credential_shaped_values, private_key_blocks_are_masked_between_pem_markers, key_based_policy_is_unchanged_by_the_model_bound_mode, model_bound_tool_results_keep_ordinary_code_byte_exact (end-to-end through prepare_model_bound_request).
  • Sub-agent permission receipts are truthful: Scout/Reviewer/Planner snapshots report the read-only shell they actually run under; one role_requires_read_only_shell predicate is shared by the spawn path and every snapshot producer. Test: read_only_roles_report_the_narrowed_shell_they_actually_run_under.
  • JSON portable bundles reject duplicate object keys at any depth before parse (TOML already did; cross-section duplicates were already rejected). Test: json_bundles_with_duplicate_keys_fail_before_parse.
  • Docs/CHANGELOG truth: four shipped 0.9.11 changes were missing from the CHANGELOG (login = account sign-in, automatic 0600 file-store session fallback, Ctrl+Shift+U /update chord + startup version hint, Fleet copy pass); docs/CONFIGURATION.md, the account-session doc comment, and docs/TELEMETRY.md now match shipped behaviour.

Found by the fresh issue report and the v0.9.11 ops-potential audit (34-agent verification of 188 commitments against the merged tree).

Validation (local, final tree)

cargo fmt --check, git diff --check, changelog sync, cargo check --workspace --all-targets --locked, cargo clippy --workspace --all-targets --all-features --locked -D warnings, cargo test --workspace --all-features --locked, 21-crate publish dry-run — results recorded in the PR comment on the final head.

No benchmark-lane change. Signed-off.

Closes #5546

- Model-bound tool results use a credential-shaped redaction policy
  (`redact_model_bound_secrets`): only values that look like secrets are
  masked before a read/shell result reaches the model, so code such as
  `password: credentials?.password` or `"password-validator": "^5.3.0"`
  stays byte-exact for exact-match edits and read-back; exact configured
  credential values are still always replaced and logs/previews/exports keep
  the broad key-based scrubber. PEM private-key blocks are masked between
  their markers in both policies. (#5546)
- Sub-agent permission receipts derive from the effective runtime profile:
  Scout/Reviewer/Planner report the read-only shell they actually run under
  instead of the requested profile; the spawn path and every snapshot
  producer share one `role_requires_read_only_shell` predicate.
- JSON portable config bundles fail before parse on a duplicate object key
  at any depth, matching the TOML behaviour and the cross-section check.
- CHANGELOG gains the shipped `login` sign-in semantics, the automatic 0600
  file-store session fallback, the Ctrl+Shift+U /update chord and startup
  version hint, and the Fleet copy pass; CONFIGURATION.md, the account
  session doc comment, and TELEMETRY.md match the shipped behaviour.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
@gitguardian

gitguardian Bot commented Aug 23, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
36514411 Triggered RSA Private Key 2776c21 crates/config/src/persistence.rs View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 6m 31s —— View job


Review: pre-tag v0.9.11 truthfulness / tool-output redaction fixes

Todo list

  • Gather context (read diff vs origin/main, changed files, CLAUDE.md/AGENTS.md)
  • Correctness review of the new RedactionPolicy::CredentialShaped state machine
  • Provider/model/route safety check (n/a — no provider/model selection code touched)
  • Reuse/simplification review (fleet role-narrowing predicate consolidation, JSON duplicate-key check)
  • Test coverage review
  • Security review of the redaction logic
  • Post final review

Summary

This is a well-scoped, well-tested follow-up. The two structural fixes are solid:

  • Fleet permission-receipt truthfulness (crates/tui/src/fleet/worker_runtime.rs, crates/tui/src/tools/subagent/mod.rs): the new role_requires_read_only_shell / effective_runtime_profile_for_role pair is a genuine simplification — it replaces two independently-maintained Scout | Reviewer | Planner match arms (spawn path + snapshot producer) with one shared predicate, and the snapshot producer now derives its reported shell from the same narrowing spawn actually applies instead of reporting the raw requested profile. Good catch, good fix, well tested (read_only_roles_report_the_narrowed_shell_they_actually_run_under).
  • JSON duplicate-key rejection (crates/cli/src/config_bundles.rs): the DeserializeSeed/Visitor walk that rejects duplicate keys at any depth without materializing values is a clean, single-pass implementation, and it also folds two near-duplicate JSON-parsing branches into one. Nested-array and sibling-key-under-different-parent cases are both tested.
  • Docs/CHANGELOG changes (docs/CONFIGURATION.md, crates/secrets/src/account.rs doc comment, docs/TELEMETRY.md) are comment/prose-only and match the code they describe — verified secure_account_session_secrets() already unconditionally falls back to the 0600 file store via Secrets::system_keyring() (crates/secrets/src/lib.rs), so the doc fix is accurate, not a behavior change.

Finding: URL-shaped credential values bypass the new model-bound redaction

crates/config/src/persistence.rs:732-745:

fn is_reference_like(value: &str) -> bool {
    value.contains("?.")
        || value.contains('(')
        || value.contains("${")
        || value.contains("process.env")
        || value.contains("os.environ")
        || value.contains("getenv")
        || value.contains("://")
        || value.chars().all(|c| c.is_ascii_alphabetic() || c == '_' || c == '.')
}

value_looks_like_credential() calls this and returns false (i.e. "don't redact") for any value containing "://", with no check for embedded userinfo credentials. That's fine for endpoint-shaped values like auth_url = https://example.test/oauth/token (covered by model_bound_redaction_keeps_code_and_config_byte_exact), but it also exempts values like:

secret: "https://hooks.slack.com/services/T000/B000/XXXXXXXXXXXXXXXXXXXXXXXX"
password: "postgres://admin:Sup3rSecretPass123@db.internal:5432/app"

Both have an explicitly sensitive key (secret, password), so under the old RedactionPolicy::KeyBased (still used for logs/previews/exports) they'd be masked unconditionally. But crates/tui/src/client.rs:641 now routes all read/shell tool output reaching the model through redact_model_bound_secrets (RedactionPolicy::CredentialShaped), and for these two lines value_looks_like_credential returns false purely because of the :// substring — so the webhook URL / DB connection string with an embedded password reaches the model unredacted, a regression versus pre-PR behavior (which used the same redact_secrets for both logging and model-bound output). I traced this by hand against the existing test suite's mechanics (matches the Bearer/curl-quoted test cases exactly), but couldn't execute cargo test in this run to confirm empirically — worth double-checking directly.

Suggest narrowing the exemption to require the URL have no user:pass@-style userinfo segment before treating it as a non-credential reference, and adding a regression test alongside model_bound_redaction_masks_credential_shaped_values.

Fix this →

Other notes

  • Provider/model/route safety: no code in this diff infers provider/model selection from a prefix or prompt text — not applicable here.
  • No other panics, unwraps-on-fallible-paths, or non-exhaustive matches spotted in the diff.
  • I was not able to run cargo fmt/clippy/test in this session (no permitted execution path for cargo), so I relied on manual tracing against the diff and the existing test expectations rather than fresh test runs. The PR body's own validation log (fmt/clippy/test/dry-run) should be treated as the authoritative build signal; the finding above is a logic gap I could not exercise directly, so it's worth a targeted test run before merge.

@Hmbown
Hmbown merged commit b982714 into main Aug 23, 2026
28 of 30 checks passed
@Hmbown
Hmbown deleted the codex/v0911-pretag-fixes-20260823 branch August 23, 2026 07:02
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.

[redacted] output from tools impairs editing

1 participant