> ## Documentation Index
> Fetch the complete documentation index at: https://docs.37audits.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Protected URL Auditor

> Probes admin, API, configuration and debug paths to confirm they require authentication

<Info>
  **Security Auditor** — probes a catalogue of sensitive paths on the monitored site without credentials and confirms each one answers `401`, `403` or `404`, or redirects to a login page.
</Info>

<CardGroup cols={2}>
  <Card title="Access control" icon="lock">
    An admin panel, API explorer or configuration endpoint that answers `200` to anyone is an open door.
  </Card>

  <Card title="Information disclosure" icon="eye">
    Debug, log, backup and setup paths leak internals even when they look harmless.
  </Card>
</CardGroup>

This auditor takes the **origin** of the monitored URL (for example `https://example.com` for `https://example.com/web/guest/home`), picks the path catalogue of the platform declared in the monitored stack, adds any paths configured for the URL, and sends one unauthenticated `GET` to every path. The first supported platform catalogue is **Liferay**; every other site uses the **generic** catalogue. New platforms (for example WordPress) can be added as visitors with their own paths.

## Preferences

These settings can be configured per monitored URL from the URL's auditor configuration tab. None is required, so the auditor also runs from Quick Audit.

\| Preference | Type | Default | Meaning |
\|---|---|---|---|---|
\| `paths` | string | empty | Comma-separated root-relative paths probed **in addition to** the platform catalogue, for example `/wp-admin, /graphql, /actuator`. Whitespace is trimmed, a missing leading `/` is added, and duplicates of catalogue paths are ignored. Extra paths follow the same rules and codes as the catalogue. |

## How it works

1. **Origin** — the scheme and host of the monitored URL. A URL without them is `ERROR` (`501`).

2. **Catalogue** — the Liferay visitor runs when the monitored stack lists Liferay as vendor or product; otherwise the generic visitor runs. Paths from the `paths` preference are appended to the selected catalogue.

   | Platform | Paths |
   | - | - |
   | Liferay | `/group/guest/~/control_panel/manage`, `/o/api`, `/api/jsonws`, `/c/portal/json_service` |
   | Generic | `/admin`, `/administrator`, `/api`, `/api/v1`, `/dashboard`, `/control_panel`, `/manage`, `/management`, `/config`, `/configuration`, `/settings`, `/setup`, `/install`, `/backup`, `/logs`, `/debug`, `/test`, `/dev`, `/development`, `/internal`, `/private`, `/secure`, `/system`, `/sys`, `/root`, `/superuser` |

3. **Baseline** — one extra request to a random path that cannot exist (`/37audits-probe-<random>`). If it answers `2xx`, the site serves a soft 404 and a `200` on a sensitive path proves nothing (`303`).

4. **Probe** — every path is requested with `GET` and the 37 Audits user agent. Up to six requests run in parallel. The URL's Basic auth, if configured, is sent only to the monitored host.

5. **Follow same-path redirects** — a `3xx` whose target keeps the same path (canonical `www` host, `http` to `https`, trailing slash) is followed, up to five hops, and the final answer is judged. Following stops, and the path is reported instead, when the target is a login-like URL, another path, a loop, or the sixth hop.

6. **Judge each answer**:
   * `401`, `403`, `404` — protected.
   * `3xx` to a URL containing `login`, `signin`, `sign-in`, `auth`, `sso`, `oauth` or `saml` — protected (redirect to a login page).
   * `2xx` — exposed (`400`), unless the baseline hit a soft 404.
   * `3xx` to another path, a loop, or more than five hops — protection unconfirmed (`300`).
   * any other status (`405`, `429`, `5xx`…) — inconclusive (`301`).
   * no HTTP response — path could not be probed (`302`); when no request at all got a response the audit is `ERROR` (`500`).

7. **Aggregate** — `ERROR` wins, then `FAIL`, then `WARNING`; if every path is protected, the audit is `SUCCESS` (`200`).

## What it audits

Every row maps to one `checkRule*` method and one `CheckCode`. Codes `200` and `501` belong to the auditor; the others are shared by every platform visitor. CheckCode suffixes use status ranges: `200` success, `300–399` warning, `400–499` fail, `500–599` error.

