swagger-api / swagger-api/swagger-parser

[Feature]: Pluggable URL validator for remote $ref resolution

Open
#2,348 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
867
Forks
560
Avg merge
2d 21h
Merged PRs (30d)
7

Description

Feature Description

When safelyResolveURL is enabled, every external $ref fetch is gated by the built-in PermittedUrlsChecker, which runs a fixed pipeline — allowlist → denylist → restricted-IP-range — with the private/restricted-IP block always on and bypassable only by the allowlist. The checker is constructed internally (ResolverCache for OAS 3.0, ReferenceVisitor for OAS 3.1) with no public seam to substitute or extend it.

I'd like to propose an optional, pluggable URL-validation hook on ParseOptions. When set, the resolver routes every external fetch — top-level, direct, and transitive/nested — through it instead of the built-in checker. When unset, behaviour is unchanged.

Use case (generic)

Embedders often already have an outbound-request policy engine and need remote $ref resolution to obey it. The fixed order can't express several common policies, e.g.:

  • Deny a specific host while still permitting private/internal addresses — impossible today: the private-IP block is always on and only the allowlist bypasses it, but you can't enumerate "all private hosts".
  • CIDR / netmask rules — the lists match host patterns, not IP ranges.
  • Dynamic or context-dependent policy — per-tenant rules, externally-loaded config, decisions needing more than the URL string.
  • Reusing an existing, already-trusted validator instead of re-encoding it as allow/deny patterns (which also has matcher edge cases, e.g. #2237).

The goal is the same in all cases: keep the parser's safe-resolution flow (so transitive/nested refs stay gated) but let the embedder make the allow/deny decision.

Suggested shape (optional)

@FunctionalInterface
public interface UrlValidator { void validate(String url) throws Exception; } // throw = deny
// ParseOptions.setCustomUrlValidator(UrlValidator)

The resolver would prefer the validator when present (e.g. a thin PermittedUrlsChecker subclass that delegates to it), keeping the existing checker as the default. To avoid a silent-bypass footgun it should be fail-closed: when a validator is set, verification runs even if safelyResolveURL is left false. Small additive change across ParseOptions, the safe-url-resolver, and the two construction sites. Happy to contribute a PR.

Related

  • #1973 (provide own RemoteUrl implementation) — related, but about the HTTP transport rather than the allow/deny decision.
  • #1425 (customize remote vs local ref loading) — similar desire for control over remote ref handling; predates the safe resolver.
  • #2237 (block-list matcher edge cases) — illustrates the limits of the string-pattern lists.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace ParseOptions and the safe URL resolver, then inspect PermittedUrlsChecker, ResolverCache, and ReferenceVisitor to understand how top-level, direct, and nested external references are gated. Define the hook's interaction with safelyResolveURL and verify that the default behavior remains unchanged while all external fetches use the validator when configured and failures deny access.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.