Skip to content

bug: PINATA_GATEWAY env var reflected into API responses without validation — open redirect / SSRF #14

Description

@brightpixel-dev

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions