Skip to content

fix: validate traceparent before using trace context#1897

Open
miloquinn wants to merge 1 commit into
TryGhost:mainfrom
miloquinn:fix-validate-trace-context
Open

fix: validate traceparent before using trace context#1897
miloquinn wants to merge 1 commit into
TryGhost:mainfrom
miloquinn:fix-validate-trace-context

Conversation

@miloquinn

Copy link
Copy Markdown

Summary

  • Validate W3C traceparent fields before returning Cloud Logging trace context.
  • Reject malformed trace IDs, span IDs, flags, and all-zero identifiers instead of emitting invalid trace metadata.
  • Add unit coverage for valid sampled/unsampled headers and malformed headers.

Testing

  • corepack yarn vitest run --dir src --reporter=dot src/helpers/context-header.unit.test.ts
  • corepack yarn _test:types
  • corepack yarn lint src/helpers/context-header.ts src/helpers/context-header.unit.test.ts

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec6a0b1f-a73f-4e5a-ac8a-95bbcee1544b

📥 Commits

Reviewing files that changed from the base of the PR and between b630a49 and 04545c1.

📒 Files selected for processing (2)
  • src/helpers/context-header.ts
  • src/helpers/context-header.unit.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/helpers/context-header.unit.test.ts
  • src/helpers/context-header.ts

Walkthrough

getTraceContext in src/helpers/context-header.ts now splits the traceparent value into version, traceId, spanId, and flags, validates each part against expected hex formats and lengths, and rejects all-zero trace or span IDs. Invalid input now returns { traceId: null, spanId: null, sampled: null }. A new Vitest test file covers missing, valid sampled/unsampled, and invalid traceparent values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: validating traceparent before using trace context.
Description check ✅ Passed The description clearly matches the changeset and mentions validation, rejection of malformed headers, and added unit coverage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/helpers/context-header.ts`:
- Around line 14-20: The version field validation in the isValidTraceContext
logic currently accepts the reserved value `ff`, which violates the W3C Trace
Context specification. Add an additional condition to the isValidTraceContext
validation that explicitly checks version !== 'ff' to reject this reserved
version value, ensuring invalid trace metadata is not emitted downstream.

In `@src/helpers/context-header.unit.test.ts`:
- Around line 40-49: The test matrix in the it.each block for invalid
traceparent validation is missing a regression case for the reserved version
"ff", which means strict version validation isn't fully tested. Add a new
traceparent string to the test array that uses "ff" as the version prefix (the
first segment before the first dash) while keeping the other segments valid,
such as "ff-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", to ensure the
reserved-version validation is properly covered by the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89b497dc-b473-459c-87c3-db43e1c32658

📥 Commits

Reviewing files that changed from the base of the PR and between 7389379 and 6e6e3c8.

📒 Files selected for processing (2)
  • src/helpers/context-header.ts
  • src/helpers/context-header.unit.test.ts

Comment on lines +14 to +20
const isValidTraceContext =
/^[0-9a-f]{2}$/.test(version) &&
/^[0-9a-f]{32}$/.test(traceId) &&
traceId !== '00000000000000000000000000000000' &&
/^[0-9a-f]{16}$/.test(spanId) &&
spanId !== '0000000000000000' &&
/^[0-9a-f]{2}$/.test(flags);

@coderabbitai coderabbitai Bot Jun 17, 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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In the W3C Trace Context traceparent specification, is version value "ff" explicitly invalid/reserved?

💡 Result:

Yes, in the W3C Trace Context traceparent specification, the version value "ff" is explicitly defined as invalid [1][2][3]. The specification states that the version field is an 8-bit unsigned integer serialized as two hexadecimal characters, and specifically reserves "ff" (decimal 255) as an invalid value [1][2][4]. This constraint is formally documented within the header format specification, which includes the ABNF note: "; this document assumes version 00. Version ff is forbidden" [1][3][5].

Citations:


Reject reserved traceparent version ff.

The version field currently accepts ff, but the W3C Trace Context specification explicitly forbids this value. Without this check, invalid trace metadata will be emitted downstream.

Suggested patch
     const isValidTraceContext =
         /^[0-9a-f]{2}$/.test(version) &&
+        version !== 'ff' &&
         /^[0-9a-f]{32}$/.test(traceId) &&
         traceId !== '00000000000000000000000000000000' &&
         /^[0-9a-f]{16}$/.test(spanId) &&
         spanId !== '0000000000000000' &&
         /^[0-9a-f]{2}$/.test(flags);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isValidTraceContext =
/^[0-9a-f]{2}$/.test(version) &&
/^[0-9a-f]{32}$/.test(traceId) &&
traceId !== '00000000000000000000000000000000' &&
/^[0-9a-f]{16}$/.test(spanId) &&
spanId !== '0000000000000000' &&
/^[0-9a-f]{2}$/.test(flags);
const isValidTraceContext =
/^[0-9a-f]{2}$/.test(version) &&
version !== 'ff' &&
/^[0-9a-f]{32}$/.test(traceId) &&
traceId !== '00000000000000000000000000000000' &&
/^[0-9a-f]{16}$/.test(spanId) &&
spanId !== '0000000000000000' &&
/^[0-9a-f]{2}$/.test(flags);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/helpers/context-header.ts` around lines 14 - 20, The version field
validation in the isValidTraceContext logic currently accepts the reserved value
`ff`, which violates the W3C Trace Context specification. Add an additional
condition to the isValidTraceContext validation that explicitly checks version
!== 'ff' to reject this reserved version value, ensuring invalid trace metadata
is not emitted downstream.

