slack-go/slack v0.30.1 was published on October 4, 2026. It is a security release: GetFile, GetFileContext and UploadToURL now refuse to send the Slack token to hosts that are not Slack. If your pipeline downloads files referenced in messages or events, this is the release to plan for.
The full release notes and downloads are on the GitHub release page. This is a stable release, not a prerelease.
What was wrong ¶
Slack lets a message reference a remote or external file. For those files, File.IsExternal is true, and the url_private field points outside Slack. That is the host the file actually lives on.
The common ingestion pattern is simple. An event handler receives a file object and calls GetFile(file.URLPrivate, w). Before this release, the client attached the token to that request no matter where the URL pointed. For an external file, the token went to whatever host the sender chose.
The trigger is a user, or an integration, attaching an external file whose URL they control. The blast radius is every deployment that forwards url_private straight into GetFile without checking the host. The exposed credential is the token the client was built with, which for a bot is often broad. The project tracks this as GHSA-3q3v-34v2-g88f. The release notes credit the reporter, @Lordseriouspig.
The new allow list ¶
The token is now sent only to:
- https URLs on
slack.comand its subdomains - https URLs on
slack-gov.comand its subdomains - the host set with
OptionAPIURL
Any other URL returns an error before a request is made. That ordering matters. The check happens client side, so nothing leaves the process for a rejected host and no token is exposed in a failed attempt.
The same rule covers GetFile, GetFileContext and UploadToURL. If you wrapped these calls in your own helper, the helper inherits the behavior.
What breaks for operators ¶
The tradeoff is explicit. Code that used GetFile to fetch external files with a token attached will now get an error. That is the intended outcome, but it will show up as a failed job in an ingestion path that used to work.
If you really need the content of an external file, fetch it with a plain HTTP client that carries no Slack credentials. Check the host first, and apply your own limits on size and destination. The release notes do not prescribe this. It follows from the fix, since the client no longer makes that request for you.
Check File.IsExternal before calling GetFile. Treat external files as untrusted input, the same way you would treat any URL from a user.
Test changes ¶
Tests are the other place this will bite. A test that points GetFile at an httptest server now fails, because the server host is not on the allow list. The server has to be passed to OptionAPIURL as well. The release notes give this example:
api := slack.New("xoxb-test", slack.OptionAPIURL(ts.URL+"/"))
err := api.GetFile(ts.URL+"/files-pri/T1-F1/a.txt", &buf)
Note the trailing slash on the API URL. Existing fixtures that build the client with slack.New and a bare test server URL will need the same edit. Expect a small, mechanical diff across test files.
Upgrade notes ¶
- This is a patch release on top of v0.30.0, and the compare view is at v0.30.0…v0.30.1.
- Search your code for
GetFile(,GetFileContext(andUploadToURL(. Any call that receives a URL derived from message or event data is in scope. - Fix failing tests by adding
OptionAPIURLthat points at the test server. - Rotate tokens if a past deployment could have fetched attacker supplied external file URLs. The release notes do not say whether exploitation was seen, so treat that as a decision for your own threat model.
- Details are also in the CHANGELOG at the release tag.
Where to get it ¶
- Release page: https://github.com/slack-go/slack/releases/tag/v0.30.1
- Repository: https://github.com/slack-go/slack
- Tag:
v0.30.1