fix: defer SignatureVerifier construction so Socket Mode apps init without a signing secret#1541
Conversation
…thout a signing secret slack_sdk>=3.43.0 validates the signing secret when a SignatureVerifier is constructed, raising "ValueError: signing_secret must not be empty." App.__init__ eagerly builds the RequestVerification middleware (and thus a SignatureVerifier) for every app, including Socket Mode apps that have no signing secret, so those apps now fail to initialize. Construct the SignatureVerifier lazily on first use instead. Request verification is already skipped for Socket Mode requests, so the verifier is never built for them. HTTP requests still require a valid signing secret as before. Fixes #1535 Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1541 +/- ##
=======================================
Coverage 91.37% 91.37%
=======================================
Files 228 228
Lines 7279 7285 +6
=======================================
+ Hits 6651 6657 +6
Misses 628 628 ☔ View full report in Codecov by Harness. |
Add sync and async tests confirming that request verification still raises for an HTTP request when the signing secret is empty, so the lazy verifier cannot be weakened into silently accepting unverified requests. Drop the now-redundant explanatory comments. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
|
HTTP-mode verification — confirming the fix preserves the empty-secret guard Tested the patched build in HTTP mode ( For Socket Mode (the original #1535 report), the verifier is never constructed and the app starts cleanly. ✅ |
|
HTTP-mode verification — with The complement to the previous comment: same HTTP setup, but with a valid signing secret configured. The full middleware chain applies cleanly and the verifier builds without error — no regression to HTTP request verification: |
|
Socket Mode verification — the original #1535 case Confirming Socket Mode ( |
WilliamBergamin
left a comment
There was a problem hiding this comment.
Left a minor comment on the comment but I think this is good to ship 💯 🚀
| def test_http_request_with_empty_signing_secret_raises(self): | ||
| middleware = RequestVerification(signing_secret="") | ||
| req = BoltRequest(body="payload={}", headers={}) | ||
| resp = BoltResponse(status=404) | ||
| with pytest.raises(ValueError): | ||
| middleware.process(req=req, resp=resp, next=next) |
| def test_socket_mode_request_skips_verification_without_signing_secret(self): | ||
| middleware = RequestVerification(signing_secret="") | ||
| req = BoltRequest(mode="socket_mode", body="payload={}", headers={}) | ||
| resp = BoltResponse(status=404, body="default") | ||
| resp = middleware.process(req=req, resp=resp, next=next) | ||
| assert resp.status == 200 | ||
| assert resp.body == "next" |
Co-authored-by: William Bergamin <wbergamin@salesforce.com>
|
@WilliamBergamin Immense thanks for the help getting this out - let's merge for a release🚢 💨 |
|
@zimeg, is it now mandatory to pass in the 2nd argument |
Summary
This pull request fixes a regression where a Socket Mode app fails to initialize with
ValueError: signing_secret must not be empty.when running onslack_sdk>=3.43.0.slack_sdk3.43.0 madeSignatureVerifier.signing_secreta validated property whose setter rejects an empty/whitespace secret on construction (it was a plain, unvalidated attribute in 3.42.0).App.__init__eagerly builds theRequestVerificationmiddleware — and therefore aSignatureVerifier— for every app, including Socket Mode apps that legitimately have no signing secret, so initialization now blows up.SignatureVerifierlazily on first use. Request verification is already skipped for Socket Mode requests (_can_skip), so the verifier is never built for them; the once-per-app construction is memoized.AsyncRequestVerificationinherits this__init__, so both sync and async paths are covered by the single change.Fixes #1535
Testing
This is an init-time regression that only reproduces against
slack_sdk>=3.43.0(the version range bolt-python already allows; CI may resolve an earlier patch). To reproduce and verify manually:slack_sdk==3.43.0.SocketModeHandlerconnects and handles events normally.401.Category
slack_bolt.Appand/or its core componentsslack_bolt.async_app.AsyncAppand/or its core componentsslack_bolt.adapter/docsRequirements
./scripts/install_all_and_run_tests.shafter making the changes.