Skip to content

fix: validate path parameters and prevent traversal/injection in REST transcoder - #67

Open
quartzmo wants to merge 8 commits into
googleapis:mainfrom
quartzmo:gapic-common-validation
Open

quartzmo wants to merge 8 commits into
googleapis:mainfrom
quartzmo:gapic-common-validation

Conversation

@quartzmo

@quartzmo quartzmo commented Jul 27, 2026

Copy link
Copy Markdown
Member

Implement path parameter validation in GrpcTranscoder#bind_uri_values! to protect
GAPIC REST clients from path traversal and parameter injection exploits.

Specifically, this change:

  • Rejects query (?) and fragment (#) characters in path parameter values to block parameter injection.
  • Rejects slashes (/) and dots (. or ..) in standard single-wildcard (*) variables (since they must represent a single, non-traversal segment).
  • Rejects dots (. or ..) anywhere in double-wildcard (**) variables, failing the request if directory traversal segments are present (as per the finalized canonical specification).

… transcoder

Implement path parameter validation in GrpcTranscoder#bind_uri_values! to protect
GAPIC REST clients from path traversal and parameter injection exploits.

Specifically, this change:
- Rejects query (?) and fragment (#) characters in path parameter values.
- Rejects slashes (/) and dots (. or ..) in standard single-wildcard (*) variables.
- Validates path traversals in double-wildcard (**) variables using the segment-traversal validation algorithm.
- Extracts the wildcard segment using the __wildcard__ named capture group, with on-the-fly regex patching fallback for legacy stubs.
- Validates prefix segments to prevent prefix buffering bypasses.

Note: If the canonical specification is updated to favor the simpler alternative,
this implementation can be easily simplified to "Fail always if dots are found in
a double-wildcard value" by replacing the segment-traversal logic with a simple
check for any "." or ".." substring.
@quartzmo
quartzmo force-pushed the gapic-common-validation branch from fda77f0 to 25e80c6 Compare August 3, 2026 17:35
@quartzmo
quartzmo marked this pull request as ready for review August 4, 2026 23:30
@quartzmo
quartzmo requested a review from a team as a code owner August 4, 2026 23:30
danieljbruce added a commit to googleapis/google-cloud-node that referenced this pull request Aug 18, 2026
… transcoder (#9151)

## Description

[Protect GAPIC REST clients from path
traversal](https://b.corp.google.com/issues/506021899/dependencies) and
parameter injection exploits with two mechanisms:
1. Percent encodes special characters to ensure intended operations like
reads can't become writes etc.
2. Throws an error when .. or . characters are used for path traversal.
This differs depending on whether the * or ** wildcard is used. For *
throws an error when exact matches are made with . and .. . For **
throws an error when the placeholder includes . or .. between slashes.

## Impact

Improves the security of our clients by preventing exploits.

## Testing

It should be noted that some new tests in
packages/google-cloud-dialogflow-cx/test/transcoding_validation.ts were
skipped because they fail in the CI pipeline. This is because they pass
with these changes, but these changes are to gax and
google-cloud-dialogflow-cx does not get this version of gax yet until it
is published.

To test locally:
cd packages/google-cloud-dialogflow-cx
pnpm link ../../core/packages/gax
npm run compile && npx mocha build/test/transcoding_validation.js

Transcoding tests are also added which provide support for ** wildcard
which the dialogflow-cx tests can't cover.

## Additional Info

I identified a refactor in
https://github.com/googleapis/google-cloud-node/pull/9150/changes which
should be worth considering to improve readability.

It should also be noted that
googleapis/ruby-core-libraries#67 was done for
Ruby which has differences that may vary from language to language.

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: danieljbruce <8935272+danieljbruce@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
"for field #{field_binding.field_path.inspect}"
end

validate_path_binding! field_binding, field_value

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.

super nit: we could just call these methods independently on L121 and L122 instead of wrapping validate_path_binding!.

@aandreassa

Copy link
Copy Markdown
Contributor

@quartzmo LGTM overall!

One question: earlier we merged the generator change to add the (?<__wildcard__>.*) capture group. Does this PR make use of that at all anymore? I noticed split("/", -1)

@quartzmo

Copy link
Copy Markdown
Member Author

One question: earlier we merged the generator change to add the (?<wildcard>.*) capture group. Does this PR make use of that at all anymore? I noticed split("/", -1)

@aandreassa, good catch. You're right that this PR no longer makse use of the capture group. The final design (updated after merging the capture group PR) changed the solution to simply reject the request if any segment in the parameter value is . or ... Because the capture group is harmless (the regex still matches the exact same patterns), I was just planning to leave it in the generated code. But we can revert back to the old regex too.

@quartzmo
quartzmo force-pushed the gapic-common-validation branch from 69e9172 to d0210db Compare August 27, 2026 22:07

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

Can't speak on the ruby-ness but domain-wise looks good

next unless segment == "." || segment == ".."
if field_binding.preserve_slashes
raise ::Gapic::Common::Error,
"Value for #{field_binding.field_path} must not contain segments that are exactly . or .."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

NIT: separate these by . and .. cases

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.

5 participants