Skip to content

fix: reject unsafe JFrog credential targets#1490

Open
mldangelo-oai wants to merge 2 commits into
mainfrom
mdangelo/codex/fix-jfrog-trusted-https-hosts-c135
Open

fix: reject unsafe JFrog credential targets#1490
mldangelo-oai wants to merge 2 commits into
mainfrom
mdangelo/codex/fix-jfrog-trusted-https-hosts-c135

Conversation

@mldangelo-oai
Copy link
Copy Markdown
Contributor

Summary

  • require HTTPS JFrog URLs before remote acquisition proceeds
  • reject loopback JFrog hosts even when accidentally present in MODELAUDIT_JFROG_ALLOWED_HOSTS
  • add artifact-download and Storage API pre-network regressions with explicit/env credentials present

Validation

  • PYTHONPATH=/private/tmp/modelaudit-c135 PROMPTFOO_DISABLE_TELEMETRY=1 /Users/mdangelo/code/modelaudit/.venv/bin/pytest tests/integrations/test_jfrog.py -q: 42 passed
  • /Users/mdangelo/code/modelaudit/.venv/bin/ruff format --check modelaudit/utils/sources/jfrog.py tests/integrations/test_jfrog.py
  • /Users/mdangelo/code/modelaudit/.venv/bin/ruff check modelaudit/utils/sources/jfrog.py tests/integrations/test_jfrog.py
  • PYTHONPATH=/private/tmp/modelaudit-c135 /Users/mdangelo/code/modelaudit/.venv/bin/mypy modelaudit/utils/sources/jfrog.py tests/integrations/test_jfrog.py
  • git diff --check

@mldangelo-oai
Copy link
Copy Markdown
Contributor Author

@codex review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 31, 2026

Workflow run and artifacts

Performance Benchmarks

Compared 12 shared benchmarks with a regression threshold of 15%.
Status: 0 regressions, 0 improved, 12 stable, 0 new, 0 missing.
Aggregate shared-benchmark median: 767.82ms -> 760.77ms (-0.9%).

Workload Benchmark Target Size Files Baseline Current Change Status
padded-multi-stream-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_padded_multi_stream_upload multi_stream_padded 4.1 KiB 1 1.54ms 1.51ms -2.1% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_hex] nested_hex 130 B 1 413.2us 420.1us +1.7% stable
suspicious-pickle-intake tests/benchmarks/test_scan_benchmarks.py::test_scan_suspicious_pickle_intake suspicious-intake 183.8 KiB 4 104.00ms 102.35ms -1.6% stable
mixed-model-repository tests/benchmarks/test_scan_benchmarks.py::test_scan_release_candidate_repository release-candidate 547.3 KiB 32 294.85ms 291.87ms -1.0% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_raw] nested_raw 78 B 1 399.7us 403.3us +0.9% stable
duplicate-heavy-registry tests/benchmarks/test_scan_benchmarks.py::test_scan_duplicate_registry_snapshot registry-snapshot 915.2 KiB 13 217.21ms 215.40ms -0.8% stable
warm-cache-rescan tests/benchmarks/test_scan_benchmarks.py::test_scan_warm_cached_repository_rescan release-candidate 547.3 KiB 32 65.31ms 64.81ms -0.8% stable
clean-training-checkpoint tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_clean_training_checkpoint safe_large 278.2 KiB 1 19.44ms 19.35ms -0.5% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_base64] nested_base64 98 B 1 412.6us 413.9us +0.3% stable
direct-malicious-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_direct_malicious_upload malicious_reduce 52 B 1 1.44ms 1.44ms -0.1% stable
single-checkpoint-preflight tests/benchmarks/test_scan_benchmarks.py::test_scan_single_checkpoint_before_load single_checkpoint.pkl 183.0 KiB 1 40.50ms 40.52ms +0.0% stable
chunked-upload-stream tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_chunked_upload_stream chunked_stream 278.2 KiB 1 22.29ms 22.28ms -0.0% stable

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a476aafcca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread modelaudit/utils/sources/jfrog.py
@mldangelo-oai mldangelo-oai marked this pull request as ready for review May 31, 2026 13:56
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 340a4f9677

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

parsed_ip = None

return parsed_ip is not None and parsed_ip.is_loopback
return parsed_ip is not None and (parsed_ip.is_loopback or parsed_ip.is_unspecified)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject IPv4-mapped loopback hosts

When MODELAUDIT_JFROG_ALLOWED_HOSTS contains an IPv4-mapped IPv6 literal like [::ffff:127.0.0.1], this check still returns false on Python 3.12 because IPv6Address.is_loopback does not consider the mapped IPv4 address, so the host remains in _get_trusted_jfrog_hosts() and download_artifact() sends explicit or env JFrog credentials to loopback. Fresh evidence beyond the earlier numeric-alias thread: the new regression added in this commit fails under uv run pytest tests/integrations/test_jfrog.py -q for [::ffff:127.0.0.1].

Useful? React with 👍 / 👎.

parsed = urlparse(url)
hostname = _normalize_hostname(parsed.hostname or "")
if parsed.scheme != "https" and not (parsed.scheme == "http" and _is_local_jfrog_host(hostname)):
if parsed.scheme != "https":
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve redaction for rejected JFrog URLs

After this change, plaintext or local JFrog-looking URLs return false here, so the CLI no longer enters the JFrog redaction path and falls through to the generic Path does not exist: {path} error in modelaudit/cli.py; for inputs such as https://user:pass@localhost/artifactory/repo/model.bin?token=... or http://localhost/..., the rejected URL is echoed with embedded credentials/query tokens instead of using redact_jfrog_url_for_display(). This is a regression for local JFrog URLs that were previously recognized as JFrog and redacted before failing the download path.

Useful? React with 👍 / 👎.


def _raise_for_jfrog_redirect(response: requests.Response, source_url: str) -> None:
"""Reject redirects so JFrog credentials never cross origin boundaries."""
if response.status_code in {301, 302, 303, 307, 308}:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow anonymous JFrog redirects

This redirect rejection is unconditional, so even public/anonymous JFrog artifacts with no explicit or environment credentials now fail as Refusing redirect... instead of following normal Artifactory CDN/object-storage redirects and scanning the file. The stated guard is to keep JFrog credentials from crossing origins, so the redirect should only be blocked when credentials are actually being sent; otherwise this breaks previously working public repositories that rely on redirects.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@ianw-oai ianw-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed; this looks acceptable.

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.

2 participants