Skip to content

fix(runtime-node): stop redaction masking GenAI/usage token counts - #17

Merged
sagnik11 merged 4 commits into
Autter-dev:mainfrom
rajeshaipython-stack:fix/redact-token-usage-overmatch
Aug 29, 2026
Merged

fix(runtime-node): stop redaction masking GenAI/usage token counts#17
sagnik11 merged 4 commits into
Autter-dev:mainfrom
rajeshaipython-stack:fix/redact-token-usage-overmatch

Conversation

@rajeshaipython-stack

@rajeshaipython-stack rajeshaipython-stack commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Problem

The server-side attribute redactor masks any key matching the sensitive-key patterns. /token/ is an unanchored substring, so besides real secrets it also masks non-secret usage attributes:

  • gen_ai.usage.input_tokens, gen_ai.usage.output_tokens (OpenTelemetry GenAI semconv)
  • prompt_tokens, completion_tokens, total_tokens, token_count, max_tokens

For an SDK that ships llmTracing, silently turning token counts into [redacted] loses exactly the usage data teams want to see.

It's also inconsistent with this file's own convention — the comment above the list notes patterns are "anchored where a loose substring would over-redact (card must not eat discard, author must not eat author_id)" — but /token/ was left loose.

Fix

Anchor the pattern to /token$/. It still masks secret token keys (token, access_token, refresh_token, authToken, …) while leaving usage counts (*_tokens, token_count, max_tokens) intact. Value-level scrubbing (JWT / bearer / provider-key patterns) still redacts token-shaped values, so defense-in-depth is unchanged.

Tests

Added two cases to redact.test.mjs: one asserting usage token-counts pass through untouched, one asserting secret *token keys are still masked. node --test → all green.

Scope

One-line behaviour change + tests. No API or wire-format change.


View code changes stack in Autter

Summary

Summary generated by Autter.
Fixes server-side attribute redaction in @autter/runtime-node so canonical GenAI and LLM usage token-count attributes remain available when their values are numeric, while sensitive token-like fields and non-numeric values continue to be masked.

Changes

  • Refines redactValue and sensitive-key handling in packages/runtime-node/src/redact.ts to preserve approved numeric usage-count attributes without weakening redaction for secrets.
  • Adds regression coverage for GenAI usage keys, numeric-only preservation, and masking of unrelated or string-valued sensitive token fields.
  • No wire-format, exported API, or storage schema changes; existing redactAttributes behavior remains unchanged for other sensitive data.

Acceptance Criteria

  • Numeric canonical GenAI usage counts are returned unchanged by redactAttributes.
  • String-valued or sensitive-key token fields remain masked.
  • Existing email, credential, nested-object, array, and custom-pattern redaction behavior continues to pass.
  • The runtime-node package builds successfully.

Test Plan

  • Run the runtime-node redaction test suite and verify the new GenAI usage-count assertions pass.
  • Run npm run build from the repository root.
  • Inspect redacted output for numeric GenAI token counts, string token values, and unrelated keys such as discard_count and author_id.

Rollback Plan

Revert commit 29a86db7bb2abdfb5f925d660a01ac8fe89d8014 and redeploy @autter/runtime-node; this restores the previous redaction implementation without requiring data or schema rollback.

Related Issues

No linked issue was identified.

Written for commit 29a86db. Summary will update on new commits.

The /token/ sensitive-key pattern is an unanchored substring, so it also masks non-secret usage attributes like gen_ai.usage.*_tokens, prompt_tokens, total_tokens, token_count and max_tokens -- unhelpful for an SDK with llmTracing. Anchoring to /token$/ keeps masking secret token keys (token, access_token, authToken) while leaving usage counts intact, matching the existing anti-over-redaction anchoring for card/author. Value-level token scrubbing still catches token-shaped values. Adds tests.

@autter-dev autter-dev 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.

🔴 Autter review in progress — running security, correctness & dependency checks on this PR. Follow live step-by-step progress on the autter/review-gate check in the merge box. Merge is blocked until the gate completes; Autter approves automatically when the review comes back clean, and releases this hold with a neutral review when it finds non-blocking issues.

@autter-dev autter-dev 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.

Autter posted 1 finding(s) as review threads below (🟠 1). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Sensitive token-containing attribute keys can bypass redaction — Risk: 65/100

Changing the key pattern from /token/ to /token$/ prevents redaction of sensitive keys that contain token without ending in it, such as session_token_id or token_payload. Preserve GenAI usage-count keys through a narrower allowlist or targeted exception while continuing to redact secret-bearing token keys.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: RedactOptions, redactAttributes, makeRedactor, AttrValue, CompiledRedactor, toCaseInsensitive
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Keep broad token redaction for arbitrary secret keys, and explicitly exempt only the approved GenAI/usage count attributes (for example, `input_tokens`, `output_tokens`, `prompt_tokens`, `completion_tokens`, `total_tokens`, `token_count`, and `max_tokens`) using a clear allowlist or key-specific predicate. Add regression tests for token keys with suffixes such as `token_value` and `session_token_id`. Blast radius — if this AI-generated slop ships it cascades to the downstream usage that depends on this file: functions `RedactOptions`, `redactAttributes`, `makeRedactor`, `AttrValue`, `CompiledRedactor`, `toCaseInsensitive`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

@autter-dev autter-dev 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.

Autter posted 1 finding(s) as review threads below (🟠 1). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Sensitive attributes containing token can bypass redaction — Risk: 75/100

Changing /token/ to /token$/ preserves usage fields such as prompt_tokens and token_count, but also allows keys like token_value and token_string to pass through unmasked. Arbitrary secrets under those keys can therefore be exported in telemetry. Use a narrower allowlist for usage-count keys or retain masking for credential-shaped token keys.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: RedactOptions, redactAttributes, makeRedactor, AttrValue, CompiledRedactor, toCaseInsensitive
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve broad token-secret coverage while exempting only the explicitly supported GenAI usage-count keys. Restore matching for token-containing credential names, or add a narrowly defined allow-list for numeric usage attributes such as `gen_ai.usage.input_tokens`, `prompt_tokens`, and `total_tokens`, then add regression tests for `token_value`, `token_string`, `bearerTokenValue`, and other token-bearing secret variants. Blast radius — if this is exploited it cascades to the downstream usage that depends on this file: functions `RedactOptions`, `redactAttributes`, `makeRedactor`, `AttrValue`, `CompiledRedactor`, `toCaseInsensitive`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown

🚦 Pre-merge checks · ⚠️ 2 warning, ✅ 167 passed

Needs attention

