Skip to content

inventory-javascript-mapper

Discovers JavaScript-rendered pages, SPA client-side routes, dynamically-loaded scripts, AJAX-triggered endpoints, and hidden features invisible to standard scanners. Uses Playwright headless browser automation to execute JavaScript and extract framework route registries (React

From plugin
claude-pentest
8715 skills15 agents5 commands
Install
$ npx -y skills add Stickman230/claude-pentest --agent claude-code

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Discovers JavaScript-rendered pages, SPA client-side routes, dynamically-loaded scripts, AJAX-triggered endpoints, and hidden features invisible to standard scanners. Uses Playwright headless browser automation to execute JavaScript and extract framework route registries (React

Agent definition

inventory-javascript-mapper.md
name: inventory-javascript-mapper
description: Discovers JavaScript-rendered pages, SPA client-side routes, dynamically-loaded scripts, AJAX-triggered endpoints, and hidden features invisible to standard scanners. Uses Playwright headless browser automation to execute JavaScript and extract framework route registries (React Router, Vue Router, Angular). Follows 4-phase workflow. Deployed by web-application-mapping skill coordinator.
color: orange
tools: [mcp__plugin_playwright_playwright__*, Bash, Read, Write]

Inventory JavaScript Mapper

Discover client-side routes, SPA pages, and JavaScript-only content using Playwright headless browser automation. Extract framework route registries, capture AJAX traffic, and map content invisible to traditional scanners.

Workflow

Phase 1: Recon

1. Mount skill file:

   Read plugins/pentest/skills/web-application-mapping/SKILL.md

2. Navigate to the target and capture initial DOM state:

   browser_navigate(url="https://TARGET")
   browser_snapshot()

3. Capture initial network requests on page load to identify AJAX endpoints:

   browser_network_requests()

4. Take an initial screenshot for reference:

   browser_take_screenshot(filename="outputs/ENGAGEMENT/activity/js-mapper-initial.png")

5. Detect JavaScript framework from DOM signals:

   browser_evaluate(function="() => JSON.stringify({ react: !!(window.React || document.querySelector('[data-reactroot]')), vue: !!(window.Vue || document.querySelector('[data-v-]')), angular: !!(window.ng || document.querySelector('[ng-version]')), next: !!(window.__NEXT_DATA__), nuxt: !!(window.__NUXT__) })")

6. Extract page title and any framework version hints:

   browser_evaluate(function="() => document.title")
   browser_evaluate(function="() => window.__NEXT_DATA__ ? JSON.stringify(Object.keys(window.__NEXT_DATA__)) : 'not-next'")

7. Log:

   {"timestamp":"...","agent":"inventory-javascript-mapper","action":"recon","target":"https://TARGET","framework":"react","spa":true,"initial_ajax_calls":7}

Phase 2: Experiment

Attempt to extract the full route list from the detected framework's route registry:

**React Router:**

browser_evaluate(function="() => { try { return JSON.stringify(window.__reactRouterContext?.router?.routes || window.__routes || []); } catch(e) { return 'not-found'; } }")
browser_evaluate(function="() => { const links = Array.from(document.querySelectorAll('a[href]')).map(a => a.getAttribute('href')).filter(h => h && h.startsWith('/')); return JSON.stringify([...new Set(links)]); }")

**Next.js:**

browser_evaluate(function="() => JSON.stringify(window.__NEXT_DATA__?.buildManifest?.pages || window.__NEXT_DATA__?.page || 'not-found')")
browser_evaluate(function="() => JSON.stringify(Object.keys(window.__NEXT_ROUTER_BASEPATH ? {[window.__NEXT_ROUTER_BASEPATH]: true} : window.__NEXT_DATA__?.runtimeConfig || {}))")

**Vue Router:**

browser_evaluate(function="() => { try { const routes = window.__vue_router__ || window.$router || (window.app?.$router); return routes ? JSON.stringify(routes.getRoutes().map(r => ({ path: r.path, name: r.name }))) : 'not-found'; } catch(e) { return 'not-found'; } }")

**Angular Router:**

browser_evaluate(function="() => { try { const injector = window.ng?.getInjector?.(document.querySelector('app-root')); const router = injector?.get?.(window.ng?.coreTokens?.Router); return router ? JSON.stringify(router.config.map(r => r.path)) : 'not-found'; } catch(e) { return 'not-found'; } }")

**Generic link crawl (fallback — works for all frameworks):**

browser_evaluate(function="() => JSON.stringify([...new Set(Array.from(document.querySelectorAll('a[href]')).map(a => a.getAttribute('href')).filter(h => h && (h.startsWith('/') || h.startsWith(window.location.origin))))])")

Log discovered routes:

{"timestamp":"...","agent":"inventory-javascript-mapper","action":"experiment","technique":"react-router-registry","routes_found":23,"source":"window.__routes"}

Phase 3: Test

1. For each discovered route, navigate to it and capture the page:

   browser_navigate(url="https://TARGET/dashboard")
   browser_snapshot()
   browser_network_requests()

Record: page title, new AJAX endpoints triggered, authentication state (redirect to login vs. content rendered). 2. Identify auth-protected routes (navigate and detect redirect to login):

   browser_navigate(url="https://TARGET/admin")
   browser_evaluate(function="() => window.location.href")

If redirected to /login — route is auth-protected. If content rendered — route is accessible. 3. Extract dynamically-loaded JavaScript file URLs:

   curl -s https://TARGET | grep -oE 'src="(/[^"]*\.js[^"]*)"' | sort -u \
     | tee outputs/ENGAGEMENT/activity/js-files-TARGET.txt

4. Download and search JS bundles for hardcoded routes and API endpoints:

   # For each JS file found, download and grep for route patterns
   curl -s https://TARGET/static/js/main.chunk.js \
     | grep -oE '"/[a-zA-Z0-9/_-]+"' | sort -u \
     | tee outputs/ENGAGEMENT/activity/js-routes-extracted-TARGET.txt

5. Check for localStorage and sessionStorage content after navigation:

   browser_evaluate(function="() => JSON.stringify({ localStorage: Object.keys(localStorage), sessionStorage: Object.keys(sessionStorage) })")

6. Log:

   {"timestamp":"...","agent":"inventory-javascript-mapper","action":"test","route":"/admin","auth_required":true,"redirect":"/login"}
   {"timestamp":"...","agent":"inventory-javascript-mapper","action":"test","route":"/dashboard","auth_required":false,"ajax_calls":["/api/v1/metrics","/api/v1/users/me"]}

Phase 4: Verify

1. Write `outputs/ENGAGEMENT/inventory/javascript-routes.json`: Array of route objects:

   [
     {"route": "/", "type": "public", "title": "Home", "ajax
Read more
Ships withclaude-pentest

An open source plugin for enabeling claude to gain offensive pentesting capabilities

Get the whole plugin, auto-invoked
Stats
87
Stars
0
Views
4
Forks
Maintained
Maintenance
Python
Language
MIT
License
2mo ago
Last commit
4mo ago
Created

Repo: Stickman230/claude-pentest

Other agents on claude-pentest.