@sagzy sagzy Jun 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This comment from Rabbit looks valid / worth addressing

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@sagzy, glad we're on the same page! The fix is straightforward — just add version !== 'ff' after the regex check in src/helpers/context-header.ts:

     const isValidTraceContext =
         /^[0-9a-f]{2}$/.test(version) &&
+        version !== 'ff' &&
         /^[0-9a-f]{32}$/.test(traceId) &&
         traceId !== '00000000000000000000000000000000' &&
         /^[0-9a-f]{16}$/.test(spanId) &&
         spanId !== '0000000000000000' &&
         /^[0-9a-f]{2}$/.test(flags);

Don't forget to add a corresponding test case for version === 'ff' in src/helpers/context-header.unit.test.ts as well.

Comment on lines +40 to +49
it.each([
'00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7',
'00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01-extra',
'zz-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01',
'00-xyz-00f067aa0ba902b7-01',
'00-00000000000000000000000000000000-00f067aa0ba902b7-01',
'00-4bf92f3577b34da6a3ce929d0e0e4736-xyz-01',
'00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000000-01',
'00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-zz',
])('returns null fields for invalid traceparent %s', (traceparent) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a regression case for invalid version ff.

The invalid-input matrix is missing the reserved-version case, so the strict-validation objective isn’t fully pinned by tests.

Suggested patch
     it.each([
         '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7',
         '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01-extra',
+        'ff-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01',
         'zz-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01',
         '00-xyz-00f067aa0ba902b7-01',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/helpers/context-header.unit.test.ts` around lines 40 - 49, The test
matrix in the it.each block for invalid traceparent validation is missing a
regression case for the reserved version "ff", which means strict version
validation isn't fully tested. Add a new traceparent string to the test array
that uses "ff" as the version prefix (the first segment before the first dash)
while keeping the other segments valid, such as
"ff-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", to ensure the
reserved-version validation is properly covered by the test.

@sagzy sagzy force-pushed the fix-validate-trace-context branch from 6e6e3c8 to b630a49 Compare June 22, 2026 08:03
/^[0-9a-f]{32}$/.test(traceId) &&
traceId !== '00000000000000000000000000000000' &&
/^[0-9a-f]{16}$/.test(spanId) &&
spanId !== '0000000000000000' &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: the 32/16 zeros are hard to read, should we simplify with

!/^0+$/.test(traceId) &&
!/^0+$/.test(spanId)

as the preceding regex already checks for hex of the right length?

Comment on lines +14 to +20
const isValidTraceContext =
/^[0-9a-f]{2}$/.test(version) &&
/^[0-9a-f]{32}$/.test(traceId) &&
traceId !== '00000000000000000000000000000000' &&
/^[0-9a-f]{16}$/.test(spanId) &&
spanId !== '0000000000000000' &&
/^[0-9a-f]{2}$/.test(flags);

@sagzy sagzy Jun 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This comment from Rabbit looks valid / worth addressing

const [_version, traceId, spanId, flags] = parts;
const [version, traceId, spanId, flags] = parts;

const isValidTraceContext =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: would be worth adding an inline comment here to explain why we're doing this

e.g. "Reject malformed/spoofed traceparent so we don't emit junk trace IDs to Cloud Logging"

@sagzy sagzy force-pushed the fix-validate-trace-context branch from b630a49 to 48e4a13 Compare June 22, 2026 08:58
@sagzy

sagzy commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Hey @miloquinn, thanks for your contribution 🙏

I've left some minor comments, this looks good overall! Can you ping me once you've gone through addressing those?

@sagzy sagzy force-pushed the fix-validate-trace-context branch from 48e4a13 to 04545c1 Compare June 24, 2026 08:09
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