oauth2: tighten regression tests for spurious-success decrypt fix#44682
Closed
Copilot wants to merge 2 commits into
Closed
oauth2: tighten regression tests for spurious-success decrypt fix#44682Copilot wants to merge 2 commits into
Copilot wants to merge 2 commits into
Conversation
- Match unique error message 'plaintext is not a valid header value' instead of
generic 'failed to decrypt token' prefix in both DecryptTokenSpuriousSuccessReturnsOriginalInput
and GarbagePlaintextCookieDoesNotCrash tests
- Add ASSERT_TRUE(cookies.contains('RefreshToken')) before cookies.at() in
GarbagePlaintextCookieDoesNotCrash to avoid out_of_range on cookie drop
- Add EXPECT_CALL for 302 redirect in GarbagePlaintextCookieDoesNotCrash using
Truly() lambda checking Status=='302' and Location non-empty
Agent-Logs-Url: https://github.com/envoyproxy/envoy/sessions/5d01f403-a691-47e4-8316-e8f2b7d29d5d
Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Update regression tests for OAuth2 filter
oauth2: tighten regression tests for spurious-success decrypt fix
Apr 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The two regression tests added for the AES-CBC spurious-success crash fix were asserting on
"failed to decrypt token"— a prefix shared with the pre-existingEVP_DecryptFinal_exfailure branch — so they would pass even if the newheaderValueIsValidguard were regressed away.Changes
DecryptTokenSpuriousSuccessReturnsOriginalInput: NarrowEXPECT_LOG_CONTAINSto"plaintext is not a valid header value", which is unique to the new branch (decrypt_result.error.value_or("plaintext is not a valid header value")). A revert of the fix hits the old path and emits a different message, failing this test.GarbagePlaintextCookieDoesNotCrash:cookies.at("RefreshToken")withASSERT_TRUE(cookies.contains("RefreshToken"))+EXPECT_EQ(...)so a dropped cookie fails clearly rather than throwingout_of_range.EXPECT_CALLondecoder_callbacks_.encodeHeaders_to assert the redirect actually fires:Status == "302"andLocationnon-empty; avoids matching Set-Cookie/nonce/CSRF values that would make the assertion brittle.DecryptTokenEmpty,DecryptTokenSameSecret, andDecryptTokenDecryptionFailsare unchanged — they provide the only direct unit-test coverage offilter_->decryptToken/encryptToken.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
dl.google.com/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)ftpmirror.gnu.org/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)mirror.bazel.build/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)pkgconfig.freedesktop.org/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
Tighten the two regression tests added in PR #44677 (
test/extensions/filters/http/oauth2/filter_test.cc) so they specifically verify the new fix path and not the pre-existing decrypt-failure path. KeepDecryptTokenEmptyandDecryptTokenSameSecretas-is — they cover the only direct unit-test coverage offilter_->decryptToken/filter_->encryptToken.Required changes (only to the two tests below — do not change anything else)
1.
DecryptTokenSpuriousSuccessReturnsOriginalInputCurrently asserts on the generic prefix
"failed to decrypt token"which is shared with the pre-existingEVP_DecryptFinal_ex-failure branch. Change theEXPECT_LOG_CONTAINSto match on the message that is unique to the new branch:That string comes from the
decrypt_result.error.value_or("plaintext is not a valid header value")insource/extensions/filters/http/oauth2/filter.cc. Matching on it ensures this test only passes when the newheaderValueIsValidbranch fires — a regression that re-introduced the crash via the old error path would emit a different message and fail this test.2.
GarbagePlaintextCookieDoesNotCrashApply three changes:
Tighten the log assertion the same way as above: match
"plaintext is not a valid header value"instead of"failed to decrypt token".Defensive cookie lookup: replace the bare
cookies.at("RefreshToken")withASSERT_TRUE(cookies.contains("RefreshToken"))followed byEXPECT_EQ(cookies.at("RefreshToken"), garbage_ciphertext);so the test fails clearly (rather than throwingout_of_range) if the cookie were dropped instead of preserved.Assert the redirect actually happened: add an expectation that
decoder_callbacks_.encodeHeaders_is called once with a 302 response. Look at the existing testRedirectToOAuthServerWithInvalidCSRFTokenin the same file for the established pattern (usesEXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&response_headers), true));).Do NOT match the full response header map — that would be very brittle (Set-Cookie values, Location with random nonce/csrf, etc.). Instead, use a custom matcher (or a
Truly(...)lambda) that only checksheaders.Status()is"302"andheaders.Location()is non-null. The intent is "filter took the redirect path rather than crashing or 401-ing", nothing more. If a simple_match is the only realistic option without significant test infrastructure work, that's acceptable too — but document why in a comment.Note:
redirectToOAuthServercurrently callsdecoder_callbacks_->encodeHeaderswithend_stream=true, so the matcher's second arg should betrue.Things NOT to change
source/extensions/filters/http/oauth2/filter.cc.changelogs/current.yaml.DecryptTokenEmpty,DecryptTokenSameSecret, orDecryptTokenDecryptionFails. They cover branches that have no other direct unit-test coverage (verified via lexical search — there are no other callers offilter_->decryptToken/filter_->encryptTokenintest/extensions/filters/http/oauth2/).Verification
Build and run only the affected test target:
Both
DecryptTokenSpuriousSuccessReturnsOriginalInputandGarbagePlaintextCookieDoesNotCrashmust pass against the existing fix infilter.cc. As a sanity-check that the assertions are actually tighter, you can mentally (or via a temporary local revert) confirm: iffilter.ccwere reverted so the new branch did not exist and the oldEVP_DecryptFinal_exfailure path were hit instead, the new log-message assertion would fail. Do not commit that revert.The following is the prior conversation context from the user's chat exploration (may be truncated):
User: trying to track down a flake in oauth2 tests that are hard to repro (requires full test suite and doesnt always repro even with x100)
so - probs with this pr bigger q is - is it a real "bug", does this fix it, are all these tests necessary, and do they test correctly
Assistant: Let me also quickly check the
encryptTokenaccessor (test callsfilter_->encryptToken) and existing tests to see if these new tests overlap with existing coverage:Assistant: # Review of PR #44677 —
oauth2: fix crash in decryptToken on spurious AES-CBC PKCS#7 successTL;DR
HeaderUtility::headerValueIsValid) thatHeaderString::assertValid()uses inte...This pull request was created from Copilot chat.