| CheckCode | Status | When it fires | Recommendation | Why it matters |
| - | - | - | - | - |
| <a id="37A-ProtectedUrlAuditor-501" />`37A-ProtectedUrlAuditor-501` | `ERROR` | The monitored URL has no scheme or hostname, so there is no origin to probe. | Monitor an absolute URL with scheme and hostname (for example `https://example.com/`) instead of `{url}`. | — |
| <a id="37A-ProtectedUrlAuditor-500" />`37A-ProtectedUrlAuditor-500` | `ERROR` | Not one request, the baseline included, got an HTTP response (DNS failure, connection refused, every request timed out). | Make sure `{origin}` is reachable by the auditor and re-run; last error was `{error}`. | — |
| <a id="37A-ProtectedUrlAuditor-303" />`37A-ProtectedUrlAuditor-303` | `WARNING` | The baseline request to a random non-existent path answered `2xx` (soft 404). The exposed-path rule is skipped for this run. | Make unknown paths on `{origin}` answer `404`, then re-run so exposed paths can be detected. | When unknown paths answer 2xx, an exposed page cannot be told apart from a missing one, so real exposures stay hidden. Soft 404s also get error pages indexed by search engines. |
| <a id="37A-ProtectedUrlAuditor-400" />`37A-ProtectedUrlAuditor-400` | `FAIL` | A sensitive path answered `2xx` without authentication, directly or after same-path redirects (the message lists them as `via "…"`). One check per exposed path. | Require authentication or block `{path}` on `{origin}` so it answers `401`, `403` or `404` instead of `{status}`. | Administration consoles, configuration and internal endpoints reachable without login give attackers a direct way to read data or take over the site. Automated scanners probe for these paths constantly. |
| <a id="37A-ProtectedUrlAuditor-300" />`37A-ProtectedUrlAuditor-300` | `WARNING` | A sensitive path ended on a redirect (`3xx`) that was not followed: its target is another path, the chain loops, or it exceeds five hops, and it does not look like a login page. One check per path; `data.redirects` lists the hops that were followed. | Confirm `{location}` requires authentication, or make `{path}` answer `401`, `403` or `404` directly. | The path does not refuse anonymous visitors, it sends them somewhere else. If that destination is not behind a login, the administration or internal page is effectively public. |
| <a id="37A-ProtectedUrlAuditor-301" />`37A-ProtectedUrlAuditor-301` | `WARNING` | A sensitive path answered a status that is neither `2xx`, `3xx`, `401`, `403` nor `404` (for example `405`, `429`, `500`). One check per path. | Make `{path}` answer `401`, `403` or `404` to unauthenticated requests; it currently answers `{status}`. | Only 401, 403 or 404 prove a path is closed to anonymous visitors. Any other answer leaves open whether an attacker could reach it with a different request. |
| <a id="37A-ProtectedUrlAuditor-302" />`37A-ProtectedUrlAuditor-302` | `WARNING` | A probe got no HTTP response (timeout, reset) while at least one other request did. One check per path. | Make sure `{probeUrl}` is reachable by the auditor, then re-run; last error was `{error}`. | A path that could not be probed is a path whose protection is unknown, so an exposed administration or internal page could go unnoticed. |
| <a id="37A-ProtectedUrlAuditor-200" />`37A-ProtectedUrlAuditor-200` | `SUCCESS` | Every path in the catalogue, extra paths included, is protected. Message is `All {n} {platform} sensitive paths on "{origin}" answered 401, 403 or 404 or redirected to a login page.`; `data` lists the paths, the extra paths and the status each one returned. | — | — |

## Output documentation

| Status | Description | Test logic |
| - | - | - |
| **SUCCESS** | Every sensitive path of the platform catalogue is protected | Each path answered `401`, `403` or `404` (directly or after same-path redirects), or redirected to a login-like URL; the baseline path did not answer `2xx` (`200`). |
| **WARNING** | Protection could not be confirmed for one or more paths | Redirect to another path, a loop or more than five hops (`300`); unexpected status such as `405`, `429` or `5xx` (`301`); a path with no HTTP response while others answered (`302`); soft-404 site (`303`). Several can fire together. |
| **FAIL** | At least one sensitive path is reachable without authentication | A path answered `2xx` and the baseline did not (`400`). One check per exposed path; warnings for other paths are listed too. |
| **ERROR** | The auditor could not judge the site | No request got an HTTP response (`500`); the monitored URL has no scheme or host (`501`). |

## Risks and considerations

### Exposed administration and API endpoints

* `/admin`, `/manage`, `/setup` and their platform equivalents are the first paths an attacker or a scanner tries. Answering `200` to an anonymous request means either the panel is open or a login form is rendered inline; both deserve a look, and only the second is acceptable.
* On Liferay, `/o/api` (the headless API explorer) and `/api/jsonws` (the JSON web services page) list every remote service the portal exposes. They should be restricted to authenticated users or disabled outside development.

### Information disclosure

* `/debug`, `/logs`, `/backup`, `/config` and `/install` routinely leak stack traces, credentials, database dumps or installer screens. A `404` is the safest answer; `403` is fine as long as the body does not describe what is being protected.

### Redirects are followed only when they keep the path

* A `302` to a login page is treated as protected because the request never reached the resource.
* Canonical redirects (`example.com` to `www.example.com`, `http` to `https`, `/admin` to `/admin/`) are followed, up to five hops, so the answer of the real URL is judged. The hops are listed in the finding as `via "…"`.
* A redirect to another path (home page, error page) is reported as a warning because a `200` there says nothing about the probed path. Follow it manually to confirm.
* Basic auth configured for the monitored URL is not sent to other hosts reached through redirects.

### Soft 404 sites

* Single-page applications and some CDNs answer `200` with the app shell for any path. The baseline probe catches this and downgrades the run to a single warning instead of flagging every path as exposed. Until unknown paths answer `404`, this auditor cannot tell an exposed path from the app shell.

### What this auditor does not check

* It never authenticates and never posts data; it only looks at the status code and the `Location` header of one `GET` per path.
* It does not inspect the response body, so a `200` that renders a login form inline is still reported as exposed. Configure the application to answer `401`/`403` or redirect to the login page instead.
* It probes only the listed catalogue plus the `paths` preference; application-specific paths (for example `/wp-admin` on WordPress) need either the preference or a visitor for that platform.
* Basic auth configured for the monitored URL is sent with every probe to the monitored host, so the audit judges the application behind the environment gate, not the gate itself.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.