Skip to content

fix(network): keep short values and pseudo-headers out of secret profiles - #234

Open
thdxr wants to merge 1 commit into
devfrom
fix/secret-overmatch
Open

thdxr wants to merge 1 commit into
devfrom
fix/secret-overmatch

Conversation

@thdxr

@thdxr thdxr commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

follow-up to the :authority fix. that one was an exact-name exclusion, so any other http/2 pseudo-header (or one spelled with stray whitespace) still went through secretNamePattern and could become a credential slot, replacing the hostname across the whole HAR.

profiles from older builds are cleaned when read and before they are written back: slots shorter than 8 characters and slots whose only sources are non-:path pseudo-headers are dropped. a header source must be METHOD url.request.header.:x or METHOD url.response.header.:x; only query, fragment, request and response can directly follow the scope, and json/form/multipart/header only appear after request/response. ambiguous URL paths ending in .query or .fragment are kept, because wrongly dropping a real secret is worse than keeping a hostname. dropped slots are not matched by value, not counted as observed, and not exported by secrets_run.

nextRef is now stored as a high-water mark, computed from the raw slots before cleaning and persisted on write. a ref held by a dropped slot is never handed to a new credential, so old HARs and scripts that still use $BC_SECRET_2 as a hostname can't receive a new token there.

  • pseudo-headers are skipped by : prefix, so none of them can become a slot regardless of name
  • short captured values are redacted in place as BC_REDACTED_n refs, but not stored as profile slots
  • secrets_run redacts only the remaining profile values, so text like BC_SECRET_1 isn't mangled by a one-character slot
  • long credentials keep being redacted

Fixes #233

@thdxr
thdxr force-pushed the fix/secret-overmatch branch 3 times, most recently from bf77e57 to 85bef1e Compare November 11, 2026 18:28
HTTP/2 pseudo-header sources are recognized only when the header segment
directly follows the request scope in METHOD url.request.header.:name or
METHOD url.response.header.:name form, with optional occurrence suffixes
and whitespace-padded old spellings. Only query, fragment, request and
response can directly follow the scope; json, form, multipart and header
only appear after request and response. Ambiguous URL paths ending in
.query or .fragment are kept, because wrongly dropping a real secret is
worse than keeping a hostname.

Short captured values and pseudo-header-only slots are dropped when a
profile is read or written back. AuthProfile keeps an optional nextRef
high-water mark, computed from the raw slots before cleaning, so a ref
held by a dropped slot is never handed to a new credential. It remains
readable for old profiles without the field.

secrets_run only exports the remaining slots, and redacts their values
from stdout/stderr instead of letting short values mangle text such as
BC_SECRET_1. Add on-disk profile tests for read, status, run and ref
continuity.
@thdxr
thdxr force-pushed the fix/secret-overmatch branch from 85bef1e to 3109f1c Compare November 11, 2026 18:43

This branch has not been deployed

No deployments
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.

Redaction over-matches: HTTP/2 :authority treated as a credential, and 1-character secrets corrupt HARs and command output

1 participant