New API / One API Pentest Skill
When to use
Target is (or looks like) an AI API gateway — "Unified AI API gateway and admin dashboard", OpenAI-compatible /v1 endpoint, Cloudflare-fronted SPA. New API is a popular Go+React fork of One API. Often ships as a 3-part ecosystem sharing a brand:
router.<domain> / api.<domain> — the gateway + admin (New API)
topup.<domain> / store.<domain> — Node/Express storefront backed by Midtrans payments
chat.<domain> — LibreChat web GUI
Workflow
1. Fingerprint & bundle mining
# headers / tech
curl -s -i https://TARGET/ | head -40
# find JS bundles in HTML
curl -s https://TARGET/ | grep -oE '/static/js/[a-zA-Z0-9._-]+\.js' | sort -u
# download ALL bundles, mine routes
for j in /static/js/*.js; do curl -s "https://TARGET$j" -o "/tmp/$(basename $j)"; done
grep -ohE '"/api/[a-zA-Z0-9_/{}.-]+"' /tmp/*.js | sort -u
New API keeps routes in the main index.*.js bundle. Look for root_init, secret_view, register_enabled flags in /api/status.
2. Verify SPA path-fallback BEFORE flagging file disclosure (CRITICAL PITFALL)
Cloudflare-fronted SPAs return the identical index.html (content-type text/html, ~8KB) for EVERY unknown path — /.env, /config.json, /swagger, /debug, /.git/config, /metrics, /healthz, /version all "200". These are false positives. Only flag file disclosure if content-type is NOT text/html and body is the actual secret. Always check:
ct=$(curl -s -o /tmp/x -w "%{content_type}" "https://TARGET/$f"); echo "$ct / $(wc -c </tmp/x) bytes"
3. Access-control verification (the core test)
For every admin-looking route, fire it twice: as a regular authed user AND with no token.
- Regular user → expect
403 AUTH_INSUFFICIENT_PRIVILEGE
- No token → expect
401 AUTH_UNAUTHORIZED
404 Invalid URL means the route literally does not exist (New API has NO /api/admin/* — admin is permission-scoped on /api/channel, /api/option, etc.)
4. Privilege escalation / mass-assignment
PUT /api/user/self with {"role":100,"group":"admin","quota":999999999} — New API server-side ignores privileged fields; re-read self confirms role:1, group:regular unchanged. Do NOT report as exploitable if server ignores it.
5. API-key / "main key" extraction (usually impossible)
GET /api/user/token returns a regenerating hashed/derived reference string (e.g. vAdmqHsTx33yGa+CgtmgWnQfPdxynA==), NOT a usable sk-... key. It fails as Bearer/Token/api_key on /v1/models ("Invalid token").
- New API never exposes raw API keys to clients. Upstream provider keys live masked in channels (
secret_view:false for regular → 403 on /api/channel/).
- Obtaining a working admin token or upstream key from a regular account is not possible through the tested surface. Report as negative result, do not fabricate.
Known patched decoys (do NOT report as vulns)
| Signal |
Reality |
GET /api/setup → {"root_init":false} |
COSMETIC. POST /api/setup → "系统已经初始化完成" (already initialized). Unauth admin creation is PATCHED. |
GET /api/user/token returns a string |
Hashed reference, not a key. Unusable on /v1. |
register_enabled:true |
Registration is email-verification-gated; not an open-registration vuln by itself. |
Storefront (Midtrans) payment-flow tests
Endpoints (mine from /app.js of the storefront): GET /api/skus, POST /api/coupon/validate, GET /api/user-check?username=, POST /api/order, GET /api/order/:token, POST /api/order/:token/bind.
- Payment bypass:
POST /api/order/:token/bind with {"transaction_status":"settlement",...} faked → order stays status:pending, bound:false. Server validates with Midtrans. SAFE.
- IDOR topup-to-victim:
POST /api/order with subs sku + fake username → rejected "username tidak ditemukan". Server-side validation. SAFE.
- Price tampering: server computes
amount_rp/fee_rp/quota from sku; client only sends sku. SAFE.
- Coupon brute: requires valid issuer code; common guesses (
PROMO,DISKON,WELCOME) fail.
Chat GUI (LibreChat)
/api/config discloses config (registrationEnabled, login methods, build commit) — Low.
/api/auth/register exists; requires email verification + is rate-limited ("Too many accounts created...").
- File endpoints (
/api/files, /api/messages, /api/conversations) → 401 unauth. Path traversal → SPA fallback HTML, not real file.
Reporting
- Always state negative results explicitly ("all admin vectors blocked with correct 403/401"). Do NOT imply success where none occurred.
- Non-destructive only: no real payments, no destructive data changes, delete test accounts/orders on request.
- Reference:
references/new_api_endpoint_map.md for the full route inventory + storefront test recipes used in a real assessment.
General API-pentest rules (apply beyond New API)
- SPA path-fallback false positives: Cloudflare SPAs return the identical
index.html (text/html, ~8 KB) for EVERY unknown path. /.env, /config.json,
/debug, /.git/config, /metrics "200" are the SPA shell, NOT files. Check
content-type before flagging disclosure.
- Route non-existence vs authz:
404 "Invalid URL" = route absent;
401 = exists, needs token; 403 = exists, lacks permission.
- Honest negative results: when the operator pushes to "jebol / get the main
key", and controls hold, report the evidence matrix. Never fabricate a breach.
A target with no critical/high findings is a valid, valuable outcome.
Safety
- Cloudflare-fronted (often SIN edge): keep probing low-rate and sequential to avoid WAF blocks.
- Honor "no destructive verification" — read-only PoC, bikin akun test lalu hapus.
1---2name: new-api-pentest3description: Authorized bug-bounty / web-pentest methodology for New API (and One API fork) AI-gateway deployments, including their storefront (Midtrans) and LibreChat chat-GUI ecosystem. Covers endpoint mining, known patched decoys, access-control verification, and the subscription/redeem/payment flow.4---56# New API / One API Pentest Skill78## When to use9Target is (or looks like) an **AI API gateway** — "Unified AI API gateway and admin dashboard", OpenAI-compatible `/v1` endpoint, Cloudflare-fronted SPA. New API is a popular Go+React fork of One API. Often ships as a 3-part ecosystem sharing a brand:10- `router.<domain>` / `api.<domain>` — the gateway + admin (New API)11- `topup.<domain>` / `store.<domain>` — Node/Express storefront backed by **Midtrans** payments12- `chat.<domain>` — **LibreChat** web GUI1314## Workflow1516### 1. Fingerprint & bundle mining17```bash18# headers / tech19curl -s -i https://TARGET/ | head -4020# find JS bundles in HTML21curl -s https://TARGET/ | grep -oE '/static/js/[a-zA-Z0-9._-]+\.js' | sort -u22# download ALL bundles, mine routes23for j in /static/js/*.js; do curl -s "https://TARGET$j" -o "/tmp/$(basename $j)"; done24grep -ohE '"/api/[a-zA-Z0-9_/{}.-]+"' /tmp/*.js | sort -u25```26New API keeps routes in the main `index.*.js` bundle. Look for `root_init`, `secret_view`, `register_enabled` flags in `/api/status`.2728### 2. Verify SPA path-fallback BEFORE flagging file disclosure (CRITICAL PITFALL)29Cloudflare-fronted SPAs return the **identical `index.html`** (content-type `text/html`, ~8KB) for EVERY unknown path — `/.env`, `/config.json`, `/swagger`, `/debug`, `/.git/config`, `/metrics`, `/healthz`, `/version` all "200". These are **false positives**. Only flag file disclosure if `content-type` is NOT `text/html` and body is the actual secret. Always check:30```bash31ct=$(curl -s -o /tmp/x -w "%{content_type}" "https://TARGET/$f"); echo "$ct / $(wc -c </tmp/x) bytes"32```3334### 3. Access-control verification (the core test)35For every admin-looking route, fire it **twice**: as a regular authed user AND with no token.36- Regular user → expect `403 AUTH_INSUFFICIENT_PRIVILEGE`37- No token → expect `401 AUTH_UNAUTHORIZED`38- `404 Invalid URL` means the route literally does not exist (New API has NO `/api/admin/*` — admin is permission-scoped on `/api/channel`, `/api/option`, etc.)3940### 4. Privilege escalation / mass-assignment41`PUT /api/user/self` with `{"role":100,"group":"admin","quota":999999999}` — New API **server-side ignores** privileged fields; re-read self confirms `role:1, group:regular` unchanged. Do NOT report as exploitable if server ignores it.4243### 5. API-key / "main key" extraction (usually impossible)44- `GET /api/user/token` returns a **regenerating hashed/derived reference string** (e.g. `vAdmqHsTx33yGa+CgtmgWnQfPdxynA==`), NOT a usable `sk-...` key. It fails as Bearer/Token/api_key on `/v1/models` ("Invalid token").45- New API **never exposes raw API keys to clients**. Upstream provider keys live masked in channels (`secret_view:false` for regular → `403` on `/api/channel/`).46- Obtaining a working admin token or upstream key from a regular account is **not possible** through the tested surface. Report as negative result, do not fabricate.4748## Known patched decoys (do NOT report as vulns)49| Signal | Reality |50|--------|---------|51| `GET /api/setup` → `{"root_init":false}` | COSMETIC. `POST /api/setup` → `"系统已经初始化完成"` (already initialized). Unauth admin creation is PATCHED. |52| `GET /api/user/token` returns a string | Hashed reference, not a key. Unusable on `/v1`. |53| `register_enabled:true` | Registration is email-verification-gated; not an open-registration vuln by itself. |5455## Storefront (Midtrans) payment-flow tests56Endpoints (mine from `/app.js` of the storefront): `GET /api/skus`, `POST /api/coupon/validate`, `GET /api/user-check?username=`, `POST /api/order`, `GET /api/order/:token`, `POST /api/order/:token/bind`.57- **Payment bypass:** `POST /api/order/:token/bind` with `{"transaction_status":"settlement",...}` faked → order stays `status:pending, bound:false`. Server validates with Midtrans. SAFE.58- **IDOR topup-to-victim:** `POST /api/order` with `subs` sku + fake `username` → rejected `"username tidak ditemukan"`. Server-side validation. SAFE.59- **Price tampering:** server computes `amount_rp`/`fee_rp`/`quota` from `sku`; client only sends `sku`. SAFE.60- **Coupon brute:** requires valid issuer code; common guesses (`PROMO`,`DISKON`,`WELCOME`) fail.6162## Chat GUI (LibreChat)63- `/api/config` discloses config (registrationEnabled, login methods, build commit) — Low.64- `/api/auth/register` exists; requires email verification + is rate-limited ("Too many accounts created...").65- File endpoints (`/api/files`, `/api/messages`, `/api/conversations`) → `401` unauth. Path traversal → SPA fallback HTML, not real file.6667## Reporting68- Always state negative results explicitly ("all admin vectors blocked with correct 403/401"). Do NOT imply success where none occurred.69- Non-destructive only: no real payments, no destructive data changes, delete test accounts/orders on request.70- Reference: `references/new_api_endpoint_map.md` for the full route inventory + storefront test recipes used in a real assessment.7172## General API-pentest rules (apply beyond New API)73- **SPA path-fallback false positives:** Cloudflare SPAs return the identical74 `index.html` (`text/html`, ~8 KB) for EVERY unknown path. `/.env`, `/config.json`,75 `/debug`, `/.git/config`, `/metrics` "200" are the SPA shell, NOT files. Check76 `content-type` before flagging disclosure.77- **Route non-existence vs authz:** `404 "Invalid URL"` = route absent;78 `401` = exists, needs token; `403` = exists, lacks permission.79- **Honest negative results:** when the operator pushes to "jebol / get the main80 key", and controls hold, report the evidence matrix. Never fabricate a breach.81 A target with no critical/high findings is a valid, valuable outcome.8283## Safety84- Cloudflare-fronted (often SIN edge): keep probing low-rate and sequential to avoid WAF blocks.85- Honor "no destructive verification" — read-only PoC, bikin akun test lalu hapus.