Skip to main content

validate_index_url

Function validate_index_url 

Source
pub fn validate_index_url(
    candidate: &str,
    raw_for_log: &str,
    ecosystem: &'static str,
    gate: PolicyGate<'_>,
) -> Result<Url, IndexUrlError>
Expand description

Validates a candidate registry/index URL: https scheme, no userinfo, and — when gate is PolicyGate::Enforce — a host the live RegistryAccessPolicy allows.

candidate is the string actually parsed (e.g. deps-npm’s already ${VAR}-expanded value); raw_for_log is what an error payload and the blocked-host tracing::warn! name instead — the pre-expansion .npmrc value for deps-npm, or the same string as candidate for deps-cargo/deps-pypi (neither has an expansion step). This split keeps an environment variable’s expanded value out of any log line or error a caller might surface in a diagnostic. ecosystem is carried on the blocked-host warning only, to tell deps-cargo/deps-npm/deps-pypi call sites apart in the logs.

The check order — parse, then https, then userinfo, then the policy gate — is load-bearing: userinfo is rejected before the policy gate runs, which is what lets a caller safely log raw_for_log unredacted on a IndexUrlError::BlockedHost warning, since a userinfo-bearing candidate can never reach that point. Do not reorder.

IndexUrlError::InvalidUrl is the one variant this invariant can’t cover — candidate failed to parse before any userinfo check could run, so raw_for_log might still carry one (S1 finding: an otherwise-valid user:pass@host URL can fail to parse for an unrelated reason, e.g. an invalid port). redact_userinfo is applied to raw_for_log before it is wrapped in IndexUrlError::InvalidUrl, so every caller — deps-cargo, deps-npm, deps-pypi — gets this for free, whether or not it separately redacts its own raw before logging.

§Errors

Returns IndexUrlError if candidate does not parse as a URL, is not https (outside the cfg(test)/test-util loopback carve-out), carries a userinfo component, or (under PolicyGate::Enforce) resolves to a host class the current policy blocks.

§Examples

use deps_core::net_policy::{PolicyGate, validate_index_url};

let url = validate_index_url(
    "https://index.mycorp.dev",
    "https://index.mycorp.dev",
    "cargo",
    PolicyGate::Skip,
)
.unwrap();
assert_eq!(url.as_str(), "https://index.mycorp.dev/");

assert!(
    validate_index_url("http://example.com", "http://example.com", "cargo", PolicyGate::Skip)
        .is_err()
);