Skip to content

harden: default allow-external-refs to false in the actions#128

Merged
reuvenharrison merged 3 commits into
mainfrom
chore/default-external-refs-false
May 30, 2026
Merged

harden: default allow-external-refs to false in the actions#128
reuvenharrison merged 3 commits into
mainfrom
chore/default-external-refs-false

Conversation

@reuvenharrison
Copy link
Copy Markdown
Contributor

@reuvenharrison reuvenharrison commented May 30, 2026

Draft — do not merge until the prerequisites below are met.

What

Makes all five actions default allow-external-refs to false, the safe posture for CI that runs unattended on pull-request (incl. fork) content, and adds a recovery hint so the new default is low-friction:

  1. Default flip + threading. breaking, changelog, diff, pr-comment gain an allow-external-refs input (default false), threaded through each entrypoint as --allow-external-refs=<value> so the explicit action input is authoritative over any .oasdiff.yaml value. validate's input default flips truefalse. README inputs tables updated.

  2. Recovery hint. With external refs off by default, a spec that resolves an external $ref now fails the step. Each entrypoint captures oasdiff's stderr, still surfaces it, and on the external-ref failure emits a GitHub ::error:: annotation with the fix:

    oasdiff: this spec resolves external $refs, which are disabled by default to prevent SSRF on untrusted pull requests. If the spec is trusted, set allow-external-refs: true on the oasdiff action step.

    This turns a post-upgrade red ❌ into a one-glance fix on the PR's Checks tab. Detection matches both failure messages: the git-ref-path external $ref not allowed and the file-path disallowed external reference (the latter is kin-openapi's terser text with no remedy of its own). Success path and authoritative exit codes are unchanged.

Compatibility

Specs loaded via the recommended git-ref form (origin/main:openapi.yaml), single- and multi-file, are unaffected — intra-repo relative $refs resolve via git show, not as external refs. Verified empirically.

Opt back in with allow-external-refs: true if you either:

  • reference external URLs in a $ref, or
  • load split multi-file specs by plain file path instead of the git-ref form.

Root specs given as a URL source (base: https://…) are not affected — the flag governs $ref resolution, not the root load.

pr-comment note

pr-comment fails closed on a blocked external $ref (no review token is created, so no comment is posted) and surfaces the same ::error:: recovery annotation as the other actions. If we later want it to post the remedy as an actual PR comment (its native surface), that's a follow-up — not in this PR.

Prerequisites before this can merge / release

  1. oasdiff #974 merged and released as v1.18.1.
  2. This branch also bumps the action Dockerfiles to tufin/oasdiff:v1.18.1.

Until the base image honors the flag on the git-ref load path (oasdiff #974), --allow-external-refs=false is a no-op there, so shipping this earlier would give a false sense of protection.

Test plan

  • Existing test-*.yaml workflows pass (their specs are self-contained / URL-sourced without external $refs, so unaffected).
  • A spec with an external-URL $ref fails closed by default, emits the ::error:: recovery annotation, and passes with allow-external-refs: true.
  • git-ref multi-file spec still resolves under the new default.

reuvenharrison and others added 3 commits May 30, 2026 22:26
CI actions run unattended on pull-request content, including from forks,
so the safe default for untrusted input is to not resolve external $refs.
All five actions now default allow-external-refs to false:

- breaking, changelog, diff, pr-comment: new `allow-external-refs` input
  (default false), threaded through each entrypoint as
  --allow-external-refs=<value> so the explicit input is authoritative.
- validate: input default flipped true -> false.

Users whose specs reference external URLs, or who load split multi-file
specs by file path rather than the recommended git-ref form, set
allow-external-refs: true to opt back in. Specs loaded via the
recommended `origin/main:openapi.yaml` git-ref form (single- and
multi-file) are unaffected: relative refs resolve via `git show`, not as
external refs. README inputs tables updated.

NOTE: effective only on an oasdiff base image that honors the flag on
the git-ref load path (oasdiff #974, shipping in v1.18.1). Must land
together with the Dockerfile bump to v1.18.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With allow-external-refs defaulting to false, a spec that resolves an
external $ref now fails the step. oasdiff prints the cause to stderr
(visible in logs), but that does not explain the new default or name
the action input, and the file-path load path emits only kin-openapi's
terse "disallowed external reference" with no remedy.

Each entrypoint now captures oasdiff's stderr, still surfaces it, and on
the external-ref failure signature emits a GitHub ::error:: annotation
with the fix: set 'allow-external-refs: true' on the step if the spec is
trusted. This turns a post-upgrade red X into a one-glance fix on the
PR's Checks tab. Detection matches both the git-ref-path message
("external $ref not allowed") and the file-path message ("disallowed
external reference"). No change to the success path or to the
authoritative exit code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e text

oasdiff returns a dedicated exit code (123) for a spec that resolves an external
$ref under --allow-external-refs=false. Key the recovery hint off that code
instead of grepping oasdiff's stderr for "external $ref not allowed" /
"disallowed external reference" — text is brittle (kin-openapi owns the file-path
wording; messages can change), an exit code is a stable contract.

Requires the v1.18.1 base image (oasdiff exit-code change). The raw error is
still surfaced for every failure; this only gates the action-specific remedy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@reuvenharrison reuvenharrison marked this pull request as ready for review May 30, 2026 21:07
@reuvenharrison reuvenharrison merged commit db329e1 into main May 30, 2026
58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant