Tier 2 per SECURITY.md — a compatibility-affecting change; needs maintainer approval before merge. Surfaced by the security review behind #39.
Problem
PathSegments.encode (PathSegments.java:24) deliberately preserves / as a separator and URLEncoder leaves . unencoded, so .. passes through intact. buildUri writes the path verbatim and URI.create does not normalize dot-segments (HttpTransport.java:365). Strict single-segment symbols have no character validation.
An application that forwards untrusted end-user ticker input into a symbol path lets that end-user inject extra path segments or dot-segments, e.g. stocks().quote(StockQuoteRequest.of("../../user")) → …/v1/stocks/quotes/../../user/, which a server/proxy may resolve to a different endpoint — served with the application's own token.
Blast radius is bounded: the authority can't be changed (no SSRF), and .. can only strip path segments — so this is same-host, same-credentials path confusion, not remote code/host control. The risk is specifically the untrusted-symbol passthrough pattern.
Proposed fix (needs approval — Tier 2)
Add a strict single-segment encoder for symbol endpoints that rejects (or percent-encodes) / and rejects ./..-only segments, while keeping the current slash-preserving PathSegments.encode only for the free-form options/lookup/{userInput} route (which legitimately matches across slashes). Alternatively validate symbols against an allowed character set at build() time.
Why Tier 2
Tightening symbol validation could reject inputs the SDK currently accepts — a behavior change for existing callers.
Tier 2 per
SECURITY.md— a compatibility-affecting change; needs maintainer approval before merge. Surfaced by the security review behind #39.Problem
PathSegments.encode(PathSegments.java:24) deliberately preserves/as a separator andURLEncoderleaves.unencoded, so..passes through intact.buildUriwrites the path verbatim andURI.createdoes not normalize dot-segments (HttpTransport.java:365). Strict single-segment symbols have no character validation.An application that forwards untrusted end-user ticker input into a symbol path lets that end-user inject extra path segments or dot-segments, e.g.
stocks().quote(StockQuoteRequest.of("../../user"))→…/v1/stocks/quotes/../../user/, which a server/proxy may resolve to a different endpoint — served with the application's own token.Blast radius is bounded: the authority can't be changed (no SSRF), and
..can only strip path segments — so this is same-host, same-credentials path confusion, not remote code/host control. The risk is specifically the untrusted-symbol passthrough pattern.Proposed fix (needs approval — Tier 2)
Add a strict single-segment encoder for symbol endpoints that rejects (or percent-encodes)
/and rejects./..-only segments, while keeping the current slash-preservingPathSegments.encodeonly for the free-formoptions/lookup/{userInput}route (which legitimately matches across slashes). Alternatively validate symbols against an allowed character set atbuild()time.Why Tier 2
Tightening symbol validation could reject inputs the SDK currently accepts — a behavior change for existing callers.