Skip to content

fix(api-map): router.use() middleware not detected, causes false-negative auth_protected #214

Description

@Wolfvin

Mengapa

Ditemukan saat audit api-map terhadap codebase Express nyata (Coretax-Auto-Downloader, vps-deploy/api/kds). Output menunjukkan auth_protected: 3 dari total total_routes: 160 — rasio yang sangat mencurigakan untuk backend dengan banyak endpoint sensitif (accounting, assignments, employees, dll).

Root cause dikonfirmasi via grep: accountingRouter.use(authMiddleware); accountingRouter.use(requireOutletAccess); (src/routes/accounting.ts:44-45) — pattern Express standar untuk apply middleware ke SEMUA route di router tersebut. Tapi _extract_js_middleware() di scripts/apimap_engine.py (baris ~726) regex-nya HARDCODE hanya kenali receiver app/server/fastify/hono:

m = re.match(
    r'(?:app|server|fastify|hono)\s*\.\s*use\s*\(\s*(\w+)',
    stripped
)

Router bernama custom (accountingRouter, assignmentsRouter, dll — konvensi Express yang sangat umum untuk modular routing) tidak pernah cocok dengan regex ini. Akibatnya SEMUA route yang di-protect via router.use(authMiddleware) dilaporkan sebagai auth_protected: false — false negative yang berbahaya untuk tool security-auditing, karena bisa membuat orang percaya endpoint tidak terproteksi padahal sebenarnya terproteksi (atau sebaliknya, luput dari endpoint yang BENAR-BENAR tidak terproteksi karena signal-to-noise sudah rusak duluan).

Konteks

api-map dipakai untuk audit permukaan API — salah satu use case utamanya adalah cek endpoint mana yang tidak terproteksi. Field auth_protected jadi tidak reliable untuk hampir semua backend Express yang pakai Router() modular (pattern paling umum di Express modern), bukan monolithic app.get/post semua di satu file.

Tujuan

api-map harus benar mendeteksi middleware yang di-attach ke instance Router() custom (bukan cuma app/server/fastify/hono), dan mengasosiasikan middleware tersebut ke SEMUA route yang didaftarkan lewat instance router itu — bukan cuma yang middleware-nya langsung jadi argument di .get()/.post()/dst.

Constraint

  • Perbaikan harus scoped ke router instance yang benar. accountingRouter.use(authMiddleware) HANYA berlaku untuk route yang didaftarkan via accountingRouter.get/post/put/delete(...) — BUKAN untuk instance router lain di file berbeda. Jangan buat semua route auth_protected secara serampangan.
  • Harus bisa detect nama variable Router apapun (tidak hardcode ke pattern "Router" di nama variable) — deteksi dari = Router() atau = express.Router() assignment, lalu lacak semua .use() dan .get/post/put/delete() call pada variable yang sama.
  • Jangan regresi test yang sudah ada untuk app.use()/server.use() global middleware — itu harus tetap terdeteksi seperti sebelumnya.
  • Baca _extract_js_middleware (baris ~717) dan logic assembly middleware_chain per route (baris ~340-370) sebagai starting point, tapi investigasi mandiri — jangan asumsikan scope perbaikan hanya di situ.

Definition of Done

  1. api-map <kds-workspace> menunjukkan auth_protected count yang jauh lebih tinggi dari 3 — verifikasi manual dengan grep berapa banyak route yang benar-benar under router yang punya .use(authMiddleware) atau .use(requirePermission(...)) sejenis
  2. Route yang TIDAK di bawah router manapun dengan auth middleware (misal endpoint publik seperti health-check) tetap auth_protected: false — tidak over-detect
  3. Test regression: app.use()/server.use() global middleware masih terdeteksi seperti sebelumnya (tidak regresi)
  4. Minimal 1 unit test baru yang reproduce pattern routerVar.use(middlewareName) + routes didaftarkan di router yang sama

Checklist Laporan Worker

  • auth_protected count sebelum dan sesudah fix di KDS backend
  • Sample 3-5 route yang sekarang benar terdeteksi auth_protected, verifikasi manual via grep bahwa itu memang benar
  • Konfirmasi tidak ada over-detection (route publik yang salah kena flag auth_protected)
  • Hasil test suite lengkap

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions