Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
| `err-ignore` | `''` | Path to a file containing regex patterns for error-level changes to ignore | file path |
| `warn-ignore` | `''` | Path to a file containing regex patterns for warning-level changes to ignore | file path |
| `output-to-file` | `''` | Write output to this file path instead of stdout | file path |
| `allow-external-refs` | `false` | Resolve external `$ref`s. Defaults to `false` to prevent SSRF on untrusted pull requests. Set `true` if your spec references external URLs or loads split files by file path | `true`, `false` |

### Generate a changelog

Expand Down Expand Up @@ -126,6 +127,7 @@ jobs:
| `case-insensitive-headers` | `false` | Compare headers case-insensitively | `true`, `false` |
| `template` | `''` | Custom Go template for output formatting | Go template string |
| `output-to-file` | `''` | Write output to this file path instead of stdout | file path |
| `allow-external-refs` | `false` | Resolve external `$ref`s. Defaults to `false` to prevent SSRF on untrusted pull requests. Set `true` if your spec references external URLs or loads split files by file path | `true`, `false` |

### Generate a diff report

Expand Down Expand Up @@ -160,6 +162,7 @@ jobs:
| `composed` | `false` | Run in composed mode | `true`, `false` |
| `flatten-allof` | `false` | Merge allOf subschemas into a single schema before diff | `true`, `false` |
| `output-to-file` | `''` | Write output to this file path instead of stdout | file path |
| `allow-external-refs` | `false` | Resolve external `$ref`s. Defaults to `false` to prevent SSRF on untrusted pull requests. Set `true` if your spec references external URLs or loads split files by file path | `true`, `false` |

### Validate a single spec

Expand All @@ -184,7 +187,7 @@ jobs:
|---|---|---|---|
| `spec` | — (required) | Path to the OpenAPI spec to validate | file path, URL, git ref |
| `fail-on` | `''` | Fail with exit code 1 when a finding is at or above this severity (empty uses the oasdiff default, `ERR`) | `ERR`, `WARN`, `INFO` |
| `allow-external-refs` | `true` | Resolve external `$ref`s; set `false` to prevent SSRF when validating untrusted specs | `true`, `false` |
| `allow-external-refs` | `false` | Resolve external `$ref`s. Defaults to `false` to prevent SSRF on untrusted pull requests. Set `true` if your spec references external URLs | `true`, `false` |

For a non-blocking, report-only run, leave `fail-on` and set `continue-on-error: true` on the step. Outputs: `findings` (total), `error_count`, `warning_count`, `info_count`.

Expand Down Expand Up @@ -292,5 +295,6 @@ Each **Review** link opens a hosted page with a side-by-side spec diff and **App
| `include-path-params` | `false` | Include path parameter names in endpoint matching | `true`, `false` |
| `exclude-elements` | `''` | Exclude certain kinds of changes from the output | `endpoints`, `request`, `response` (comma-separated) |
| `composed` | `false` | Run in composed mode | `true`, `false` |
| `allow-external-refs` | `false` | Resolve external `$ref`s. Defaults to `false` to prevent SSRF on untrusted pull requests. Set `true` if your spec references external URLs or loads split files by file path | `true`, `false` |

[Get oasdiff Pro →](https://www.oasdiff.com/pricing)
5 changes: 5 additions & 0 deletions breaking/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ inputs:
description: 'Output to a file at the given path'
required: false
default: ''
allow-external-refs:
description: 'Allow external $refs in the spec; disable to prevent SSRF when processing untrusted specs. Defaults to false (safe for CI on untrusted pull requests).'
required: false
default: 'false'
outputs:
breaking:
description: 'Output summary of API breaking changes, encompassing both warnings and errors'
Expand All @@ -75,3 +79,4 @@ runs:
- ${{ inputs.err-ignore }}
- ${{ inputs.warn-ignore }}
- ${{ inputs.output-to-file }}
- ${{ inputs.allow-external-refs }}
16 changes: 15 additions & 1 deletion breaking/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ readonly flatten_allof="${11}"
readonly err_ignore="${12}"
readonly warn_ignore="${13}"
readonly output_to_file="${14}"
readonly allow_external_refs="${15}"

write_output () {
local output="$1"
Expand All @@ -44,6 +45,11 @@ echo "running oasdiff breaking... base: $base, revision: $revision, fail_on: $fa

# Build flags to pass in command
flags=""
# allow-external-refs defaults to false (safe for CI on untrusted PRs); pass
# whatever the input resolved to so the explicit action input is authoritative.
if [ -n "$allow_external_refs" ]; then
flags="$flags --allow-external-refs=$allow_external_refs"
fi
if [ "$include_path_params" = "true" ]; then
flags="$flags --include-path-params"
fi
Expand Down Expand Up @@ -86,7 +92,15 @@ if [ -n "$fail_on" ]; then
fail_on_flag="--fail-on $fail_on"
fi
exit_code=0
breaking_changes=$(oasdiff breaking "$base" "$revision" $flags $fail_on_flag) || exit_code=$?
_err=$(mktemp)
breaking_changes=$(oasdiff breaking "$base" "$revision" $flags $fail_on_flag 2>"$_err") || exit_code=$?
[ -s "$_err" ] && cat "$_err" >&2
# Exit code 123 = oasdiff refused a disallowed external $ref (stable contract,
# not message text). Surface the action-specific remedy.
if [ "$exit_code" -eq 123 ]; then
echo "::error::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."
fi
rm -f "$_err"

# Run 2: render annotations to stdout via --format githubactions so
# GitHub parses them onto the PR's "Files changed" tab. Tolerate
Expand Down
5 changes: 5 additions & 0 deletions changelog/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ inputs:
description: 'Output level: INFO (default), WARN, or ERR'
required: false
default: ''
allow-external-refs:
description: 'Allow external $refs in the spec; disable to prevent SSRF when processing untrusted specs. Defaults to false (safe for CI on untrusted pull requests).'
required: false
default: 'false'
outputs:
changelog:
description: 'Output summary of API changelog'
Expand All @@ -78,4 +82,5 @@ runs:
- ${{ inputs.format }}
- ${{ inputs.template }}
- ${{ inputs.level }}
- ${{ inputs.allow-external-refs }}

23 changes: 21 additions & 2 deletions changelog/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ readonly case_insensitive_headers="${11}"
readonly format="${12}"
readonly template="${13}"
readonly level="${14}"
readonly allow_external_refs="${15}"

echo "running oasdiff changelog base: $base, revision: $revision, include_path_params: $include_path_params, exclude_elements: $exclude_elements, filter_extension: $filter_extension, composed: $composed, flatten_allof: $flatten_allof, output_to_file: $output_to_file, prefix_base: $prefix_base, prefix_revision: $prefix_revision, case_insensitive_headers: $case_insensitive_headers, format: $format, template: $template, level: $level"

# Build flags to pass in command
flags=""
# allow-external-refs defaults to false (safe for CI on untrusted PRs); pass
# whatever the input resolved to so the explicit action input is authoritative.
if [ -n "$allow_external_refs" ]; then
flags="$flags --allow-external-refs=$allow_external_refs"
fi
if [ "$include_path_params" = "true" ]; then
flags="$flags --include-path-params"
fi
Expand Down Expand Up @@ -89,11 +95,24 @@ echo "flags: $flags"
delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-')
echo "changelog<<$delimiter" >>"$GITHUB_OUTPUT"

exit_code=0
_err=$(mktemp)
if [ -n "$flags" ]; then
output=$(oasdiff changelog "$base" "$revision" $flags)
output=$(oasdiff changelog "$base" "$revision" $flags 2>"$_err") || exit_code=$?
else
output=$(oasdiff changelog "$base" "$revision")
output=$(oasdiff changelog "$base" "$revision" 2>"$_err") || exit_code=$?
fi
if [ "$exit_code" -ne 0 ]; then
[ -s "$_err" ] && cat "$_err" >&2
# Exit code 123 = oasdiff refused a disallowed external $ref (stable
# contract, not message text). Surface the action-specific remedy.
if [ "$exit_code" -eq 123 ]; then
echo "::error::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."
fi
rm -f "$_err"
exit "$exit_code"
fi
rm -f "$_err"

if [ -n "$output" ] && ! echo "$output" | head -n 1 | grep -q "^No "; then
write_output "$output"
Expand Down
5 changes: 5 additions & 0 deletions diff/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ inputs:
description: 'Output to a file at the given path'
required: false
default: ''
allow-external-refs:
description: 'Allow external $refs in the spec; disable to prevent SSRF when processing untrusted specs. Defaults to false (safe for CI on untrusted pull requests).'
required: false
default: 'false'
outputs:
diff:
description: 'Output summary of API diff'
Expand All @@ -56,3 +60,4 @@ runs:
- ${{ inputs.composed }}
- ${{ inputs.flatten-allof }}
- ${{ inputs.output-to-file }}
- ${{ inputs.allow-external-refs }}
18 changes: 16 additions & 2 deletions diff/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@ readonly filter_extension="$7"
readonly composed="$8"
readonly flatten_allof="$9"
readonly output_to_file="${10}"
readonly allow_external_refs="${11}"

echo "running oasdiff diff base: $base, revision: $revision, format: $format, fail_on_diff: $fail_on_diff, include_path_params: $include_path_params, exclude_elements: $exclude_elements, filter_extension: $filter_extension, composed: $composed, flatten_allof: $flatten_allof, output_to_file: $output_to_file"

# Build flags to pass in command
flags=""
# allow-external-refs defaults to false (safe for CI on untrusted PRs); pass
# whatever the input resolved to so the explicit action input is authoritative.
if [ -n "$allow_external_refs" ]; then
flags="$flags --allow-external-refs=$allow_external_refs"
fi
if [ "$format" != "yaml" ]; then
flags="$flags --format $format"
fi
Expand Down Expand Up @@ -75,11 +81,19 @@ echo "diff<<$delimiter" >>"$GITHUB_OUTPUT"

# Capture the exit code from oasdiff command while still getting the output
exit_code=0
_err=$(mktemp)
if [ -n "$flags" ]; then
output=$(oasdiff diff "$base" "$revision" $flags) || exit_code=$?
output=$(oasdiff diff "$base" "$revision" $flags 2>"$_err") || exit_code=$?
else
output=$(oasdiff diff "$base" "$revision") || exit_code=$?
output=$(oasdiff diff "$base" "$revision" 2>"$_err") || exit_code=$?
fi
[ -s "$_err" ] && cat "$_err" >&2
# Exit code 123 = oasdiff refused a disallowed external $ref (stable contract,
# not message text). Surface the action-specific remedy.
if [ "$exit_code" -eq 123 ]; then
echo "::error::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."
fi
rm -f "$_err"

if [ -n "$output" ]; then
write_output "$output"
Expand Down
5 changes: 5 additions & 0 deletions pr-comment/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ inputs:
description: 'oasdiff service base URL (override for testing)'
required: false
default: 'https://api.oasdiff.com'
allow-external-refs:
description: 'Allow external $refs in the spec; disable to prevent SSRF when processing untrusted specs. Defaults to false (safe for CI on untrusted pull requests).'
required: false
default: 'false'
runs:
using: 'docker'
image: 'Dockerfile'
Expand All @@ -42,3 +46,4 @@ runs:
- ${{ inputs.oasdiff-token }}
- ${{ inputs.github-token }}
- ${{ inputs.service-url }}
- ${{ inputs.allow-external-refs }}
17 changes: 16 additions & 1 deletion pr-comment/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ readonly composed="$5"
readonly oasdiff_token="$6"
readonly github_token="$7"
readonly service_url="${8:-https://api.oasdiff.com}"
readonly allow_external_refs="${9}"

echo "running oasdiff pr-comment base: $base, revision: $revision, include_path_params: $include_path_params, exclude_elements: $exclude_elements, composed: $composed"

# Build flags
flags=""
# allow-external-refs defaults to false (safe for CI on untrusted PRs); pass
# whatever the input resolved to so the explicit action input is authoritative.
if [ -n "$allow_external_refs" ]; then
flags="$flags --allow-external-refs=$allow_external_refs"
fi
if [ "$include_path_params" = "true" ]; then
flags="$flags --include-path-params"
fi
Expand All @@ -36,11 +42,20 @@ fi
# us from collecting the JSON. Real failures (missing file, parse error)
# still abort because they leave $changelog empty.
oasdiff_exit=0
changelog=$(oasdiff changelog "$base" "$revision" --format json $flags) || oasdiff_exit=$?
_err=$(mktemp)
changelog=$(oasdiff changelog "$base" "$revision" --format json $flags 2>"$_err") || oasdiff_exit=$?
if [ "$oasdiff_exit" -ne 0 ] && [ -z "$changelog" ]; then
[ -s "$_err" ] && cat "$_err" >&2
# Exit code 123 = oasdiff refused a disallowed external $ref (stable
# contract, not message text). Surface the action-specific remedy.
if [ "$oasdiff_exit" -eq 123 ]; then
echo "::error::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."
fi
rm -f "$_err"
echo "ERROR: oasdiff exited $oasdiff_exit with no output" >&2
exit $oasdiff_exit
fi
rm -f "$_err"

# If no changes, use empty array
if [ -z "$changelog" ] || [ "$changelog" = "null" ] || [ "$changelog" = "[]" ]; then
Expand Down
4 changes: 2 additions & 2 deletions validate/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ inputs:
required: false
default: ''
allow-external-refs:
description: 'Allow external $refs in the spec; disable to prevent SSRF when validating untrusted specs'
description: 'Allow external $refs in the spec; disable to prevent SSRF when validating untrusted specs. Defaults to false (safe for CI on untrusted pull requests).'
required: false
default: 'true'
default: 'false'
outputs:
findings:
description: 'Total number of findings reported by validate (0 if the spec is valid)'
Expand Down
19 changes: 14 additions & 5 deletions validate/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ readonly allow_external_refs="$3"

echo "running oasdiff validate... spec: $spec, fail_on: $fail_on, allow_external_refs: $allow_external_refs"

# Build flags. --allow-external-refs defaults to true in oasdiff, so only
# pass it when the input opts out. --fail-on defaults to ERR in oasdiff
# Build flags. The action input allow-external-refs defaults to false (safe for
# CI on untrusted PRs); pass whatever it resolved to so the explicit input is
# authoritative over any oasdiff.yaml value. --fail-on defaults to ERR in oasdiff
# (errors fail the build; warnings and info are reported but don't), so only
# pass it when the input overrides the threshold.
flags=""
if [ "$allow_external_refs" = "false" ]; then
flags="$flags --allow-external-refs=false"
if [ -n "$allow_external_refs" ]; then
flags="$flags --allow-external-refs=$allow_external_refs"
fi
if [ -n "$fail_on" ]; then
flags="$flags --fail-on $fail_on"
Expand All @@ -31,7 +32,15 @@ echo "flags: $flags"
# threshold, 0 otherwise). Tolerate non-zero so we can still set the outputs
# below; the exit code is reapplied at the end.
exit_code=0
oasdiff validate $flags --format githubactions "$spec" || exit_code=$?
_err=$(mktemp)
oasdiff validate $flags --format githubactions "$spec" 2>"$_err" || exit_code=$?
[ -s "$_err" ] && cat "$_err" >&2
# Exit code 123 = oasdiff refused a disallowed external $ref (stable contract,
# not message text). Surface the action-specific remedy.
if [ "$exit_code" -eq 123 ]; then
echo "::error::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 validate step."
fi
rm -f "$_err"

# Run 2: text format, captured for the finding count. Tolerate non-zero
# exit (the authoritative decision is already captured above).
Expand Down
Loading