Skip to content

Redact sensitive headers in populateServerData (DATA-12974)#32

Open
pragyash258 wants to merge 8 commits into
masterfrom
data-12974-secure-headers-and-ci-hygiene
Open

Redact sensitive headers in populateServerData (DATA-12974)#32
pragyash258 wants to merge 8 commits into
masterfrom
data-12974-secure-headers-and-ci-hygiene

Conversation

@pragyash258
Copy link
Copy Markdown
Collaborator

@pragyash258 pragyash258 commented May 26, 2026

Summary

Closes DATA-12974populateServerData in lib/chitragupta/util.js was running JSON.stringify(request.headers) with no denylist, so every request through setupServerLogger was writing Authorization, Cookie, Set-Cookie, X-Api-Key, X-Auth-Token, Proxy-Authorization, and WWW-Authenticate headers into log records in cleartext. Any operator with Kibana access could see Bearer tokens and session cookies. This is the one operational security vulnerability the scan turned up that has a real path in our deployment.

Code changes

File Change
lib/chitragupta/util.js Add DEFAULT_SENSITIVE_HEADERS denylist (case-insensitive match on the 7 header names above) and a redactHeaders(headers) helper that replaces matched values with [REDACTED] before the JSON serialisation. Export extendSensitiveHeaders([...]) so a host app can extend the denylist without forking.
lib/chitragupta/chitragupta.js One-line re-export of extendSensitiveHeaders from util.js (part of the same feature).
package.json Patch bump 1.7.5 → 1.7.6, add engines: { node: ">=14.0.0" } to match the only consumer's runtime floor.
.nvmrc 10.3.0 → 18.18.0 (stale — ip-protection runs Node 18.18.0 per its Dockerfile).

That's the full scope. No other features, no API-shape changes, no behaviour change for non-redacted headers.

Downstream-safety verification

a11y-engine/ip-protection is the only Node consumer of chitragupta-node. It uses three Chitragupta APIs (all keep identical surface and semantics after this PR):

API Call site Behaviour after this PR
Chitragupta.setupServerLogger app.js:179 Identical control flow. Authorization/Cookie/etc in the resulting log records now appear as [REDACTED].
Chitragupta.jsonLogFormatter utils/logger.js:41 Identical.
Chitragupta.setMetaData('userId', req.userId) utils/middleware.js:119 Identical — literal 'userId' key, no policy change.

Elasticsearch check (chitraguptaes-use-cluster-001, 7-day window): zero saved Kibana searches / dashboards / visualizations / lenses reference any of the 7 sensitive header names; zero documents currently have data.data.request.headers populated with these values. The change has no observable blast radius on existing query consumers.

Workspace grep also confirms ip-protection reads req.headers.authorization from the live HTTP request (utils/middleware.js:63,157,228) for auth processing — this PR does not touch req.headers, so the auth flow is unaffected.

Tickets explicitly NOT in scope of this PR

The other 35 tickets in the DATA-12973 → DATA-13008 range have all been classified as WONT-FIX or DUPLICATE after applying a strict "real operational security vulnerability" lens. They fall into:

  • Library-trust-contract / design-by-intent: 12977, 12981, 12983, 12989, 12991, 12993, 12997, 13000, 13006, 13007. (The API exposes things the host controls; ip-protection passes literal 'userId'; verifier itself flags Confidence -10: depends on host misuse on the strongest of these.)
  • Low-blast-radius CI/hygiene: 12975, 12976, 12978, 12980, 12985, 12987, 12995, 12996. (Host Gemfile.lock governs runtime, Logstash JSON codec absorbs CRLF, Semgrep workflow declares contents: read + zero secrets, etc.)
  • Not an operational security vulnerability: 12979, 12982, 12986, 12990, 12992, 12994, 12999, 13002, 13003, 13004, 13005. (No reachable CVE trigger, observability defect not exploit primitive, downstream-viewer renders text, dependabot is process hygiene, chains whose leaves are all WONT-FIX.)
  • Duplicate: 12984, 12988, 12998, 13001, 13008.
  • Not exercised by Rails consumers: 12973 (Rack/Sinatra path; both our gem consumers are Rails).

Per-ticket close-out comments are in /Users/pragyashpratimbarman/data/chitragupta-security-audit-2026-05-21/DATA-*.md under each file's ## Final close-out comment section, ready to copy into the Jira/Slack reply.

Test plan

  • Branch CI passes green.
  • After merge: tag v1.7.6 on master.
  • Update a11y-engine/ip-protection/package.json to pin chitragupta to git+https://github.com/browserstack/chitragupta-node.git#v1.7.6 and npm install chitragupta.
  • Verify in Kibana that Authorization / Cookie / X-Api-Key headers from an ip-protection request now appear as [REDACTED] in the indexed log records.
  • (Optional) If any host needs an additional header redacted, document the Chitragupta.extendSensitiveHeaders([...]) extension API in the gem README.

🤖 Generated with Claude Code

Weekly npm and github-actions ecosystem updates with grouped minor/patch PRs.
…, DATA-12979, DATA-12992)

Add header denylist for Authorization/Cookie/Set-Cookie/X-Api-Key/X-Auth-Token/Proxy-Authorization/WWW-Authenticate before serialising request headers into the log payload. extendSensitiveHeaders() lets a host extend the denylist without forking. UUID v1-v5 allowlist on x-chitragupta-log-id at populateServerData; non-UUID inputs are dropped, not propagated.
Block __proto__/constructor/prototype keys at the public setMetaData API. Reserved identity keys (userId/request/etc) intentionally remain writable — host apps legitimately call setMetaData('userId', ...) at request time. Re-exports extendSensitiveHeaders from util.js.
Patch bump for security hardening (header redaction, log-id allowlist, proto guard). Adds engines.node >= 14.0.0 to formalise the runtime floor required for the only consumer (ip-protection on Node 18).
ip-protection (the only Node consumer) runs Node 18.18.0 per its Dockerfile. The previous .nvmrc claim of 10.3.0 was a stale floor that did not match any actual deployment.
@pragyash258 pragyash258 requested a review from a team as a code owner May 26, 2026 11:42
Narrowing PR scope to only the operational fix (header denylist). The UUID
allowlist on x-chitragupta-log-id closed DATA-12979/12992/13005, but on
audit those tickets are not operational hazards — the JSON pipeline already
absorbs CRLF inside string values, and Kibana renders log.id as text not
HTML, so the downstream XSS leg cannot fire in our deployment.
DATA-12979/12992/13005 are reclassified WONT-FIX in
/data/chitragupta-security-audit-2026-05-21/INDEX.md (revision 2).
Narrowing PR scope. The PROTO_POLLUTION_KEYS guard closed DATA-12990 but
the underlying ticket is library-trust-contract — verifier itself admits
Confidence -10 ('depends on host misuse'), and our only Node consumer
(ip-protection/utils/middleware.js:119) passes the literal string 'userId'
to setMetaData. There is no operational hazard. DATA-12990 reclassified
WONT-FIX in /data/chitragupta-security-audit-2026-05-21/INDEX.md
(revision 2). Re-export of extendSensitiveHeaders remains because it is
part of the DATA-12974 header-denylist feature this PR ships.
Narrowing PR scope. dependabot.yml closed DATA-12994 but the underlying
ticket is process hygiene, not an operational hazard. The chitragupta-node
repo is a sleepy library; manual `npm audit` cadence at release-tag time
is accepted. DATA-12994 reclassified WONT-FIX in
/data/chitragupta-security-audit-2026-05-21/INDEX.md (revision 2).
@pragyash258 pragyash258 changed the title Redact sensitive headers, allowlist log-id, proto guard (DATA-12974 et al) Redact sensitive headers before logging (DATA-12974) May 26, 2026
@pragyash258 pragyash258 changed the title Redact sensitive headers before logging (DATA-12974) Redact sensitive headers in populateServerData (DATA-12974) May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant