543 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Security Audit Report — app.closebot.com
**Date:** February 7, 2026
**Auditor:** Clawdbot Security Scanner
**Scope:** app.closebot.com, api.closebot.com, closebot.com
**Authorization:** Fully authorized pentest by site owner (Jake Shore)
---
## 1. Executive Summary
### Severity Matrix
| Severity | Count | Findings |
|----------|-------|----------|
| 🔴 **CRITICAL** | 1 | API CORS wildcard `Access-Control-Allow-Origin: *` on authenticated endpoints |
| 🟠 **HIGH** | 3 | Missing security headers on API, Azure infrastructure info leak, No rate limiting on API |
| 🟡 **MEDIUM** | 4 | WordPress readme/license exposed, NEXT_LOCALE cookie lacks Secure flag, API Azure AppId leak, /bot endpoint method disclosure |
| 🔵 **LOW** | 3 | WordPress version exposed, Clerk auth status header leak, Build ID exposed in 404 pages |
| **INFO** | 6 | Tech stack details, positive findings |
### Overall Risk Rating: **HIGH**
The most critical finding is that **api.closebot.com has `Access-Control-Allow-Origin: *` on ALL endpoints**, including authenticated ones like `/bot`, `/bot/list`, `/bot/create`, `/bot/config`, `/bot/settings`, `/lead`, `/agency`. This is the same class of vulnerability found in SuperFunnels. While `Access-Control-Allow-Credentials` is NOT set (which prevents cookie-based CSRF), any token-based auth (Bearer tokens) sent from JS is still vulnerable to being used in cross-origin attacks if tokens are predictable or leaked.
---
## 2. Tech Stack
| Component | Technology | Details |
|-----------|-----------|---------|
| **Frontend (app)** | Next.js (App Router) | Build ID: `SJe3XKo4eqvdUfxjtlLi9`, deployment: `dpl_9XCbPqSSm7KFrRoZoDtTN7Cu7QhM` |
| **Frontend Hosting** | Vercel | IAD1 region (us-east-1), Vercel Security Checkpoint enabled |
| **Auth Provider** | Clerk | Headers: `x-clerk-auth-status`, `x-clerk-auth-reason` |
| **API Backend** | ASP.NET (Kestrel) | Running on Azure App Service |
| **API Hosting** | Azure App Service | `cb-api-zarqcgo3sph6q.azurewebsites.net` (West US 2) |
| **Marketing Site** | WordPress 6.9.1 | Hosted on Kinsta, behind Cloudflare |
| **CDN (marketing)** | Cloudflare | CF-Ray headers present |
| **DNS** | GoDaddy | `ns77.domaincontrol.com`, `ns78.domaincontrol.com` |
| **SSL** | Let's Encrypt (R13) | Valid Feb 5 May 6, 2026 |
| **i18n** | Multi-language | EN, ES, PT, NL supported |
### Subdomain Map
| Subdomain | Status | Resolves To |
|-----------|--------|-------------|
| `app.closebot.com` | ✅ Active | Vercel (`592229a97db57f91.vercel-dns-017.com`) |
| `api.closebot.com` | ✅ Active | Azure (`cb-api-zarqcgo3sph6q.azurewebsites.net``20.115.232.12`) |
| `www.closebot.com` | ✅ Redirect | → `closebot.com` (Cloudflare `162.159.134.42`) |
| `closebot.com` | ✅ Active | Cloudflare/Kinsta WordPress |
| `admin.closebot.com` | ❌ No DNS | - |
| `dashboard.closebot.com` | ❌ No DNS | - |
| `ws.closebot.com` | ❌ No DNS | - |
| `mail.closebot.com` | ❌ No DNS | - |
| `staging.closebot.com` | ❌ No DNS | - |
| `dev.closebot.com` | ❌ No DNS | - |
### DNS Records
- **TXT:** Google site verification (`A_X4u_WKhr2Mp6maxNXC71DUBr-RlWzxCjrvyxnVrZo`), Microsoft verification (`MS=ms24389368`)
- **MX:** None configured (no email hosting on root domain)
- **NS:** GoDaddy (`ns77/ns78.domaincontrol.com`)
---
## 3. HTTP Security Headers
### app.closebot.com (Vercel/Next.js)
| Header | Status | Value |
|--------|--------|-------|
| `Strict-Transport-Security` | ✅ Present | `max-age=63072000` (~2 years) |
| `Content-Security-Policy` | ❌ **MISSING** | Not set |
| `X-Frame-Options` | ❌ **MISSING** | Not set |
| `X-Content-Type-Options` | ❌ **MISSING** | Not set |
| `X-XSS-Protection` | ❌ **MISSING** | Not set (deprecated, but still recommended) |
| `Referrer-Policy` | ❌ **MISSING** | Not set |
| `Permissions-Policy` | ❌ **MISSING** | Not set |
| `X-Powered-By` | ⚠️ Leaking | `Next.js` |
| `Server` | ⚠️ Leaking | `Vercel` |
**Severity: HIGH** — Missing CSP, X-Frame-Options, and X-Content-Type-Options on the frontend.
### api.closebot.com (Azure/Kestrel)
| Header | Status | Value |
|--------|--------|-------|
| `Strict-Transport-Security` | ❌ **MISSING** | Not set |
| `Content-Security-Policy` | ❌ **MISSING** | Not set |
| `X-Frame-Options` | ❌ **MISSING** | Not set |
| `X-Content-Type-Options` | ❌ **MISSING** | Not set |
| `X-XSS-Protection` | ❌ **MISSING** | Not set |
| `Referrer-Policy` | ❌ **MISSING** | Not set |
| `Permissions-Policy` | ❌ **MISSING** | Not set |
| `Server` | ⚠️ Leaking | `Kestrel` |
| `Request-Context` | ⚠️ Leaking | `appId=cid-v1:1593e7a7-a705-4f69-977e-49c3fa1d0aa3` |
| `x-ms-middleware-request-id` | ⚠️ Leaking | `00000000-0000-0000-0000-000000000000` |
**Severity: HIGH** — API has ZERO security headers. No HSTS, no CSP, nothing.
### closebot.com (WordPress/Cloudflare)
| Header | Status | Value |
|--------|--------|-------|
| `X-Content-Type-Options` | ✅ Present | `nosniff` |
| `Strict-Transport-Security` | ❌ **MISSING** | Not set |
| `Content-Security-Policy` | ❌ **MISSING** | Not set |
| `X-Frame-Options` | ❌ **MISSING** | Not set |
| `Referrer-Policy` | ❌ **MISSING** | Not set |
| `Permissions-Policy` | ❌ **MISSING** | Not set |
---
## 4. CORS Analysis — 🔴 CRITICAL
### api.closebot.com — WILDCARD CORS ON ALL ENDPOINTS
This is the **#1 finding** of the entire audit.
| Endpoint | Origin Tested | ACAO Header | Result |
|----------|--------------|-------------|--------|
| `/` (root) | `https://evil.com` | `*` | 🔴 **OPEN** |
| `/` (root) | `null` | `*` | 🔴 **OPEN** |
| `/` (root) | `https://evil.closebot.com` | `*` | 🔴 **OPEN** |
| `/bot` | `https://evil.com` | `*` | 🔴 **OPEN** |
| `/bot` (OPTIONS) | `https://evil.com` | `*` | 🔴 **OPEN** |
| Preflight | Any | Allows `Authorization,Content-Type` | 🔴 **OPEN** |
**Key facts:**
- `Access-Control-Allow-Origin: *` is returned for ANY origin
- Preflight `OPTIONS` returns `Access-Control-Allow-Headers: Authorization,Content-Type` — meaning cross-origin JS can send auth headers
- `Access-Control-Allow-Credentials` is NOT set (mitigating cookie-based attacks)
- However, if the API uses Bearer tokens (JWT) passed via `Authorization` header, any malicious website can make authenticated API calls if it obtains the token
**Impact:**
- If a user visits a malicious site while logged into Closebot, and the malicious site can obtain/guess the auth token, it can make full API calls to read/modify bot data, leads, agency settings
- The preflight allows `Authorization` header, so even "complex" requests are permitted cross-origin
**Recommendation:** Replace `*` with an explicit allowlist: `https://app.closebot.com`, `https://closebot.com`
### app.closebot.com — No CORS headers on most responses
The frontend (Vercel/Next.js) does NOT return CORS headers on normal pages. The 404 page returns `Access-Control-Allow-Origin: *` but this is a static error page and lower risk.
---
## 5. Cookie/Session Analysis
### app.closebot.com Cookies
| Cookie | Secure | HttpOnly | SameSite | Domain | Notes |
|--------|--------|----------|----------|--------|-------|
| `NEXT_LOCALE` | ❌ No | ❌ No | `Lax` | `/` path | ⚠️ Language preference — missing Secure flag |
| Clerk session cookies | Not directly observed (behind Vercel checkpoint) | — | — | — | Clerk typically handles this well |
**Severity: MEDIUM**`NEXT_LOCALE` cookie is set without `Secure` flag, allowing it to be sent over HTTP if user visits `http://` URL. While HSTS mitigates this on the app domain, it's still a best practice violation.
### api.closebot.com Cookies
| Cookie | Secure | HttpOnly | SameSite | Domain | Notes |
|--------|--------|----------|----------|--------|-------|
| `TiPMix` | ✅ Yes | ✅ Yes | `None` | `.api.closebot.com` | Azure routing cookie |
| `x-ms-routing-name` | ✅ Yes | ✅ Yes | `None` | `.api.closebot.com` | Azure routing — value: `self` |
**Note:** `SameSite=None` on Azure routing cookies means they're sent cross-site. Combined with the CORS `*`, this is concerning — though these are infrastructure cookies, not auth tokens.
### closebot.com Cookies
| Cookie | Secure | HttpOnly | SameSite | Domain |
|--------|--------|----------|----------|--------|
| `__cf_bm` | ✅ Yes | ✅ Yes | `None` | `.closebot.com` |
Cloudflare bot management cookie — properly secured.
### Auth Mechanism
- **Clerk** is used for authentication (confirmed by `x-clerk-auth-status` and `x-clerk-auth-reason` headers)
- Unauthenticated requests get `x-clerk-auth-status: signed-out` and `x-clerk-auth-reason: session-token-and-uat-missing`
- Root `/` redirects to `/login?redirect_url=%2F` (307 redirect)
- `/register` exists and returns 200 — **open registration is available**
---
## 6. API/Endpoint Map
### app.closebot.com (Vercel/Next.js)
| Path | Status | Notes |
|------|--------|-------|
| `/` | 307 | Redirects to `/login` |
| `/login` | 200 | Login page (Clerk) |
| `/register` | 200 | Registration page (open signup) |
| `/signup` | 404 | Not used |
| `/pricing` | 403* | Protected (behind Vercel checkpoint after rate limit) |
| `/settings` | 403* | Protected |
| `/billing` | 403* | Protected |
| `/account` | 403* | Protected |
| `/bots` | 403* | Protected |
| `/conversations` | 403* | Protected |
| `/analytics` | 403* | Protected |
| `/docs` | 403* | Protected |
| `/.env` | 404 | ✅ Not exposed |
| `/.git` | 404 | ✅ Not exposed |
| `/robots.txt` | 404 | No robots.txt |
| `/sitemap.xml` | 404 | No sitemap |
| `/.well-known/security.txt` | 404 | No security.txt |
*403 responses are from Vercel Security Checkpoint (bot challenge), not actual authorization blocks.
### api.closebot.com (Azure/Kestrel)
| Path | Status | Methods | Notes |
|------|--------|---------|-------|
| `/bot` | 401/405 | GET, POST | **Core bot endpoint** — requires auth |
| `/bot/list` | 401 | — | List bots |
| `/bot/create` | 401 | — | Create bot |
| `/bot/all` | 401 | — | All bots |
| `/bot/settings` | 401 | — | Bot settings |
| `/bot/config` | 401 | — | Bot config |
| `/lead` | 401 | — | Lead management |
| `/agency` | 401 | — | Agency management |
| `/swagger` | 301 | — | Swagger redirect (leads to 404 — likely disabled in prod) |
| `/` | 404 | — | No root handler |
| All other paths | 404 | — | — |
**Severity: MEDIUM** — The `/bot` endpoint returns `Allow: GET, POST` in the 405 response, revealing accepted HTTP methods. The `/swagger` 301 redirect suggests Swagger UI was enabled at some point.
### closebot.com (WordPress)
| Path | Status | Notes |
|------|--------|-------|
| `/wp-admin` | 301 | Redirects to login — **exposed** |
| `/wp-login.php` | 200 | **Login page accessible** |
| `/wp-json` | 200 | REST API root — **accessible** |
| `/wp-json/wp/v2/users` | 401 | User enumeration blocked ✅ |
| `/.env` | 403 | Blocked ✅ |
| `/xmlrpc.php` | 403 | Blocked ✅ |
| `/wp-config.php` | 403 | Blocked ✅ |
| `/readme.html` | 200 | ⚠️ **Exposed** — WordPress readme |
| `/license.txt` | 200 | ⚠️ **Exposed** — WordPress license |
| `/feed/` | 200 | ⚠️ Exposes WordPress version `6.9.1` |
---
## 7. Client-Side Analysis
### Findings from HTML Source
1. **Vercel Security Checkpoint** — app.closebot.com serves a JS-based browser verification challenge (Astro framework) before allowing access. This is an effective bot protection layer.
2. **Next.js Build ID exposed**: `SJe3XKo4eqvdUfxjtlLi9` — visible in error pages and static chunk URLs. Low risk but provides deployment fingerprinting.
3. **Deployment ID exposed**: `dpl_9XCbPqSSm7KFrRoZoDtTN7Cu7QhM` — in chunk URLs.
4. **Internationalization**: Site supports EN, ES, PT, NL via `x-matched-path: /[locale]/login` routing.
5. **Clerk Auth Headers Leaked in Every Response**:
- `x-clerk-auth-status: signed-out`
- `x-clerk-auth-reason: session-token-and-uat-missing`
These headers confirm the auth provider and current auth state to any observer.
### Source Maps
- All `_next/static` resources are behind Vercel Security Checkpoint (return 403 challenge page to curl)
- Could not confirm/deny source map availability without browser access
- **Recommendation:** Ensure `.map` files are not deployed to production
### JS Bundles Analysis
- Could not analyze JS bundles directly due to Vercel Security Checkpoint blocking curl requests
- The checkpoint uses a Web Worker-based challenge system
- **Recommendation:** Verify no API keys, Firebase configs, or secrets are hardcoded in client bundles
---
## 8. Injection Test Results
### Host Header Injection
- **app.closebot.com**: ✅ **Protected** — Vercel returns 404 `DEPLOYMENT_NOT_FOUND` for invalid Host headers
- **X-Forwarded-Host**: ⚠️ Accepted without error (200 response) — Vercel passes it through to Next.js
### CRLF Injection
- **app.closebot.com**: ✅ **Not vulnerable** — URL-encoded `%0d%0a` is preserved in `Link` header as-is (not decoded), no header injection
### Path Traversal
- Standard path traversal payloads return 404 from Next.js catch-all router — **not vulnerable**
### SQL Injection / XSS
- Could not test input fields directly (behind Vercel Security Checkpoint)
- API endpoints return 401 without processing input — auth layer prevents unauthenticated injection testing
- **Recommendation:** Test authenticated injection scenarios during development
---
## 9. Rate Limiting Results
### app.closebot.com
| Endpoint | Requests | All Status Codes | Rate Limited? |
|----------|----------|-----------------|---------------|
| `/login` | 50 rapid | All `200` | 🔴 **NO** |
After approximately 50+ requests, Vercel Security Checkpoint started returning 403 challenges — this is Vercel's built-in protection, not application-level rate limiting.
**Note:** Vercel's checkpoint eventually kicked in (HTTP 403 with `x-vercel-mitigated: challenge`), providing some protection, but this is infrastructure-level, not application-level rate limiting.
### api.closebot.com
| Endpoint | Requests | All Status Codes | Rate Limited? |
|----------|----------|-----------------|---------------|
| `/` | 50 rapid | All `404` | 🔴 **NO** |
**Severity: HIGH** — No rate limiting on the API. This means:
- Brute-force attacks on auth tokens are possible
- API abuse/scraping is unrestricted
- DDoS amplification risk
**Recommendation:** Implement rate limiting (e.g., Azure API Management, custom middleware, or Cloudflare in front of the API).
---
## 10. Auth/Firebase Analysis
### Authentication System: Clerk
- **Provider**: Clerk (not Firebase)
- **Open Registration**: Yes — `/register` returns 200
- **Login**: `/login` with redirect support
- **Auth tokens**: Likely JWT via Clerk (standard Clerk flow)
- **Session management**: Clerk handles sessions via `__session` cookie and/or Bearer tokens
### No Firebase Found
- `/__/firebase/init.json` → 404
- No Firebase references detected in accessible HTML/JS
- Not applicable for Firebase-specific testing
---
## 11. Third-Party Risk
### External Scripts (from HTML source)
Due to Vercel Security Checkpoint, detailed JS bundle analysis was limited. From what was visible:
1. **Clerk** — Authentication provider (trusted, SOC 2 compliant)
2. **Next.js** — React framework (trusted)
3. **Vercel** — Hosting platform (trusted)
### WordPress Third-Party
- **Cloudflare** — CDN and bot protection
- **Kinsta** — WordPress hosting
### SRI (Subresource Integrity)
- Could not verify SRI on JS bundles due to Vercel checkpoint
- **Recommendation:** Ensure all third-party scripts have SRI hashes
---
## 12. Infrastructure Notes
### Origin IP Exposure
| Domain | Behind CDN? | Origin Exposed? |
|--------|-------------|-----------------|
| `app.closebot.com` | Vercel Edge | ✅ Protected (Vercel DNS) |
| `api.closebot.com` | ❌ **NO CDN** | 🔴 **YES — `20.115.232.12`** (Azure direct) |
| `closebot.com` | Cloudflare | ✅ Protected |
**Severity: HIGH**`api.closebot.com` resolves directly to an Azure App Service IP with no CDN/WAF in front. The full Azure hostname `cb-api-zarqcgo3sph6q.azurewebsites.net` is exposed via DNS CNAME chain.
### Azure Information Leakage
- **App ID**: `cid-v1:1593e7a7-a705-4f69-977e-49c3fa1d0aa3` (via `Request-Context` header)
- **Azure hostname**: `cb-api-zarqcgo3sph6q.azurewebsites.net`
- **Datacenter**: `waws-prod-mwh-117` (West US 2, Microsoft West Hub)
- **Server**: Kestrel (ASP.NET)
- **Routing cookies**: TiPMix (Azure traffic routing)
### SSL/TLS
| Property | Value |
|----------|-------|
| **Certificate** | Let's Encrypt R13 |
| **Valid From** | Feb 5, 2026 |
| **Valid Until** | May 6, 2026 |
| **Subject** | `CN=app.closebot.com` |
| **SANs** | `app.closebot.com` only |
| **HSTS** | ✅ `max-age=63072000` (app only) |
| **HSTS Preload** | ❌ Not in preload list |
---
## 13. Positive Findings ✅
1. **Vercel Security Checkpoint** — Effective bot/scraping protection on the frontend
2. **Clerk Authentication** — Industry-standard auth provider, properly handling session states
3. **No sensitive files exposed**`.env`, `.git`, `wp-config.php` all blocked
4. **WordPress user enumeration blocked**`/wp-json/wp/v2/users` returns 401
5. **XML-RPC disabled** — Returns 403
6. **HSTS on app.closebot.com** — 2-year max-age
7. **Host header injection blocked** — Vercel properly rejects invalid hosts
8. **CRLF injection blocked** — Properly encoded
9. **No admin/staging subdomains exposed** — Clean subdomain surface
10. **WordPress .env/wp-config blocked** — Server-level blocks in place
11. **Azure API cookies properly secured** — Secure, HttpOnly flags set
12. **Cloudflare protecting WordPress** — Bot management, edge caching
---
## 14. Recommendations
### 🔴 CRITICAL — Fix Immediately
#### 1. API CORS Wildcard (`Access-Control-Allow-Origin: *`)
**Impact:** Any website can make cross-origin requests to your API, including authenticated endpoints
**Fix:**
```csharp
// In your ASP.NET API startup/program.cs
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(
"https://app.closebot.com",
"https://closebot.com"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
```
### 🟠 HIGH — Fix This Week
#### 2. Add Security Headers to API (api.closebot.com)
```csharp
// Middleware or web.config
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
context.Response.Headers.Add("Content-Security-Policy", "default-src 'none'");
context.Response.Headers.Remove("Server");
context.Response.Headers.Remove("Request-Context");
context.Response.Headers.Remove("x-ms-middleware-request-id");
await next();
});
```
#### 3. Put API Behind CDN/WAF
- Add Cloudflare or Azure Front Door in front of `api.closebot.com`
- Hide the origin Azure IP
- Get DDoS protection and rate limiting
#### 4. Implement API Rate Limiting
```csharp
// ASP.NET rate limiting middleware
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("api", opt =>
{
opt.Window = TimeSpan.FromMinutes(1);
opt.PermitLimit = 60;
opt.QueueLimit = 0;
});
});
```
### 🟡 MEDIUM — Fix This Sprint
#### 5. Add Security Headers to app.closebot.com
In `next.config.js`:
```javascript
const securityHeaders = [
{ key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.clerk.accounts.dev; style-src 'self' 'unsafe-inline';" },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];
module.exports = {
headers: async () => [{ source: '/:path*', headers: securityHeaders }],
poweredByHeader: false, // Remove X-Powered-By: Next.js
};
```
#### 6. Remove WordPress readme.html and license.txt
```bash
# On WordPress server
rm /path/to/wordpress/readme.html
rm /path/to/wordpress/license.txt
```
#### 7. Hide Azure Infrastructure Headers
Remove `Request-Context` and `x-ms-middleware-request-id` headers from API responses.
#### 8. Add `Secure` Flag to NEXT_LOCALE Cookie
In Next.js middleware or cookie configuration, ensure `Secure` flag is set.
### 🔵 LOW — Fix When Convenient
#### 9. Add `security.txt`
Create `/.well-known/security.txt` with responsible disclosure contact.
#### 10. Add `robots.txt`
Even if you don't want indexing, an explicit `robots.txt` is good practice.
#### 11. Hide WordPress Version
```php
// In functions.php
remove_action('wp_head', 'wp_generator');
```
#### 12. Remove Clerk Auth Headers from Responses
Configure Clerk middleware to not expose `x-clerk-auth-status` and `x-clerk-auth-reason` to external responses.
#### 13. HSTS Preload
Submit `app.closebot.com` to the HSTS preload list and add `includeSubDomains; preload` to the HSTS header.
---
## Appendix: Raw Test Data
### CORS Test Results (api.closebot.com)
```
Origin: https://evil.com → Access-Control-Allow-Origin: *
Origin: null → Access-Control-Allow-Origin: *
Origin: https://evil.closebot.com → Access-Control-Allow-Origin: *
OPTIONS (preflight) → Access-Control-Allow-Origin: *, Allow-Headers: Authorization,Content-Type
```
### API Endpoint Discovery Summary
```
Authenticated (401): /bot, /bot/list, /bot/create, /bot/all, /bot/settings, /bot/config, /lead, /agency
Redirect (301): /swagger
Not Found (404): everything else
```
### Rate Limiting Test (50 rapid requests)
```
app.closebot.com/login: 200 200 200 200 200 ... (all 200, then Vercel checkpoint kicks in)
api.closebot.com/: 404 404 404 404 404 ... (all 404, never rate limited)
```