mirror of
https://github.com/bahdotsh/wrkflw.git
synced 2026-05-18 05:05:35 +02:00
fix(executor): add User-Agent header and handle auth redirects properly
The action resolver was making HTTP requests to raw.githubusercontent.com with no User-Agent header, which is the kind of thing that gets you silently rate-limited by GitHub's CDN. Not great when your whole resolution strategy depends on those requests actually succeeding. While at it, the no-redirect policy on the authenticated retry path was *correct* for preventing token leakage to non-GitHub hosts, but it also meant that legitimate CDN redirects (3xx) would fall through to the success check and produce a misleading "HTTP 301 fetching..." error. Fix this by following the redirect with HTTP_CLIENT (no auth header) when we get a 3xx, so we get the content without leaking the token. Also add a note on the SHA-1 detection in shallow_clone — it only matches 40-char hex strings, which will need updating if GitHub ever adopts SHA-256 refs.
This commit is contained in:
@@ -76,6 +76,7 @@ static ACTION_CACHE: Lazy<RwLock<BoundedCache>> = Lazy::new(|| RwLock::new(Bound
|
||||
static HTTP_CLIENT: Lazy<reqwest::Client> = Lazy::new(|| {
|
||||
reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(5))
|
||||
.user_agent("wrkflw")
|
||||
.build()
|
||||
.expect("Failed to create HTTP client")
|
||||
});
|
||||
@@ -133,15 +134,40 @@ async fn fetch_and_parse(
|
||||
if let Ok(token) = std::env::var("GITHUB_TOKEN") {
|
||||
let no_redirect_client = reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(5))
|
||||
.user_agent("wrkflw")
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.build()
|
||||
.map_err(|e| format!("Failed to create HTTP client: {}", e))?;
|
||||
no_redirect_client
|
||||
let auth_response = no_redirect_client
|
||||
.get(&url)
|
||||
.header("Authorization", format!("token {}", token))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("Failed to fetch {}: {}", url, e))?
|
||||
.map_err(|e| format!("Failed to fetch {}: {}", url, e))?;
|
||||
|
||||
// The no-redirect policy prevents token leakage, but the server may
|
||||
// legitimately redirect (CDN routing). If we get a 3xx, follow it
|
||||
// without the auth header to avoid leaking the token.
|
||||
if auth_response.status().is_redirection() {
|
||||
if let Some(location) = auth_response.headers().get(reqwest::header::LOCATION) {
|
||||
let redirect_url = location
|
||||
.to_str()
|
||||
.map_err(|_| "Invalid redirect URL encoding".to_string())?;
|
||||
HTTP_CLIENT
|
||||
.get(redirect_url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("Failed to follow redirect {}: {}", redirect_url, e))?
|
||||
} else {
|
||||
return Err(format!(
|
||||
"HTTP {} (redirect with no Location header) fetching {}",
|
||||
auth_response.status(),
|
||||
url
|
||||
));
|
||||
}
|
||||
} else {
|
||||
auth_response
|
||||
}
|
||||
} else {
|
||||
response
|
||||
}
|
||||
|
||||
@@ -642,6 +642,8 @@ async fn shallow_clone(
|
||||
git_ref: &str,
|
||||
target_dir: &Path,
|
||||
) -> Result<(), ExecutionError> {
|
||||
// NOTE: This only detects SHA-1 (40 hex chars). Git's SHA-256 transition uses
|
||||
// 64-char hashes — update this check if/when GitHub adopts SHA-256 refs.
|
||||
let is_sha = git_ref.len() == 40 && git_ref.chars().all(|c| c.is_ascii_hexdigit());
|
||||
|
||||
if is_sha {
|
||||
|
||||
Reference in New Issue
Block a user