Skip to content
Back to skills

Detecting Debug Endpoints

ASecurity

Probe a target for accidentally-public admin / debug / introspection endpoints — Spring Boot Actuator, Apache server-status, Prometheus metrics, GraphQL playground, Swagger UI, phpMyAdmin, JMX-over-HTTP (Jolokia), Elasticsearch _cat, Kibana / Grafana / Eureka / Consul panels. Use when: post-deploy verification, security audit before SOC2, inheriting a system you didn't build, or a bug bounty hints at an exposed introspection panel. Threshold: any of the canonical 40+ admin/debug paths returns...

  • 2,719 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 21, 2026
ai-agentspythongophpbashspringgitdatabasesecurity

Works with

  • claude code

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 21, 2026

npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill detecting-debug-endpoints --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Detecting Debug Endpoints?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Detecting Debug Endpoints
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jeremylongshore-detecting-debug-endpoints-beaa33a0/badge)](https://www.skillsdirectory.com/skills/jeremylongshore-detecting-debug-endpoints-beaa33a0)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: detecting-debug-endpoints
description: |
  Probe a target for accidentally-public admin / debug / introspection
  endpoints — Spring Boot Actuator, Apache server-status, Prometheus
  metrics, GraphQL playground, Swagger UI, phpMyAdmin, JMX-over-HTTP
  (Jolokia), Elasticsearch _cat, Kibana / Grafana / Eureka / Consul
  panels.
  Use when: post-deploy verification, security audit before SOC2,
  inheriting a system you didn't build, or a bug bounty hints at an
  exposed introspection panel.
  Threshold: any of the canonical 40+ admin/debug paths returns 200,
  302 to a login, or framework-specific JSON shape (e.g., Actuator
  returning a _links object, server-status HTML body containing
  the Apache Server Status title).
  Trigger with: "check debug endpoints", "actuator exposure", "admin
  panel scan", "graphql playground check".
allowed-tools:
  - Read
  - Bash(python3:*)
  - Bash(curl:*)
disallowed-tools:
  - Bash(rm:*)
  - Edit(/etc/*)
version: 3.30.0
author: Jeremy Longshore <jeremy@intentsolutions.io>
license: MIT
compatibility: Designed for Claude Code
tags:
  - security
  - information-disclosure
  - admin-panels
  - actuator
  - pentest
---

# Detecting Debug Endpoints

## Overview

Modern web stacks ship rich introspection by default. Spring Boot
Actuator exposes `/actuator/env` (every environment variable),
`/actuator/heapdump` (a live heap snapshot that contains credentials),
`/actuator/jolokia` (JMX bean invocation = pre-auth RCE in some
configurations). Apache `mod_status` exposes `/server-status` with
internal IPs, request counts, and the URL of every active request.
Prometheus `/metrics` exposes operational telemetry that often
includes connection-string-bearing labels by accident. phpMyAdmin
exposes the entire database if unauthenticated.

These are not bugs in the frameworks. They're features that ship
enabled-by-default for development convenience and stay enabled in
production because nobody disabled them at install time. The probe
set covers the canonical 40+ paths and grades each by the response
fingerprint specific to that framework.

## When the skill produces findings

| Finding | Severity | Threshold | Affected control |
|---|---|---|---|
| Spring Boot Actuator `/env` exposed | **CRITICAL** | 200 + body has `"propertySources"` | OWASP A05:2021 |
| Spring Boot Actuator `/heapdump` exposed | **CRITICAL** | 200 + `Content-Type: application/octet-stream` + multi-MB body | CWE-200 |
| Spring Boot Actuator `/jolokia` exposed | **CRITICAL** | 200 + body has `"agent":"jolokia"` | CWE-749 |
| phpMyAdmin reachable | **CRITICAL** | 200 + HTML body contains "phpMyAdmin" + login form | OWASP A07:2021 |
| Prometheus `/metrics` exposed | **HIGH** | 200 + body has `# HELP` or `# TYPE` lines | CWE-200 |
| Apache `mod_status` exposed | **HIGH** | 200 + body contains "Apache Server Status" | CWE-200 |
| Spring Boot Actuator `/actuator` index | **HIGH** | 200 + body has `"_links"` JSON | OWASP A05:2021 |
| Generic `/admin` returning 200 (not 401/403) | **HIGH** | 200 + HTML body with admin-shaped UI | CWE-285 |
| Elasticsearch `_cat` exposed | **HIGH** | 200 + body matches `health\s+status\s+index` | CWE-200 |
| GraphQL Playground on prod | **MEDIUM** | 200 + body contains `"GraphQLPlayground"` | CWE-200 |
| Swagger UI on prod | **MEDIUM** | 200 + body contains `"swagger-ui"` | CWE-200 |
| Spring Boot Actuator `/health` exposed | **MEDIUM** | 200 + body has `"status":"UP"` | CWE-200 |
| `phpinfo` page on prod | **MEDIUM** | 200 + body has `PHP Version` heading | CWE-200 |
| `/robots.txt` discloses admin paths | **LOW** | 200 + `Disallow:` lines mentioning `/admin` | CWE-200 |

## Prerequisites

- Python 3.9+ with `requests`
- Authorization for non-local targets

## Instructions

### Step 1 — Confirm Authorization

```text
"Do you have authorization to perform admin / debug endpoint
 discovery on this target? I need confirmation before proceeding."
```

### Step 2 — Run the scanner

```bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-debug-endpoints/scripts/probe_debug.py \
    https://target.example.com \
    --authorized
```

Options:

```
Usage: probe_debug.py URL [OPTIONS]

Options:
  --authorized       Attest authorization (required for non-local)
  --output FILE      Write findings to FILE
  --format FMT       json | jsonl | markdown (default: markdown)
  --min-severity SEV (default: info)
  --timeout SECS     Per-probe timeout (default: 10)
  --paths-file FILE  Override the default probe set with a custom list
  --include-redirects  Treat 302/303 to /login as findings (debug panel
                       exists but auth gates it — still worth noting)
```

The scanner sends a GET for each path. For 200 responses, it inspects
the body for the framework-specific fingerprint to confirm a true
positive (not the app's SPA index page). For 302 responses to common
login paths, the panel exists but auth is in front — flagged only
with `--include-redirects`.

### Step 3 — Interpret findings

CRITICAL = direct compromise vector (env vars / heapdump / Jolokia /
phpMyAdmin). Ship same-hour fix: take the endpoint behind authn or
disable it. Audit for prior exploitation.

HIGH = information disclosure substantial enough to drive subsequent
attacks (server-status reveals request URLs including session tokens
in query strings; /metrics labels often contain connection strings;
/admin reachable means brute-force can start).

MEDIUM = posture hardening (health checks, swagger).

### Step 4 — Cross-skill chaining

After this skill, suggest:

- `detecting-exposed-secrets-files` (#6) — same deploy mistake. If
  `/server-status` is reachable, `.git/` often is too.
- `auditing-cors-policy` (#3) — if a GraphQL or admin endpoint is
  reachable AND has open CORS, the attack chain compounds.

## Examples

### Example 1 — Inheriting a system audit

User: "We just acquired example.io. Quick audit of admin surface."

```bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-debug-endpoints/scripts/probe_debug.py \
    https://example.io --authorized --min-severity medium
```

Commonly surfaces forgotten `/server-status` on Apache hosts,
`/actuator/*` left enabled from Spring Boot defaults, leftover
`/phpmyadmin` from initial install.

### Example 2 — Spring Boot Actuator paranoia sweep

User: "We use Spring Boot heavily. Show me everywhere Actuator is
reachable."

```bash
for ENDPOINT in $(cat spring-services.txt); do
  python3 ${CLAUDE_PLUGIN_ROOT}/skills/detecting-debug-endpoints/scripts/probe_debug.py \
      "$ENDPOINT" --authorized --format jsonl
done | jq 'select(.title | contains("Actuator"))'
```

### Example 3 — CI gate against accidental re-enablement

```yaml
- name: Debug-endpoint guard
  run: |
    python3 plugins/security/penetration-tester/skills/detecting-debug-endpoints/scripts/probe_debug.py \
        "${{ secrets.STAGING_URL }}" \
        --authorized --min-severity high
```

Exit 1 fails the deploy if any HIGH or CRITICAL endpoint exposure
appears. Catches the regression where a debug profile gets enabled
in a `application-prod.yml` by accident.

## Output

JSON / JSONL / Markdown per `lib/report.py`. Exit codes: 0 clean, 1
high/critical, 2 error.

## Error Handling

- **SPA catches every URL with 200** → use `--check-only` semantics
  (default: fingerprint check filters out SPA matches).
- **WAF / CDN blocks the scanner** → expected for some targets.
  Coordinate with the target's security team for an allowlist; or
  run the scanner from inside the target's network if you have
  authorized internal access.
- **Connection error** → exit 2 with underlying error.

## Resources

- `references/THEORY.md` — Per-framework reasoning: why Actuator,
  mod_status, Prometheus, GraphQL Playground, Swagger, phpMyAdmin
  each matter; canonical fingerprints
- `references/PLAYBOOK.md` — Per-framework remediation: Spring Boot
  Actuator authn, Apache mod_status `<Location>` deny, Prometheus
  Bearer-token, GraphQL introspection toggle, Swagger profile gate
- `../analyzing-tls-config/references/AUTHORIZATION.md` — Active-scan
  authorization pattern

Files in this skill

  • SKILL.md7.9 KB
  • references/PLAYBOOK.md8.1 KB
  • references/THEORY.md9.2 KB
  • scripts/probe_debug.py15.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.