You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
@google-cloud/common@8.0.2 security patch breaks ADC project ID detection — joinURIComponents() encodes DEFAULT_PROJECT_ID_TOKEN before replaceProjectIdToken() runs #9256
@google-cloud/common@8.0.2 introduced joinURIComponents() in Service.request_() as part of PR #9188.
While encoding URI path components is appropriate for user-supplied resource IDs, it also encodes the internal DEFAULT_PROJECT_ID_TOKEN ({{projectId}}).
That token is expected to remain unchanged until decorateRequest() calls replaceProjectIdToken() and substitutes the actual project ID.
As a result, clients relying on lazy project ID resolution / ADC — for example:
newBigQuery()
without an explicit projectId — may send the encoded literal:
%7B%7BprojectId%7D%7D
to the backend instead of the resolved project ID.
Regression
@google-cloud/common@8.0.1
request_()
→ URI: ".../projects/{{projectId}}/queries"
decorateRequest()
→ replaceProjectIdToken(uri, "my-project")
→ placeholder is found and replaced
BigQuery receives:
".../projects/my-project/queries" ✓
makeAuthenticatedRequest is assigned as an instance property, so it needs to be replaced after constructing the Service.
The following reproduction captures the URI passed to makeAuthenticatedRequest. This allows the behavior to be reproduced without depending on ADC credentials, network access, or a GCP environment.
One option would be to preserve DEFAULT_PROJECT_ID_TOKEN while encoding URI components.
The token is an internal symbolic placeholder rather than a concrete resource ID, and still needs to be visible to replaceProjectIdToken() later in the request lifecycle.
Alternatively, replaceProjectIdToken() in @google-cloud/projectify could recognize both:
{{projectId}}
and:
%7B%7BprojectId%7D%7D
However, that would make project substitution aware of URI-encoding behavior from another layer.
Preserving the placeholder before request decoration therefore seems preferable.
Confirming this end to end against the live BigQuery API, and confirming that #9315 fixes it.
Setup:@google-cloud/bigquery 9.1.0 with @google-cloud/common 8.1.0 (its build/src is identical to 8.0.2, so both are affected), @google-cloud/projectify 6.1.0, Node 24, Application Default Credentials.
Result without projectId: HTTP 400 from jobs.insert:
Value <my-project> in content does not agree with value {{projectId}}. This can happen when a value set through a parameter is inconsistent with a value set in the request.
The request body carries the resolved project (jobReference.projectId), the URL path still carries the encoded placeholder. With projectId passed to the constructor the same call succeeds. For jobs.insert the symptom is this 400 rather than the 404 seen on queries, which may help people searching for the error text.
With the change from #9315 applied to the installed build/src/util.js (the DEFAULT_PROJECT_ID_TOKEN bypass in joinURIComponents()), the same project-less call succeeds against the live API: createQueryJob returns a job in the resolved project. No other change was needed.
In our case this reached production because a Renovate-driven bump moved @google-cloud/bigquery from 8.3.1 (common 6) straight to 9.1.0: the API surface was unchanged and a mocked test suite stayed green, so nothing flagged the regression until real requests failed. An explicit projectId is a complete workaround.
Activity
[-]@google-cloud/common@8.0.2 security patch breaks ADC project ID detection — joinURIComponents() encodes DEFAULT_PROJECT_ID_TOKEN before replaceProjectIdToken() runs[/-][+]@google-cloud/common@8.0.2 security patch breaks ADC project ID detection — joinURIComponents() encodes `DEFAULT_PROJECT_ID_TOKEN` before` replaceProjectIdToken()` runs[/+]jt274 commentedon Sep 10, 2026
This should be a very high priority issue since it breaks ALL BigQuery operations.
fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents
fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents
fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents
fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents
fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents
TorbenWetter commentedon Oct 1, 2026
Confirming this end to end against the live BigQuery API, and confirming that #9315 fixes it.
Setup:
@google-cloud/bigquery9.1.0 with@google-cloud/common8.1.0 (itsbuild/srcis identical to 8.0.2, so both are affected),@google-cloud/projectify6.1.0, Node 24, Application Default Credentials.Result without
projectId: HTTP 400 fromjobs.insert:The request body carries the resolved project (
jobReference.projectId), the URL path still carries the encoded placeholder. WithprojectIdpassed to the constructor the same call succeeds. Forjobs.insertthe symptom is this 400 rather than the 404 seen onqueries, which may help people searching for the error text.With the change from #9315 applied to the installed
build/src/util.js(theDEFAULT_PROJECT_ID_TOKENbypass injoinURIComponents()), the same project-less call succeeds against the live API:createQueryJobreturns a job in the resolved project. No other change was needed.In our case this reached production because a Renovate-driven bump moved
@google-cloud/bigqueryfrom 8.3.1 (common 6) straight to 9.1.0: the API surface was unchanged and a mocked test suite stayed green, so nothing flagged the regression until real requests failed. An explicitprojectIdis a complete workaround.fix(common): preserve DEFAULT_PROJECT_ID_TOKEN in joinURIComponents