Severity
High — SSRF / open redirect
Description
src/services/ipfs.ts constructs a gatewayUrl by directly interpolating the PINATA_GATEWAY environment variable into the response. If this variable is misconfigured (typo, wrong scheme) or an attacker achieves control over the environment (misconfigured CI secrets, container env injection), clients that automatically follow the returned URL are redirected to an arbitrary host, enabling server-side request forgery or phishing.
Code Evidence
```typescript
// src/services/ipfs.ts:24-25
const gatewayUrl = ${PINATA_GATEWAY}/ipfs/${cid};
return { cid, gatewayUrl };
```
PINATA_GATEWAY is read verbatim with no validation:
```typescript
// src/services/ipfs.ts:5
const PINATA_GATEWAY = process.env.PINATA_GATEWAY ?? "https://gateway.pinata.cloud";
```
Example misconfiguration that turns the response into an open redirect:
```
PINATA_GATEWAY=http://attacker.com/steal?x=
→ gatewayUrl: "http://attacker.com/steal?x=/ipfs/QmXxx"
```
Frontend clients that auto-load the gatewayUrl to display a waveform preview would fetch attacker-controlled content.
Impact
- Clients automatically fetching the
gatewayUrl are directed to attacker infrastructure.
- If the backend itself ever uses
gatewayUrl for a server-side fetch (e.g. preview generation), this becomes a classic SSRF — the attacker controls the URL the server fetches, allowing internal network scanning.
- An injected gateway URL could serve malicious audio files branded as Crate content.
Fix
Validate PINATA_GATEWAY at startup against an allowlist of known IPFS gateway hostnames:
```typescript
const ALLOWED_GATEWAY_HOSTS = new Set([
"gateway.pinata.cloud",
"ipfs.io",
"cloudflare-ipfs.com",
]);
const PINATA_GATEWAY = (() => {
const raw = process.env.PINATA_GATEWAY ?? "https://gateway.pinata.cloud";
const { hostname } = new URL(raw); // throws on malformed URL — caught at startup
if (!ALLOWED_GATEWAY_HOSTS.has(hostname)) {
throw new Error(PINATA_GATEWAY hostname "${hostname}" is not in the allowlist);
}
return raw.replace(//$/, "");
})();
```
This causes the process to fail fast at startup rather than serving poisoned URLs silently.
Files Affected
src/services/ipfs.ts (lines 5, 24-25)
Severity
High — SSRF / open redirect
Description
src/services/ipfs.tsconstructs agatewayUrlby directly interpolating thePINATA_GATEWAYenvironment variable into the response. If this variable is misconfigured (typo, wrong scheme) or an attacker achieves control over the environment (misconfigured CI secrets, container env injection), clients that automatically follow the returned URL are redirected to an arbitrary host, enabling server-side request forgery or phishing.Code Evidence
```typescript
// src/services/ipfs.ts:24-25
const gatewayUrl =
${PINATA_GATEWAY}/ipfs/${cid};return { cid, gatewayUrl };
```
PINATA_GATEWAYis read verbatim with no validation:```typescript
// src/services/ipfs.ts:5
const PINATA_GATEWAY = process.env.PINATA_GATEWAY ?? "https://gateway.pinata.cloud";
```
Example misconfiguration that turns the response into an open redirect:
```
PINATA_GATEWAY=http://attacker.com/steal?x=
→ gatewayUrl: "http://attacker.com/steal?x=/ipfs/QmXxx"
```
Frontend clients that auto-load the
gatewayUrlto display a waveform preview would fetch attacker-controlled content.Impact
gatewayUrlare directed to attacker infrastructure.gatewayUrlfor a server-side fetch (e.g. preview generation), this becomes a classic SSRF — the attacker controls the URL the server fetches, allowing internal network scanning.Fix
Validate
PINATA_GATEWAYat startup against an allowlist of known IPFS gateway hostnames:```typescript
const ALLOWED_GATEWAY_HOSTS = new Set([
"gateway.pinata.cloud",
"ipfs.io",
"cloudflare-ipfs.com",
]);
const PINATA_GATEWAY = (() => {
const raw = process.env.PINATA_GATEWAY ?? "https://gateway.pinata.cloud";
const { hostname } = new URL(raw); // throws on malformed URL — caught at startup
if (!ALLOWED_GATEWAY_HOSTS.has(hostname)) {
throw new Error(
PINATA_GATEWAY hostname "${hostname}" is not in the allowlist);}
return raw.replace(//$/, "");
})();
```
This causes the process to fail fast at startup rather than serving poisoned URLs silently.
Files Affected
src/services/ipfs.ts(lines 5, 24-25)