| name | new-api-pentest |
| description | 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. |
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
curl -s -i https://TARGET/ | head -40
curl -s https://TARGET/ | grep -oE '/static/js/[a-zA-Z0-9._-]+\.js' | sort -u
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.