Skip to content

fix(sanitize): stop redacting member paths and lowercase type annotations - #95

Merged
senamakel merged 3 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-7713-scrub-code-references
Oct 14, 2026
Merged

senamakel merged 3 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-7713-scrub-code-references

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

scrub_credentials is redacting ordinary source code again. Since a5f129d (#60), a bare identifier is spared only when it equals its key. So accessToken: string | null; came back as stri*[REDACTED], and state.accessToken = action.payload; as acti*[REDACTED]. An agent reading its own TypeScript auth code saw a redacted view and could not recover, because the notice tells it not to retry.

Two narrow exemptions:

  • A bare, digitless dotted path (action.payload, config.apiKey) counts as a code reference in looks_like_secret, but only under token/key/credential/bearer keys. Under *password/*secret keys a dotted word stays redacted.
  • A bare lowercase built-in type name after : (TS primitives, plus Python str/int/float/bool; see LOWERCASE_TYPE_NAMES) counts as an annotation, next to the existing uppercase String exemption.

Related issue

Part of tinyhumansai/openhuman#7713. The gitlink bump tinyinference → tinyagents → openhuman follows after merge.

API or behavior changes

No API change. Fewer false-positive redactions:

  • Still redacted: quoted values, plain words (password=correcthorse, password: correcthorse) and dotted values containing digits.
  • Still redacted: password=correct.horse, secret: a.b and client_secret = battery.staple.
  • Deliberately unchanged: a quoted value under a *_KEY name (const USER_KEY = 'anime-shop-user'). It cannot be told apart from a short real key, and api_key="short" is pinned as redacted.

Validation

No local builds or tests, by repo-owner policy for this contributor; GitHub CI is the gate.

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings: CI
  • cargo build --all-targets --all-features: CI
  • cargo test --all-features: CI

Revert-check: the not-run expectations below follow from the pre-fix code path. Reverting the sanitize.rs hunks makes member_paths_and_lowercase_type_annotations_are_not_secrets fail: string and action.payload reach the !value.eq_ignore_ascii_case(key) arm. Dropping the password/secret guard makes values_that_only_resemble_code_references_stay_redacted fail on correct.horse and a.b.

Tests

Two table-driven tests in sanitize_tests.rs, next to the #6954 cases:

  • member_paths_and_lowercase_type_annotations_are_not_secrets: TS string, Python str (also under a password key), and dotted paths under token, key and credential keys.
  • values_that_only_resemble_code_references_stay_redacted: quoted "string", password: correcthorse, password=correct.horse, secret: a.b, and token=abc123.def456.

The existing alphabetic_password_assignment_is_redacted is unchanged.

Documentation

Not needed: the rule is documented in comments at both exemption sites.

Checklist

  • The change is focused on one logical change
  • No new #[allow(...)], #[ignore], or relaxed lints
  • No secrets, tokens, or .env contents in the diff or the description

…ions

The alphabetic-password fix (a5f129d) spared a bare identifier only when it
equalled its key, so ordinary source code was redacted again:
`accessToken: string | null` and `state.accessToken = action.payload`.

Treat a bare digitless dotted path as a code reference, and a bare lowercase
built-in type name after `:` as an annotation. Quoted values and plain words
such as `password=correcthorse` stay redacted.

Part of tinyhumansai/openhuman#7713
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f8679751-0643-4679-83a4-ee55bd0fae69
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

…keys

`password=correct.horse` is as likely a value as a member path, so the
member-path exemption now applies only to token, key, credential and bearer
keys, where code like `x.token = action.payload` is common.

Part of tinyhumansai/openhuman#7713
Fold the near-duplicate cases into one table per behaviour, drop the auth-slice
test whose lines are asserted on their own, and keep only the type names the
issue covers.

Part of tinyhumansai/openhuman#7713
@tinysweeper

tinysweeper Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Tiny Sweeper completed its review; deterministic results follow.

State: Ready for maintainer review
Priority: none
Reviewed head: 4fbb6c0dbdd2
Updated: 2026-10-13T21:51:16Z

Review snapshot

Change surface Files Review signal Count
Production 1 Active findings 0
Tests 1 Noted findings 0
Documentation 0 Resolved findings 0
Configuration 0 Pending checks/questions 0

Completeness: Complete
Test assessment: No supported feature-to-test mapping was available; this does not mean tests are absent or passed.

Features

  • Added — Lowercase built-in type names treated as annotations: Bare lowercase built-in type names after ':' (for example accessToken: string) are treated as type annotations and left unredacted, while quoted '"string"' remains redacted and the check sits inside the existing ':' branch so it cannot fire on '=' assignments. (crates/tinyinference-core/src/sanitize.rs#static NON_SECRET_NUMBER_REGEX: LazyLock<Regex> = LazyLock::new(|| {, crates/tinyinference-core/src/sanitize.rs#pub fn scrub_credentials(input: &str) -> String {)
  • Added — Bare dotted member paths treated as code references: Bare digitless dotted member paths (for example action.payload) under keys other than password/secret are treated as code references and left unredacted; the guard runs after the known-secret-prefix, placeholder, whitespace and number checks, and quoted or password/secret-keyed dotted values stay in the redaction path. (crates/tinyinference-core/src/sanitize.rs#fn looks_like_secret(value: &str, quoted: bool, rest: &str, key: &str) -> bool {)

Tests

No supported feature-to-test mapping was produced. Test execution is not inferred.

Findings

No active actionable findings.

Before merge

None.

How this fits together

flowchart LR
  n0["looks_like_secret<br/>changed"]:::changed
  n1["scrub_credentials<br/>changed"]:::changed
  n2["...nces_and_type_annotations_are_not_secrets<br/>changed"]:::changed
  n3["assert_unchanged"]:::impacted
  n4["sanitize_api_error"]:::impacted
  n5["scrub_secret_patterns"]:::impacted
  n6["fixture"]:::impacted
  n7["known_secret_prefixes_are_always_redacted"]:::impacted
  n8["..._a_literal_is_code_but_a_full_stop_is_not"]:::impacted
  n1 -->|calls| n0
  n2 -->|calls| n3
  n2 -->|tests| n3
  n4 -->|calls| n5
  n7 -->|calls| n1
  n7 -->|tests| n1
  n7 -->|calls| n6
  n7 -->|tests| n6
  n8 -->|calls| n1
  n8 -->|tests| n1
  n8 -->|calls| n3
  n8 -->|tests| n3
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The critique lane traced the new early-return and the widened type-annotation guard against the regex captures and existing callers, and reported it found no reachable input where credentials now pass through that were redacted before.
  • Lane summary: The change adds two heuristics to `scrub_credentials`: bare dotted member paths (`action.payload`) and bare lowercase built-in type names after `:` (`accessToken: string`) are treated as code and left unredacted, with tests covering both the pass-through and the cases that must still redact. I traced the new early-return in `looks_like_secret` and the widened type-annotation guard against the regex captures and the existing callers, and the guards (quoted check, lower-key exclusion for `password`/`secret`, digitless-identifier regex) hold for the inputs the tests name; I found no reachable input where credentials now pass through that were redacted before.

security

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The new checks are gated on quoted/!quoted exactly as the surrounding heuristics, the lowercase type-name check sits inside the existing ':' branch so it cannot fire on '=' assignments, and the new looks_like_secret short-circuit runs after the known-secret-prefix, placeholder, whitespace and number checks, so 'sk-', 'ghp_', 'xox?-', 'AKIA'/'ASIA', 'eyJ' and quoted values still redact.
  • Lane summary: The change narrows `scrub_credentials` in two ways: bare lowercase built-in type names after `:` are treated as annotations, and bare digitless dotted member paths under keys other than `password`/`secret` are treated as code references. Both are gated on `quoted`/`!quoted` exactly as the surrounding heuristics are, the new `LOWERCASE_TYPE_NAMES` check sits inside the existing `== ":"` branch so it cannot fire on `=` assignments, and the new `looks_like_secret` short-circuit runs after the known-secret-prefix, placeholder, whitespace and number checks, so `sk-`, `ghp_`, `xox?-`, `AKIA`/`ASIA`, `eyJ` and quoted values still redact — including `password=correct.horse` and `secret: a.b`, which the `lower_key` guards keep inside the redaction path. The accompanying tests cover both the newly-passing source snippets and the values that must stay redacted, and there is no untrusted-input path, network call, subprocess or permission change here. I found no defect.

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The change narrows credential redaction so bare dotted member paths (`action.payload`, `config.apiKey`) and bare lowercase built-in type names after `:` (`accessToken: string`) pass through, while quoted `"string"`, dotted values with digits and dotted words under password/secret keys stay redacted. The diff does touch crates/tinyinference-core/src/sanitize_tests.rs, so the claim in the "no test file changed" banner is wrong: both new behaviours and the guard clauses are exercised by `member_paths_and_lowercase_type_annotations_are_not_secrets` and `values_that_only_resemble_code_references_stay_redacted`, and the pass-through assertions use `assert_unchanged` (an exact-equality check), which can genuinely fail. I found no reachable input where the new pass-through leaks a value the old code redacted beyond the intended source-code case, and no repository-rule violation in the changed lines.

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Positive: The commits lane reported nothing sensitive found in what this pull request commits.
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The description lane found the description matches the diff accurately, naming both exemptions, the deliberate password/secret guard, the still-redacted cases, and the quoted-key-name exclusion, and reported no substantiable defect.
  • Lane summary: The change adds two narrow exemptions to `looks_like_secret` (bare digitless dotted member paths under non-password/secret keys, and bare lowercase built-in type names after `:`) plus two table-driven tests. The description matches the diff accurately: it names both exemptions, the deliberate password/secret guard, the still-redacted cases, and the quoted-key-name exclusion. I found no defect I can substantiate from the diff and the read code.
Evidence and run details
  • Models: ladder/vectors-oai3, deepseek-v4.1-flash
  • Spend: $0.002494
  • Tokens: 253603 input · 19719 output · 42240 cached · 238 embedding
Head State Pass summary
4fbb6c0dbdd2 incomplete 0 active finding(s), 0 resolved finding(s) (at 2026-10-13T20:24:52Z)
4fbb6c0dbdd2 ready for maintainer review 0 active finding(s), 0 resolved finding(s) (at 2026-10-13T21:51:16Z)

tinysweeper 0.1.2

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking, but could not review everything, so this is not an approval: crates/tinyinference-core/src/sanitize.rs, crates/tinyinference-core/src/sanitize_tests.rs.

             $0.0022 · 203,404 in / 32,311 out · 52,608 cached (26%) · ladder/vectors-oai3, deepseek-v4.1-flash · 238 embedded
critique:    $0.0008 · 43,367 in  / 12,747 out · 19,456 cached (45%) · deepseek-v4.1-flash
security:    $0.0011 · 89,661 in  / 17,076 out · 22,144 cached (25%) · deepseek-v4.1-flash
tests:       $0.0000 · 35,077 in  / 393 out    · 5,120 cached (15%)  · deepseek-v4.1-flash
description: $0.0001 · 32,273 in  / 874 out    · 5,888 cached (18%)  · deepseek-v4.1-flash

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking. Approving.

             $0.0025 · 253,603 in / 19,719 out · 42,240 cached (17%) · ladder/vectors-oai3, deepseek-v4.1-flash · 238 embedded
critique:    $0.0001 · 86,837 in  / 1,025 out  · 9,344 cached (11%)  · deepseek-v4.1-flash
security:    $0.0018 · 87,630 in  / 9,835 out  · 9,856 cached (11%)  · deepseek-v4.1-flash
tests:       $0.0005 · 58,418 in  / 7,149 out  · 16,256 cached (28%) · deepseek-v4.1-flash
description: $0.0000 · 17,388 in  / 376 out    · 6,784 cached (39%)  · deepseek-v4.1-flash

@senamakel
senamakel merged commit a668318 into tinyhumansai:main Oct 14, 2026
10 checks passed
senamakel pushed a commit to tinyhumansai/tinyagents that referenced this pull request Oct 14, 2026
Moves vendor/tinyinference from 8607cefd to 5c413dcf (tinyinference main),
which brings in tinyhumansai/tinyinference#95 (scrubber stops redacting
member paths and lowercase type annotations), #102 (streamed usage
extension fields kept on raw) and #90 (output-limit stops reported as
`length`). No crate manifest changed between the pins, so Cargo.lock is
unchanged.

Part of tinyhumansai/openhuman#7713
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants