fix: never crash on invalid noProxyAddresses entries - #1825
Conversation
An invalid noProxyAddresses entry (e.g. a glob-style '*.example.com', which is not valid Java regex) threw an uncaught PatternSyntaxException from String.matches() at both MQTT proxy-bypass call sites, killing MQTT connectivity for the device. - Add ProxyUtils.noProxyMatches(): regex semantics preserved, but entries are trimmed before matching (previously a space-padded entry from a comma-space separated list could never match), a null/empty endpoint or blank entry never matches, and an uncompilable entry is logged and treated as a non-match instead of throwing. - Route the MqttClient and StandaloneMqttConnector bypass checks through it. - Add ProxyUtils.validateNoProxyAddresses() and reject deployments early in BootstrapManager when an entry contains whitespace or does not compile, so operators get a clear deployment-time error instead of a runtime crash. Empty segments from stray commas are skipped, matching the runtime matcher's tolerance. A device already carrying an invalid entry can still recover: a deployment with a corrected value passes validation. Wildcard (glob) support is intentionally out of scope for this change and will follow separately.
| continue; | ||
| } | ||
| try { | ||
| Pattern.compile(trimmed); |
There was a problem hiding this comment.
Recommendation generated by Amazon CodeGuru Reviewer. Leave feedback on this recommendation by replying to the comment or by reacting to the comment using emoji.
When using regular expressions (regex) in Java, it's best practice to first compile your regex pattern separately instead of using pattern matching methods directly. By compiling first, you can reuse the same Pattern instance repeatedly without having to recompile.
There was a problem hiding this comment.
Agreed in principle, but leaving as-is for this PR: this path only runs during MQTT connection setup against a small, comma-separated config list, so recompilation cost is negligible, and caching compiled Patterns would add static state for little gain. A follow-up PR (glob wildcard support for noProxyAddresses) restructures this exact code around a shared entry-translation helper — that's the right place to revisit pattern reuse if it matters.
|
Unit Tests Coverage Report
Minimum allowed coverage is Generated by 🐒 cobertura-action against a808c3d |
|
Integration Tests Coverage Report
Minimum allowed coverage is Generated by 🐒 cobertura-action against a808c3d |
Issue #, if available: Related: #1809 (this PR carves out the crash-safety portion; glob/wildcard support will follow separately)
Description of changes:
An invalid
noProxyAddressesentry — e.g. the glob-style*.example.com, which is not valid Java regex — threw an uncaughtPatternSyntaxException("Dangling meta character '*'") fromString.matches()at both MQTT proxy-bypass call sites, killing MQTT connectivity for the device.This change makes noProxy handling crash-safe without changing the documented regex semantics:
ProxyUtils.noProxyMatches(endpoint, pattern)(new): regex semantics preserved, butWARN) and treated as a non-match instead of throwing.MqttClientandStandaloneMqttConnectorbypass checks now route through it.ProxyUtils.validateNoProxyAddresses()(new) + wiring inBootstrapManager.networkProxyHasChanged: deployments carrying anetworkProxysection are rejected early with a clearComponentConfigurationValidationExceptionnaming the offending entries when an entry contains whitespace or does not compile — instead of a runtime crash (uncompilable) or silent no-match. Empty segments from stray commas (a.com,,b.com) are skipped, matching the runtime matcher's tolerance.Why is this change necessary:
Users naturally write glob-style entries like
*.sts.amazon.com(the convention every other NO_PROXY implementation uses). Today that config crashes MQTT connection setup entirely — a config mistake should degrade to "entry doesn't match" plus a clear deployment-time error, never loss of connectivity. Crash safety is split out from wildcard support so this fix can land independently; glob semantics need a wider change (the SDK HTTP path ingetProxyConfiguration()passes raw patterns tononProxyHosts(), which also does raw regex matching) and will come as a follow-up.Recovery note: a device already carrying an invalid entry is not deadlocked by the new validation — a deployment with a corrected value passes validation and applies.
How was this change tested:
11 new unit tests: 9 in
ProxyUtilsTest(regex behavior preserved, invalid pattern no-throw, null/empty endpoint, blank entries, trim, validation accept/skip/reject paths) and 2 inBootstrapManagerTest(invalid entry → deployment rejected with the entry named in the message; valid entries with stray commas pass validation). Full runs ofProxyUtilsTest(24),BootstrapManagerTest(24),MqttClientTest(101),StandaloneMqttConnectorTest(16) — all pass. Checkstyle and PMD (main + tests) clean locally.Any additional information or context required to review the change:
Validation strictness deliberately mirrors runtime tolerance: whatever the matcher silently skips (blank/stray-comma segments) is also accepted by validation; whatever the matcher cannot ever match (uncompilable, embedded whitespace) is rejected at deployment time. Validation only runs when a deployment carries a
networkProxysection; pre-existing bad config in the tlog is covered by the runtime no-throw guard.Documentation Checklist:
Compatibility Checklist:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.