Check Status Explanation
Missing linked tracker issue ⚠️ Warning 2 potential issue(s) detected (max risk 50/100): packages/runtime-node/test/redact.test.mjs:127, packages/runtime-node/src/redact.ts:152.
Missing CODEOWNERS reviewer approval ⚠️ Warning 2 potential issue(s) detected (max risk 50/100): packages/runtime-node/src/redact.ts:145, packages/runtime-node/test/redact.test.mjs:128.
✅ Passed checks (167)
Check Status Explanation
Too many files changed ✅ Passed Changed 2 file(s), within the limit of 50.
Too many lines changed ✅ Passed Changed 90 line(s), within the limit of 1000.
Too many unrelated chapters ✅ Passed 1 chapter(s) detected, within the limit of 6.
Generated files hiding real changes ✅ Passed Generated-file volume (0 lines) does not obscure the 90 hand-written line(s).
Missing PR context ✅ Passed PR context looks sufficient.
Mixed concerns (refactor + behavior change) ✅ Passed The PR contains a focused redaction behavior change with regression tests, not a refactor combined with behavior work.
Migration + app logic + UI combined in one PR ✅ Passed The PR contains no database migrations and no user-interface changes.
Sensitive data in logs ✅ Passed No sensitive data in logs issues detected.
Log injection ✅ Passed No log injection issues detected.
Missing audit logging ✅ Passed No missing audit logging issues detected.
Removed observability ✅ Passed No removed observability issues detected.
Silent exception swallowing ✅ Passed No silent exception swallowing issues detected.
Unhandled promise rejection ✅ Passed No unhandled promise rejection issues detected.
Circuit breaker not detected ✅ Passed No circuit breaker not detected issues detected.
Stack trace leakage ✅ Passed No stack trace leakage issues detected.
Multi-write without detected transaction ✅ Passed No multi-write without detected transaction issues detected.
Possible TOCTOU in critical path ✅ Passed No possible toctou in critical path issues detected.
Idempotency key not detected ✅ Passed No idempotency key not detected issues detected.
Possible non-atomic read-modify-write ✅ Passed No possible non-atomic read-modify-write issues detected.
Optimistic locking not detected ✅ Passed No optimistic locking not detected issues detected.
Rate limiting not detected ✅ Passed No rate limiting not detected issues detected.
Rate limiting removed ✅ Passed No rate limiting removed issues detected.
Batch size limit not detected ✅ Passed No batch size limit not detected issues detected.
Pagination not detected ✅ Passed No pagination not detected issues detected.
Publicly exposed storage ✅ Passed No publicly exposed storage issues detected.
Over-permissive IAM policy ✅ Passed No over-permissive iam policy issues detected.
Security group open to the internet ✅ Passed No security group open to the internet issues detected.
Unencrypted storage at rest ✅ Passed No unencrypted storage at rest issues detected.
Infrastructure missing access logging ✅ Passed No infrastructure missing access logging issues detected.
Hardcoded secret in IaC ✅ Passed No hardcoded secret in iac issues detected.
Infrastructure misconfiguration ✅ Passed No infrastructure misconfiguration issues detected.
Deprecated Kubernetes API version ✅ Passed No deprecated kubernetes api version issues detected.
Compound IaC attack chain ✅ Passed No compound iac attack chain issues detected.
Prompt injection risk ✅ Passed No LLM/AI-integration code touched by this diff.
LLM output used in a dangerous sink ✅ Passed No LLM/AI-integration code touched by this diff.
Sensitive data in prompt or system-prompt leakage ✅ Passed No LLM/AI-integration code touched by this diff.
Over-privileged LLM tool / excessive agency ✅ Passed No LLM/AI-integration code touched by this diff.
Missing validation on an LLM-driven decision ✅ Passed No LLM/AI-integration code touched by this diff.
Unbounded LLM usage (denial-of-wallet) ✅ Passed No LLM/AI-integration code touched by this diff.
Table exposed without row-level security ✅ Passed No row-level-security-related code touched by this diff.
Over-broad row-level security policy ✅ Passed No row-level-security-related code touched by this diff.
Code path that bypasses row-level security ✅ Passed No row-level-security-related code touched by this diff.
Privileged database credential reachable from the client ✅ Passed No row-level-security-related code touched by this diff.
Privileged query without row-level scoping ✅ Passed No row-level-security-related code touched by this diff.
Template-default gradient styling ✅ Passed No added frontend pages or design-slop markers in this diff.
Interchangeable AI marketing copy ✅ Passed No added frontend pages or design-slop markers in this diff.
Placeholder content shipped to users ✅ Passed No added frontend pages or design-slop markers in this diff.
Emoji standing in for an icon system ✅ Passed No added frontend pages or design-slop markers in this diff.
Call-to-action that goes nowhere ✅ Passed No added frontend pages or design-slop markers in this diff.
Templated page composition ✅ Passed No added frontend pages or design-slop markers in this diff.
Merge-blocking marker left in the change ✅ Passed No pending-work markers added by this diff.
Known-defect marker shipped in code ✅ Passed No pending-work markers added by this diff.
Untracked TODO without an issue reference ✅ Passed No pending-work markers added by this diff.
Test disabled or left pending ✅ Passed No pending-work markers added by this diff.
PII in logs ✅ Passed No pii in logs issues detected.
PII or internals leaked in error response ✅ Passed No pii or internals leaked in error response issues detected.
PII stored without application-level encryption ✅ Passed No pii stored without application-level encryption issues detected.
User data stored without retention controls ✅ Passed No user data stored without retention controls issues detected.
PII sent to external / cross-border destination ✅ Passed No pii sent to external / cross-border destination issues detected.
Lockfile resolution / integrity tampered ✅ Passed No lockfile resolution / integrity tampered issues detected.
Dependency runs install-time lifecycle script ✅ Passed No dependency runs install-time lifecycle script issues detected.
Possible dependency-confusion attack ✅ Passed No possible dependency-confusion attack issues detected.
Lockfile resolves a dependency the manifest does not declare ✅ Passed No lockfile resolves a dependency the manifest does not declare issues detected.
Checked-in build artefact modified without source change ✅ Passed No checked-in build artefact modified without source change issues detected.
Dockerfile build-step is insecure ✅ Passed No dockerfile build-step is insecure issues detected.
External artefact pulled in without integrity pinning ✅ Passed No external artefact pulled in without integrity pinning issues detected.
Changed export, importer not updated ✅ Passed No changed export with an un-updated importer detected.
Missing security-team review on sensitive path ✅ Passed No missing security-team review on sensitive path issues detected.
Source changes without matching tests ✅ Passed No source changes without matching tests issues detected.
Migration missing rollback / down step ✅ Passed No migration missing rollback / down step issues detected.
Frontend importing database client directly ✅ Passed No frontend importing database client directly issues detected.
Route handler bypassing service layer ✅ Passed No route handler bypassing service layer issues detected.
Backend service importing UI module ✅ Passed No backend service importing ui module issues detected.
Cross-context internals import ✅ Passed No cross-context internals import issues detected.
Workspace package rule violation ✅ Passed No workspace package rule violation issues detected.
Inconsistent logging pattern ✅ Passed No inconsistent logging pattern issues detected.
Inconsistent error handling ✅ Passed No inconsistent error handling issues detected.
Endpoint missing input validation ✅ Passed No endpoint missing input validation issues detected.
Multi-write without transaction wrapper ✅ Passed No multi-write without transaction wrapper issues detected.
New feature shipped without feature flag ✅ Passed No new feature shipped without feature flag issues detected.
Module placed in the wrong workspace package ✅ Passed No module placed in the wrong workspace package issues detected.
Direct env-var access bypasses config module ✅ Passed No direct env-var access bypasses config module issues detected.
Hallucinated import (package not installed) ✅ Passed No hallucinated import (package not installed) issues detected.
Nonexistent package (not found in registry) ✅ Passed No nonexistent package (not found in registry) issues detected.
Call to function that does not exist ✅ Passed No call to function that does not exist issues detected.
Generic placeholder identifier in production logic ✅ Passed No generic placeholder identifier in production logic issues detected.
Repetitive boilerplate (duplicated block) ✅ Passed No repetitive boilerplate (duplicated block) issues detected.
Overbroad try/catch swallowing all exceptions ✅ Passed No overbroad try/catch swallowing all exceptions issues detected.
TODO / FIXME on critical path ✅ Passed No todo / fixme on critical path issues detected.
Comment contradicts or fabricates code behaviour ✅ Passed No comment contradicts or fabricates code behaviour issues detected.
Abstraction defined but never used ✅ Passed No abstraction defined but never used issues detected.
Code style differs from rest of codebase ✅ Passed No code style differs from rest of codebase issues detected.
Established pattern ignored ✅ Passed No established pattern ignored issues detected.
Unhandled edge case (null / empty / zero / boundary) ✅ Passed No unhandled edge case (null / empty / zero / boundary) issues detected.
Doc-copy code with insecure defaults ✅ Passed No doc-copy code with insecure defaults issues detected.
Dead code (defined but never referenced) ✅ Passed No dead code (defined but never referenced) issues detected.
Deprecated API call ✅ Passed No deprecated api call issues detected.
API pattern from wrong library version ✅ Passed No api pattern from wrong library version issues detected.
API endpoint removed ✅ Passed No api endpoint removed issues detected.
HTTP method changed (GET ↔ POST etc.) ✅ Passed No http method changed (get ↔ post etc.) issues detected.
New required field added to request ✅ Passed No new required field added to request issues detected.
Field removed from response schema ✅ Passed No field removed from response schema issues detected.
Response field type changed ✅ Passed No response field type changed issues detected.
HTTP status code changed ✅ Passed No http status code changed issues detected.
Auth requirement added / removed / changed ✅ Passed No auth requirement added / removed / changed issues detected.
Error response shape changed ✅ Passed No error response shape changed issues detected.
Pagination behaviour changed ✅ Passed No pagination behaviour changed issues detected.
Outbound webhook payload schema changed ✅ Passed No outbound webhook payload schema changed issues detected.
GraphQL field removed without deprecation ✅ Passed No graphql field removed without deprecation issues detected.
GraphQL enum value removed ✅ Passed No graphql enum value removed issues detected.
SQL injection ✅ Passed No sql injection issues detected.
Cross-site scripting (XSS) ✅ Passed No cross-site scripting (xss) issues detected.
Path traversal ✅ Passed No path traversal issues detected.
Command injection ✅ Passed No command injection issues detected.
Insecure deserialization ✅ Passed No insecure deserialization issues detected.
Weak cryptography ✅ Passed No weak cryptography issues detected.
Hardcoded secret ✅ Passed No hardcoded secret issues detected.
Insecure randomness for security material ✅ Passed No insecure randomness for security material issues detected.
Unsafe file upload ✅ Passed No unsafe file upload issues detected.
Missing input validation ✅ Passed No missing input validation issues detected.
Unsafe CORS configuration ✅ Passed No unsafe cors configuration issues detected.
Unsafe / open redirect ✅ Passed No unsafe / open redirect issues detected.
Missing CSRF protection ✅ Passed No missing csrf protection issues detected.
Unsafe cookie / session settings ✅ Passed No unsafe cookie / session settings issues detected.
Sensitive data exposure ✅ Passed No sensitive data exposure issues detected.
API key in source ✅ Passed No api key in source detected.
Access token in source ✅ Passed No access token in source detected.
Private key in source ✅ Passed No private key in source detected.
Database connection URL with embedded credentials ✅ Passed No database connection url with embedded credentials detected.
Cloud credential in source ✅ Passed No cloud credential in source detected.
Webhook signing secret in source ✅ Passed No webhook signing secret in source detected.
OAuth client secret in source ✅ Passed No oauth client secret in source detected.
JWT signing secret in source ✅ Passed No jwt signing secret in source detected.
Hardcoded password ✅ Passed No hardcoded password detected.
Auth middleware removed from route ✅ Passed No auth middleware removed from route issues detected.
Route protection changed (protected → public) ✅ Passed No route protection changed (protected → public) issues detected.
Permission / RBAC check removed ✅ Passed No permission / rbac check removed issues detected.
Required role weakened ✅ Passed No required role weakened issues detected.
Admin-only route exposed to lower privilege ✅ Passed No admin-only route exposed to lower privilege issues detected.
Token validation skipped in middleware chain ✅ Passed No token validation skipped in middleware chain issues detected.
JWT verification weakened or changed ✅ Passed No jwt verification weakened or changed issues detected.
Session expiration / TTL changed ✅ Passed No session expiration / ttl changed issues detected.
Password reset flow changed ✅ Passed No password reset flow changed issues detected.
OAuth callback / redirect handling changed ✅ Passed No oauth callback / redirect handling changed issues detected.
Webhook endpoint missing signature verification ✅ Passed No webhook endpoint missing signature verification issues detected.
Public route touches private/PII data ✅ Passed No public route touches private/pii data issues detected.
Frontend performance issue ✅ Passed No additional explanation was reported.
Frontend security issue ✅ Passed No additional explanation was reported.
Frontend correctness issue ✅ Passed No additional explanation was reported.
Accessibility issue ✅ Passed No additional explanation was reported.
Frontend maintainability issue ✅ Passed No additional explanation was reported.
Code correctness issue ✅ Passed No additional explanation was reported.
Runtime error risk ✅ Passed No additional explanation was reported.
Resource leak risk ✅ Passed No additional explanation was reported.
Data integrity risk ✅ Passed No additional explanation was reported.
Maintainability issue ✅ Passed No additional explanation was reported.
Co-change coupling ✅ Passed No additional explanation was reported.
Redundant alias / duplicate import ✅ Passed No additional explanation was reported.
Redundant type construct ✅ Passed No additional explanation was reported.
Simplifiable code ✅ Passed No additional explanation was reported.
Unnecessary type assertion ✅ Passed No additional explanation was reported.
Module smell ✅ Passed No additional explanation was reported.
Excessive complexity ✅ Passed No additional explanation was reported.
Dead export (no callers) ✅ Passed No additional explanation was reported.
Code duplication / DRY violation ✅ Passed No additional explanation was reported.
Complexity Guard ✅ Passed No additional explanation was reported.
Bundle Size Monitor ✅ Passed No additional explanation was reported.

This comment is updated automatically whenever Autter reviews a new PR revision.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown

🧭 PR hygiene & process suggestions

Autter has 2 suggestion(s) about the shape of this PR (size, scope, reviewability). These are process guidance — not code defects — so they are consolidated here instead of posted as inline comments on individual files.

🟠 Missing linked tracker issue — Risk: 50/100

This PR's title and body do not reference any tracker issue (GitHub #123, Jira/Linear KEY-123, or Fixes/Closes/Resolves).

🛠 AI fix prompt (copy & paste into your coding agent)
In the PR description, add a reference to the tracker issue this change implements (GitHub `#123`, Jira/Linear `PROJ-456`, or a `Fixes/Closes/Resolves` marker). Reviewers anchor on `packages/runtime-node/test/redact.test.mjs` around line 127 need that context to understand why this change exists and what success looks like. Why it matters: reviewers and on-call engineers need the linked issue to understand the why behind a change months from now.

🟡 Missing CODEOWNERS reviewer approval — Risk: 40/100

The added redaction regression tests have no demonstrated approving CODEOWNER review; the only listed reviewer requested changes. This leaves coverage for redactAttributes and its secret-token masking contract unapproved. Blast radius — skipping this guardrail cascades to the downstream usage that depends on this file: scopes @autter/runtime-node; dependent files ../dist/index.js, node:assert/strict, node:test.

🛠 AI fix prompt (copy & paste into your coding agent)
Obtain an approving review from the CODEOWNER for packages/runtime-node/test/redact.test.mjs. Blast radius — skipping this guardrail cascades to the downstream usage that depends on this file: scopes `@autter/runtime-node`; dependent files `../dist/index.js`, `node:assert/strict`, `node:test`.

Flagged by Autter PR-hygiene checks.


⚠️ 1 unconfirmed finding(s) — flagged by a detector but not proven by Autter's verification pass

Inline comments are reserved for findings that survived verification. These are plausible but could not be confirmed from the available context, so they are listed here as FYIs instead — review the ones that look real to you.

  • 🟡 Missing CODEOWNERS reviewer approval (risk 49/100) — packages/runtime-node/src/redact.ts:46 — The supplied source and code graph do not establish whether a CODEOWNERS file exists or whether the required reviewers approved the PR; this repository evidence is insufficient to confirm a process violation.
🔇 2 finding(s) suppressed as likely false positives by Autter's verification pass

These were flagged by a detector but a second, full-file verification judged them not to be real issues. Listed here for transparency — review if you disagree.

  • 🟡 Access token in source (risk 1/100) — packages/runtime-node/test/redact.test.mjs:151 — These are test fixtures, not access tokens: every value is the literal placeholder "raw", and the test explicitly verifies that credential-shaped keys are masked. The file is under test/ and the values are not wired into authentication or any runtime credential path.
  • 🟡 Missing linked tracker issue (risk 35/100) — packages/runtime-node/src/redact.ts:46 — The supplied PR description does not state that no linked tracker issue was identified, so the finding's premise is unsupported. The code and tests only show the intentional redaction behavior change.

@autter-dev autter-dev 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.

Autter completed PR review for #17: 5 finding(s) remain below the merge-blocking bar, so this review stays neutral rather than approving. (Also detected: 2 finding(s) dismissed as likely false positives by verification.) See the findings below; the task checklist follows as the review's final comment.

@autter-dev autter-dev 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.

Autter posted 4 finding(s) as review threads below (🔴 3 · 🟠 1). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Narrowed token key matching allows custom secrets to be exported — Risk: 86/100

Changing the built-in token rule from a substring match to /token$/ means sensitive custom attribute names such as token_value, tokenString, or token_id are no longer masked by key. Their values can be arbitrary secrets that do not match the separate JWT/provider-token value regexes, so redactWith copies them unchanged and the server attaches those attributes to spans that are sent to the authenticated OTLP exporter. This is a reachable data-exposure regression for applications passing token-bearing custom attributes, and the added tests only cover token names that still end exactly in 'token'.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve masking for token-bearing secret keys while exempting only the documented usage/count attributes, for example by explicitly allowing known numeric GenAI usage keys or by using a boundary-aware token rule rather than requiring the whole key to end in token. Add regression tests for token_value, tokenString, token_id, and id_token alongside the usage-count exemptions.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Narrowed token-key matching allows opaque credentials into error telemetry — Risk: 86/100

This change stops treating any key containing token as sensitive and only masks keys ending exactly in token. As a result, common opaque credential names such as tokenValue, session_token_value, or idTokenValue are no longer masked; the value-level rules only recognize specific JWT/provider/bearer formats and will not reliably catch arbitrary credential strings. When application code captures an exception or error message with one of these attributes, the active capture path passes it through activeRedactor and creates the export span, so an exporter can receive the credential in failure telemetry instead of the operation failing safely. The new tests cover only token, access_token, refresh_token, and authToken, leaving this regression unproved for non-suffix token keys.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts, packages/runtime-node/test/redact.test.mjs
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve the GenAI usage-count exception without dropping broad secret-key protection: use an explicit allowlist for known usage/count keys or a key-pattern rule that masks token-bearing keys unless they are recognized numeric usage attributes, and add tests for opaque names such as tokenValue and session_token_value through captureException/captureMessage.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Token-containing secret keys no longer get masked unless they end exactly in token — Risk: 82/100

Changing the matcher from /token/ to /token$/ makes the redactor miss reachable secret-bearing attribute names such as tokenValue, oauth_token_value, or id_token_hash. These are accepted as arbitrary custom attributes and flow through activeRedactor in llmBaseAttributes (and the capture paths) without any other key-level guard; unless the value happens to match one of the separate token-shape regexes, it is exported unchanged. This contradicts the documented guarantee that attributes whose key looks like token are masked and regresses the prior behavior while fixing usage-count keys that contain tokens.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts, packages/runtime-node/README.md
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve the GenAI usage-count exception without weakening token-key redaction: use a matcher that recognizes token as a sensitive key component while explicitly excluding the documented usage/count forms (including `gen_ai.usage.*_tokens`, `prompt_tokens`, `completion_tokens`, `total_tokens`, `token_count`, and `max_tokens`), or otherwise classify usage keys before applying the generic token rule. Add regression coverage for a non-token-shaped secret under `tokenValue` or `oauth_token_value`.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated
/e-?mail/,
/pass(word|wd|phrase)|^pass$/,
/token/,
/token$/,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Suffix-only token matching leaks credential-bearing token attributes — Risk: 78/100

Changing the sensitive-key rule from substring matching to /token$/ removes the redaction guarantee for custom attribute names where token is followed by a qualifier, such as token_value, api_token_value, or id_token_hint. Those names are accepted through the public Attributes contract and their values can be arbitrary secrets; the new rule sends them through value redaction instead of masking the whole value, and ordinary secret values that do not match the token-shape regexes can therefore be exported. The call chain is active server capture -> activeRedactor -> redactWith -> isSensitiveKey, so this is a production privacy regression rather than a test-only behavior change.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve masking for credential-oriented token key variants while exempting known usage-count keys explicitly, or use a narrowly defined token-key regex that handles separators and suffix qualifiers without masking GenAI usage/count attributes.

Flagged by Autter security & observability checks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@autter then is it not correct that it should allow all forms of token?

@autter-dev autter-dev Bot Aug 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not all forms. The intended behavior is to allow the known usage-count keys, but still mask arbitrary credential-bearing names. In this codebase, generated GenAI usage is already added separately in packages/runtime-node/src/server.ts:533-547, while caller-supplied LLM attributes go through the shared redactor at packages/runtime-node/src/server.ts:517-530 and that redactor is also used for captured errors at packages/runtime-node/src/server.ts:813-825. With /token$/ in packages/runtime-node/src/redact.ts:43-50, names such as token_value, tokenString, or id_token_hint can now pass through if their values are opaque secrets that do not match the value regexes. So the safer fix is an explicit allowlist/exception for the usage metrics (for example gen_ai.usage.*_tokens, prompt_tokens, completion_tokens, total_tokens, token_count, max_tokens) while retaining broad token-key redaction for custom attributes. The current tests only prove the suffix cases in packages/runtime-node/test/redact.test.mjs:128-156; they do not cover those credential-bearing variants.

🤖 Replying to your mention — mention @autter again to continue.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown

🧪 Autter test run

Autter checked 29a86db7.

Execution summary: 4 checks executed · 4 passed.

Project test commands

Scope Command Result
@autter/otlp-ingester npm run test ⚠️ could not run — missing toolchain

Autter targeted verification

4 tests executed · 4 passed.

Declared tests: 8 test file(s) found — 0 ran, 0 not observed in suite output, 8 did not run.

⚠️ Test cases that did not run
  • packages/otlp-ingester/src/fingerprint.test.ts (3 cases) — its suite was skipped (missing toolchain)
  • packages/otlp-ingester/src/normalize-browser.test.ts (4 cases) — its suite was skipped (missing toolchain)
  • packages/otlp-ingester/src/normalize.test.ts (4 cases) — its suite was skipped (missing toolchain)
  • packages/otlp-ingester/src/server.sink.test.ts (2 cases) — its suite was skipped (missing toolchain)
  • packages/otlp-ingester/src/sink.test.ts (9 cases) — its suite was skipped (missing toolchain)
  • packages/runtime-browser/test/redact.test.mjs (5 cases) — no test suite covers this file
  • packages/runtime-node/test/autoflush.test.mjs (5 cases) — no test suite covers this file
  • packages/runtime-node/test/redact.test.mjs (15 cases) — no test suite covers this file

Change coverage (is each changed file's behavior verified by a test?)

Changed file Related test Result
packages/runtime-node/src/redact.ts packages/runtime-node/test/redact.test.mjs ✅ existing test passes
🤖 Coverage-check evidence

packages/runtime-node/src/redact.ts
Ran: npm run build -w @autter/runtime-node && node --test packages/runtime-node/test/redact.test.mjs

TAP: 1..15; # tests 15; # pass 15; # fail 0; build succeeded (ESM/CJS/DTS). Tests 13-15 covered canonical GenAI usage counts and token-key redaction.

Temporary tests are written under .autter/scratch/ for verification only — they are never committed to the repository.

Test plan (from the PR description)

  • ✅ Run the runtime-node redaction test suite and verify the new GenAI usage-count assertions pass. — verified by agent execution
  • ✅ Run npm run build from the repository root. — verified by agent execution
  • ✅ Inspect redacted output for numeric GenAI token counts, string token values, and unrelated keys such as discard_count and author_id. — verified by agent execution
🤖 Agent-executed checks

✅ Run the runtime-node redaction test suite and verify the new GenAI usage-count assertions pass.
Ran: npm install --include=dev && npm test -w @autter/runtime-node

TAP: 1..20; tests 20; suites 0; pass 20; fail 0. Subtests 18 and 19 ('keeps canonical GenAI usage counts only when numeric' and 'redacts non-numeric canonical GenAI usage values') both reported ok.

✅ Run npm run build from the repository root.
Ran: npm run build

Build succeeded for @autter/runtime-browser, @autter/runtime-node, @autter/otlp-ingester, and @autter/runtime-next; all tsup/tsc commands completed successfully.

✅ Inspect redacted output for numeric GenAI token counts, string token values, and unrelated keys such as discard_count and author_id.
Ran: node .autter/scratch/inspect-redaction.mjs

Observed: {"gen_ai.usage.input_tokens":512,"gen_ai.usage.output_tokens":128,"gen_ai.usage.total_tokens":640,"gen_ai.usage.input_tokens_string":"[redacted]","discard_count":7,"author_id":"u_8f2k1"}. Assertions passed for numeric counts, string redaction, and unrelated keys.

⬜ items could not be verified automatically and still need a manual check.

@autter-dev autter-dev 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.

Autter blocked this PR after its agentic checks (build/test/deep scans) completed: 2 confirmed correctness/runtime finding(s). See the findings below and the full PR review for details.

@autter-dev autter-dev 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.

🔴 Autter review in progress — running security, correctness & dependency checks on this PR. Follow live step-by-step progress on the autter/review-gate check in the merge box. Merge is blocked until the gate completes; Autter approves automatically when the review comes back clean, and releases this hold with a neutral review when it finds non-blocking issues.

@autter-dev autter-dev 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.

Autter posted 1 finding(s) as review threads below (🟡 1). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
return r.keyPatterns.some((re) => re.test(lowered));
const lowered = key.toLowerCase();

// Known GenAI usage-count attributes are safe to keep.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 [ai] Comment inaccurately categorizes max_tokens as a usage-count attribute — Risk: 10/100

The allowlist includes max_tokens, which is typically a generation-limit/request parameter, not a usage count. Update the comment to describe these as token-related GenAI attributes, or remove max_tokens if only usage counts should bypass redaction.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: redactAttributes, redactValue, isSensitiveKey, redactWith, makeRedactor, redactString
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Clarify the comment to describe all allowlisted token-related attributes, or remove `max_tokens` from this set if only usage-count attributes should bypass redaction. Blast radius — if this AI-generated slop ships it cascades to the downstream usage that depends on this file: functions `redactAttributes`, `redactValue`, `isSensitiveKey`, `redactWith`, `makeRedactor`, `redactString`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

@autter-dev autter-dev 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.

Autter posted 2 finding(s) as review threads below (🟠 2). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
"completion_tokens",
"total_tokens",
"token_count",
"max_tokens",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Sensitive max_tokens attributes bypass configured redaction — Risk: 75/100

The unconditional max_tokens allowlist entry skips all configured key-redaction patterns, so callers that treat this key as sensitive receive its value unredacted. Allowlist only actual usage-count fields or apply configured redaction patterns first.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: redactAttributes, redactValue, isSensitiveKey, redactWith, makeRedactor, redactString
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Remove `max_tokens` from the unconditional usage-token allowlist, or only exempt it when it is an explicitly recognized GenAI attribute and not when it matches a configured sensitive-key pattern. Add a regression test proving configured redaction still applies to `max_tokens`. Blast radius — if this defect reaches production it can fail the downstream usage that depends on this file: functions `redactAttributes`, `redactValue`, `isSensitiveKey`, `redactWith`, `makeRedactor`, `redactString`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated
const lowered = key.toLowerCase();

// Known GenAI usage-count attributes are safe to keep.
const usageKey = lowered.split(".").pop() ?? lowered;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Dotted attributes with allowlisted token suffixes bypass redaction — Risk: 75/100

Using lowered.split(".").pop() makes any attribute whose final segment is an allowlisted usage name bypass configured key redaction, including sensitive names such as credentials.input_tokens. Restrict the exemption to recognized GenAI usage attributes rather than arbitrary dotted keys.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: redactAttributes, redactValue, isSensitiveKey, redactWith, makeRedactor, redactString
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Match only the explicitly supported GenAI usage attribute names (including their documented full dotted forms), rather than allowing any key whose final segment is in `USAGE_TOKEN_KEYS`. Add regression tests showing unrelated dotted keys such as `credentials.input_tokens` remain redacted. Blast radius — if this defect reaches production it can fail the downstream usage that depends on this file: functions `redactAttributes`, `redactValue`, `isSensitiveKey`, `redactWith`, `makeRedactor`, `redactString`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown
⚠️ 2 unconfirmed finding(s) — flagged by a detector but not proven by Autter's verification pass

Inline comments are reserved for findings that survived verification. These are plausible but could not be confirmed from the available context, so they are listed here as FYIs instead — review the ones that look real to you.

  • 🟡 Missing linked tracker issue (risk 49/100) — packages/runtime-node/src/redact.ts:152 — The provided PR context does not show a statement that no linked issue exists, nor does it include tracker or PR metadata needed to verify whether an issue is linked.
  • 🟡 Missing CODEOWNERS reviewer approval (risk 49/100) — packages/runtime-node/src/redact.ts:163 — The provided code and graph do not include repository CODEOWNERS contents or review metadata, so the absence of required approval cannot be verified.

@autter-dev autter-dev 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.

Autter blocked this PR: 2 confirmed correctness/runtime finding(s). See the findings below and the full PR review for details.

@autter-dev autter-dev 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.

Autter posted 3 finding(s) as review threads below (🔴 3). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated

// Known GenAI usage-count attributes are safe to keep.
const usageKey = lowered.split(".").pop() ?? lowered;
if (USAGE_TOKEN_KEYS.has(usageKey)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Usage-key exemption bypasses configured sensitive-key redaction — Risk: 86/100

The new suffix allowlist returns false before evaluating every entry in r.keyPatterns. This changes the contract for all callers that pass additionalKeyPatterns: a caller configuring a sensitive key such as total_tokens now receives its value unchanged, despite RedactOptions documenting that matching additional key patterns mask the whole value. The same bypass also affects nested objects because redactValue calls isSensitiveKey for nested keys. Since makeSafeCapture and the server's cached activeRedactor both route caller attributes through this helper, sensitive values can cross those capture chains unmasked; the exemption must only apply to the built-in usage-key case without overriding explicit configured patterns.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/server.ts, packages/runtime-node/src/redact.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve the usage-count exception only for keys that are not matched by caller-supplied additionalKeyPatterns (and ensure the same precedence applies to nested keys). Evaluate explicit sensitive patterns before allowing the known usage suffixes, or otherwise distinguish the built-in token rule from configured rules.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated

// Known GenAI usage-count attributes are safe to keep.
const usageKey = lowered.split(".").pop() ?? lowered;
if (USAGE_TOKEN_KEYS.has(usageKey)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Usage-name exemption bypasses sensitive-key masking for arbitrary namespaces — Risk: 86/100

The new early return treats any key whose final dot segment is a known usage name as non-sensitive before evaluating the built-in or additional key patterns. Consequently a reachable public call such as captureException(error, {"password.token_count": "hunter2"}) or redactAttributes({"api_key.max_tokens": "secret"}) returns the secret unchanged: the key ends in token_count/max_tokens, so the /password/ or /api...key/ rule is never consulted, and the value is not otherwise scrubbed. The intended exemption is for numeric GenAI usage counts, but this implementation exempts arbitrary keys and value types, breaking the documented guarantee that attributes whose names look sensitive are masked before export.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Restrict the usage-count exemption to the intended GenAI/usage attribute namespace and numeric usage values, or otherwise ensure built-in and additional sensitive-key patterns take precedence; add regression coverage for sensitive keys ending in token_count and max_tokens.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated

// Known GenAI usage-count attributes are safe to keep.
const usageKey = lowered.split(".").pop() ?? lowered;
if (USAGE_TOKEN_KEYS.has(usageKey)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 [ai] Usage-key exemption bypasses secret redaction on captured failures — Risk: 86/100

The early return treats any attribute whose final dot-separated component is a usage token name as safe, before evaluating the built-in or caller-supplied sensitive-key patterns. Consequently a failed request reported with a key such as api.input_tokens or an explicitly configured additionalKeyPatterns: ["input_tokens"] can export its raw secret value; a string value also bypasses value scrubbing because redactWith skips redactValue for the exempt key. The same redactor is used for captured exceptions and error messages before their spans are exported (server.ts:719, server.ts:824, server.ts:868), so the failure path can leak credentials precisely when diagnostic telemetry is emitted. Restrict the exemption to the exact documented GenAI usage attribute names, and still let explicit additional key patterns take precedence.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Make the usage exemption apply only to the exact supported GenAI usage attribute names (or otherwise preserve the documented redaction precedence), and ensure caller-provided additionalKeyPatterns can never be bypassed. Add coverage for a secret-valued `api.input_tokens` and for an explicit `additionalKeyPatterns: ["input_tokens"]` case through captureException/captureMessage.

Flagged by Autter security & observability checks.

@autter-dev autter-dev 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.

🔴 Autter review in progress — running security, correctness & dependency checks on this PR. Follow live step-by-step progress on the autter/review-gate check in the merge box. Merge is blocked until the gate completes; Autter approves automatically when the review comes back clean, and releases this hold with a neutral review when it finds non-blocking issues.

@autter-dev autter-dev 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.

Autter posted 1 finding(s) as review threads below (🟠 1). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
const lowered = key.toLowerCase();

// Only explicitly supported GenAI usage attributes bypass key redaction.
if (USAGE_TOKEN_KEYS.has(lowered)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Code correctness issue — Risk: 75/100

This unconditional exemption bypasses all configured redaction patterns for generic keys such as token_count, total_tokens, and input_tokens. An arbitrary attribute using one of these names can now expose a sensitive string or other secret value, and callers cannot explicitly redact it. This affects the exported redactAttributes path and makeSafeCapture in packages/runtime-node/src/server.ts. This touches exported/public surface code, so impact assessment should consider downstream callers. Blast radius — if this defect reaches production it can fail the downstream usage that depends on this file: functions redactAttributes, redactValue, isSensitiveKey, redactWith, makeRedactor, redactString; scopes @autter/runtime-node; dependent files @opentelemetry/api.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Functions/symbols: redactAttributes, redactValue, isSensitiveKey, redactWith, makeRedactor, redactString
  • Dependent files: @opentelemetry/api
  • Scopes: @autter/runtime-node
🛠 AI fix prompt (copy & paste into your coding agent)
Preserve user-configured redaction for arbitrary attributes: exempt only canonical GenAI usage attributes when their values are valid non-negative numeric token counts, or otherwise apply the configured key redaction before bypassing. Add tests covering sensitive string values and custom redaction patterns on `token_count`/`input_tokens`, while retaining numeric GenAI usage counts. Blast radius — if this defect reaches production it can fail the downstream usage that depends on this file: functions `redactAttributes`, `redactValue`, `isSensitiveKey`, `redactWith`, `makeRedactor`, `redactString`; scopes `@autter/runtime-node`; dependent files `@opentelemetry/api`.

Flagged by Autter security & observability checks.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown
⚠️ 1 unconfirmed finding(s) — flagged by a detector but not proven by Autter's verification pass

Inline comments are reserved for findings that survived verification. These are plausible but could not be confirmed from the available context, so they are listed here as FYIs instead — review the ones that look real to you.

  • 🟡 Missing CODEOWNERS reviewer approval (risk 49/100) — packages/runtime-node/src/redact.ts:168 — The supplied files do not include CODEOWNERS content, reviewer approvals, or repository review metadata, so the absence of a required CODEOWNERS approval cannot be established.

@autter-dev autter-dev 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.

Autter blocked this PR: 1 confirmed correctness/runtime finding(s). See the findings below and the full PR review for details.

@autter-dev autter-dev 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.

Autter posted 2 finding(s) as review threads below (🟠 2). Each carries a copy-paste AI fix prompt.

Comment thread packages/runtime-node/src/redact.ts Outdated
const lowered = key.toLowerCase();

// Only explicitly supported GenAI usage attributes bypass key redaction.
if (USAGE_TOKEN_KEYS.has(lowered)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Token-count allowlist bypasses guaranteed redaction and custom key patterns — Risk: 78/100

The new early return makes exact keys such as token_count and input_tokens bypass every compiled key pattern, including caller-supplied additionalKeyPatterns. This breaks the documented contract for makeSafeCapture, whose callers use it as a guaranteed-redaction boundary, and for RedactOptions, where matching additional key patterns are supposed to mask the whole value. A library calling safe.captureException(error, { token_count: secret }) or configuring redactAttributes({ additionalKeyPatterns: ['token_count'] }) now forwards the value unchanged instead of masking it.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Apply the usage exception only to the built-in GenAI usage attributes, or evaluate caller-supplied additionalKeyPatterns before the usage allowlist. Preserve makeSafeCapture's guarantee that every sensitive/custom-matched attribute is redacted.

Flagged by Autter security & observability checks.

Comment thread packages/runtime-node/src/redact.ts Outdated
const lowered = key.toLowerCase();

// Only explicitly supported GenAI usage attributes bypass key redaction.
if (USAGE_TOKEN_KEYS.has(lowered)) return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Usage-key exemption can leak arbitrary sensitive values during error capture — Risk: 78/100

The exact-key bypass disables the whole-value sensitive-key mask for every value stored under an allowlisted usage name, but it does not validate that the value is a numeric token count. If an exception or failure path passes an attacker-controlled or accidentally mis-keyed string such as gen_ai.usage.input_tokens: "database password: ...", redactValue only applies the finite value-pattern scrubbers and then returns any text those patterns do not recognize. The previous key-level behavior would have replaced the entire value before the span was exported, so this change is not safe unless the exemption is restricted to validated numeric usage values (or the value is otherwise guaranteed not to contain secrets).

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts, packages/runtime-node/src/server.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Keep the usage exemption only when the value is a finite numeric token count, or apply a type/value validation before bypassing key redaction; non-numeric or object/string values under usage keys should remain fully masked.

Flagged by Autter security & observability checks.

@autter-dev autter-dev 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.

🔴 Autter review in progress — running security, correctness & dependency checks on this PR. Follow live step-by-step progress on the autter/review-gate check in the merge box. Merge is blocked until the gate completes; Autter approves automatically when the review comes back clean, and releases this hold with a neutral review when it finds non-blocking issues.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown
⚠️ 1 unconfirmed finding(s) — flagged by a detector but not proven by Autter's verification pass

Inline comments are reserved for findings that survived verification. These are plausible but could not be confirmed from the available context, so they are listed here as FYIs instead — review the ones that look real to you.

  • 🟡 Missing CODEOWNERS reviewer approval (risk 49/100) — packages/runtime-node/src/redact.ts:145 — The supplied files contain no CODEOWNERS configuration or review metadata, so the claimed absence of required approval cannot be verified from the provided evidence.

@autter-dev autter-dev 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.

Autter completed PR review for #17: 4 finding(s) remain below the merge-blocking bar, so this review stays neutral rather than approving. See the findings below; the task checklist follows as the review's final comment.

@autter-dev autter-dev 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.

Autter posted 1 finding(s) as review threads below (🟠 1). Each carries a copy-paste AI fix prompt.


// Canonical GenAI usage attributes are safe when they contain
// valid non-negative numeric counts.
if (USAGE_TOKEN_KEYS.has(lowered)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [ai] Canonical usage exemption ignores additional key redaction patterns — Risk: 56/100

The canonical GenAI branch returns before checking r.keyPatterns, so a caller-supplied additionalKeyPatterns match can never redact a valid numeric value under a canonical usage key such as gen_ai.usage.input_tokens. This is reachable through the documented redactAttributes(attributes, { additionalKeyPatterns: [...] }) API and violates the option contract that extra key patterns extend the built-in key rules, allowing a configured policy to be silently bypassed for these attributes.

⚠ Downstream affected — if this fails, it cascades to the usage that depends on this file:

  • Dependent files: packages/runtime-node/src/redact.ts
🛠 AI fix prompt (copy & paste into your coding agent)
Evaluate the configured key patterns before applying the canonical GenAI numeric exemption, while retaining the exemption only when no configured pattern matches and the value is a finite non-negative number.

Flagged by Autter security & observability checks.

@autter-dev autter-dev 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.

Autter posted 2 finding(s) as review threads below (🟠 2). Each carries a copy-paste AI fix prompt.

const out = redactAttributes({
"gen_ai.usage.input_tokens": "secret",
"gen_ai.usage.output_tokens": -1,
"gen_ai.usage.total_tokens": NaN,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [deterministic] Biome: lint/style/useNumberNamespace — Risk: 55/100

Use Number.NaN instead of the equivalent global.

🛠 AI fix prompt (copy & paste into your coding agent)
Fix the Biome `lint/style/useNumberNamespace` issue at packages/runtime-node/test/redact.test.mjs:158: Use Number.NaN instead of the equivalent global.

Flagged by Autter security & observability checks.

"gen_ai.usage.input_tokens": "secret",
"gen_ai.usage.output_tokens": -1,
"gen_ai.usage.total_tokens": NaN,
"gen_ai.usage.token_count": Infinity,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 [deterministic] Biome: lint/style/useNumberNamespace — Risk: 55/100

Use Number.POSITIVE_INFINITY instead of the equivalent global.

🛠 AI fix prompt (copy & paste into your coding agent)
Fix the Biome `lint/style/useNumberNamespace` issue at packages/runtime-node/test/redact.test.mjs:159: Use Number.POSITIVE_INFINITY instead of the equivalent global.

Flagged by Autter security & observability checks.

@autter-dev

autter-dev Bot commented Aug 26, 2026

Copy link
Copy Markdown

Autter task list

  • @rajeshaipython-stack Honor additional redaction patterns before preserving canonical usage counts (packages/runtime-node/src/redact.ts, packages/runtime-node/test/redact.test.mjs) - Update redactValue so canonical GenAI and LLM usage keys preserve finite numeric counts only when they do not match caller-supplied keyPatterns, while continuing to mask matching, string-valued, non-numeric, and sensitive token fields.
  • @rajeshaipython-stack Add regression coverage for pattern overrides and numeric edge cases (packages/runtime-node/test/redact.test.mjs) - Extend the redaction tests to assert that additional patterns override the canonical numeric exemption and that NaN and positive infinity are handled according to the intended masking policy alongside existing numeric, string, nested, and unrelated-key cases.
  • @rajeshaipython-stack Use Number namespace constants in redaction tests (packages/runtime-node/test/redact.test.mjs) - Replace global NaN and Infinity references with Number.NaN and Number.POSITIVE_INFINITY to satisfy Biome useNumberNamespace lint rules.
  • @rajeshaipython-stack Link the redaction change to a tracker issue (packages/runtime-node/src/redact.ts, packages/runtime-node/test/redact.test.mjs) - Create or identify a tracker issue covering canonical GenAI token-count redaction behavior and add its GitHub, Jira, or Linear reference to the PR title or description.
  • @rajeshaipython-stack Obtain CODEOWNERS approval for runtime-node redaction changes (packages/runtime-node/src/redact.ts, packages/runtime-node/test/redact.test.mjs) - Identify the appropriate runtime-node ownership group, request review, and obtain an approving review for both the implementation and its regression tests before merging.
  • @rajeshaipython-stack Run package and workspace verification before merge (packages/runtime-node/src/redact.ts, packages/runtime-node/test/redact.test.mjs, packages/runtime-node/src/server.ts) - Run the runtime-node redaction test suite, Biome validation, and npm run build from the repository root, then manually inspect numeric canonical counts, string token fields, additional-pattern matches, discard_count, and author_id outputs.

Generated from PR diff, blast radius, and context.

Issues found

  1. Canonical usage exemption ignores additional key redaction patterns · risk 56/100 · packages/runtime-node/src/redact.ts:170
  2. Biome: lint/style/useNumberNamespace · risk 55/100 · packages/runtime-node/test/redact.test.mjs:158
  3. Biome: lint/style/useNumberNamespace · risk 55/100 · packages/runtime-node/test/redact.test.mjs:159
  4. Missing linked tracker issue · risk 50/100 · packages/runtime-node/test/redact.test.mjs:127
  5. Missing CODEOWNERS reviewer approval · risk 49/100 · packages/runtime-node/src/redact.ts:145
  6. Missing CODEOWNERS reviewer approval · risk 45/100 · packages/runtime-node/test/redact.test.mjs:128
  7. Missing linked tracker issue · risk 35/100 · packages/runtime-node/src/redact.ts:152

🛠 Fix options

Check one option and Autter will start a fix run for the unresolved issues above.

  • One PR with all unresolved fixes
  • One independent PR per unresolved issue

Checking a box triggers the fix run immediately — Autter comments back with the issues being fixed and the branch created for each.

@rajeshaipython-stack

Copy link
Copy Markdown
Contributor Author

Hi Sagnik,
I’ve addressed the token redaction issue identified in the review. The latest commit (29a86db) now preserves only the supported canonical gen_ai.usage.* attributes when their values are valid non-negative numeric counts, while sensitive token-like attributes continue to be redacted.
I also added regression coverage for numeric and non-numeric GenAI usage values. The runtime-node build completes successfully, and all 15 redaction tests are passing.
Could you please re-review the latest changes and approve the PR if everything looks good?
Thank you.

@sagnik11
sagnik11 merged commit 8e340ec into Autter-dev:main Aug 29, 2026
2 checks passed
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.

2 participants