Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.2.2 — 2026-10-30

Fixes the Shotstack credential in n8n's HTTP Request node. With the credential
picked there, calls to api.shotstack.io (such as the Ingest API) went out without
the API key and failed with "Missing API key". The key still only goes to
api.shotstack.io.

## 0.2.1 — 2026-10-07

Adds search words, so n8n's Nodes panel finds Shotstack when people search for
Expand Down
5 changes: 4 additions & 1 deletion credentials/ShotstackApi.credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ export class ShotstackApi implements ICredentialType {
// relative url like //evil.example.com/x is absolute to axios but not to
// /^https?:\/\//, so that test fell through to baseURL, saw Shotstack and
// attached the key to a request axios then sent to evil.example.com.
const url = String(requestOptions.url ?? '');
//
// n8n's HTTP Request node still goes through the legacy request helper,
// which names the address uri, so read that too or the key never goes.
const url = String(requestOptions.url ?? (requestOptions as { uri?: string }).uri ?? '');
const target = /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
? url
: String(requestOptions.baseURL ?? '');
Expand Down
3 changes: 3 additions & 0 deletions test/credential-host-scope.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const cases = [
false,
],
['protocol relative url with no baseURL', { baseURL: '', url: '//evil.example.com/x.mp4' }, false],
// n8n's HTTP Request node, with this credential picked, passes uri, not url.
['HTTP Request node to the Ingest API', { uri: 'https://api.shotstack.io/ingest/v1/sources' }, true],
['HTTP Request node to a third party', { uri: 'https://evil.example.com/collect.mp4' }, false],
// The same rule must not stop the key reaching a genuine relative call.
['a relative path on the Edit API', { baseURL: 'https://api.shotstack.io/edit/stage', url: '/render' }, true],
];
Expand Down
Loading