fix(git-sync): run auto-pull as the admin who enabled it (#11121)

* fix(git-sync): run auto-pull as the admin who enabled it

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(git-sync): audit the admin grant fork pulls make

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: bump ee ref for the post-commit fork grant audit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(git-sync): address review nits on the auto-pull stamp

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: update ee-repo-ref to ccada062c072d7b74894b63863728fd1ef9bdffd

This commit updates the EE repository reference after PR #799 was merged in windmill-ee-private.

Previous ee-repo-ref: 7cee30f0cf12721cba551cd754dc817444810470

New ee-repo-ref: ccada062c072d7b74894b63863728fd1ef9bdffd

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
hugocasa
2026-09-15 10:34:57 +02:00
committed by GitHub
co-authored by Claude Opus 5 windmill-internal-app[bot]
parent 082d897328
commit 69e6efd875
20 changed files with 481 additions and 43 deletions
@@ -910,12 +910,15 @@ fn redact_git_sync_webhook_secrets(git_sync: &mut serde_json::Value) {
}
/// Zero the server-owned auto-pull fields (webhook id/secret/url/error, synced
/// sha, last pull status) on a client-supplied `AutoPullSettings`. The client only
/// controls `enabled` / `mode` / `poll_interval_s`; the rest is written by the
/// server (webhook creation, poller) and must never be trusted from the request —
/// otherwise a caller could inject a webhook id/secret or fake sync state.
fn clear_client_supplied_auto_pull_state(
/// sha, last pull status) on a client-supplied `AutoPullSettings`, and stamp who
/// pulls run as: `saver_email` while auto pull is on. The client only controls
/// `enabled` / `mode` / `poll_interval_s`; the rest is written by the server (webhook
/// creation, poller, this save) and must never be trusted from the request —
/// otherwise a caller could inject a webhook id/secret, fake sync state, or pick who
/// pulls run as.
fn sanitize_client_auto_pull(
auto_pull: &mut windmill_common::workspaces::AutoPullSettings,
saver_email: &str,
) {
auto_pull.webhook_id = None;
auto_pull.webhook_secret = None;
@@ -923,6 +926,28 @@ fn clear_client_supplied_auto_pull_state(
auto_pull.webhook_error = None;
auto_pull.last_synced_sha = std::collections::HashMap::new();
auto_pull.last_pull_status = None;
auto_pull.enabled_by = auto_pull.enabled.then(|| saver_email.to_string());
}
#[cfg(test)]
mod sanitize_client_auto_pull_tests {
use windmill_common::workspaces::AutoPullSettings;
#[test]
fn a_save_stamps_the_saver_over_any_client_supplied_stamp() {
let mut ap = AutoPullSettings {
enabled: true,
enabled_by: Some("forged@example.com".to_string()),
..Default::default()
};
super::sanitize_client_auto_pull(&mut ap, "saver@example.com");
assert_eq!(ap.enabled_by.as_deref(), Some("saver@example.com"));
ap.enabled = false;
ap.enabled_by = Some("forged@example.com".to_string());
super::sanitize_client_auto_pull(&mut ap, "saver@example.com");
assert_eq!(ap.enabled_by, None, "auto pull off carries no stamp");
}
}
/// Whether a git-sync repository tracking `tracked` rules out `label_branch` as a dev workspace's
@@ -3983,7 +4008,7 @@ async fn edit_git_sync_config(
// stay clean.
for repo in git_sync_settings.repositories.iter_mut() {
if let Some(ap) = repo.auto_pull.as_mut() {
clear_client_supplied_auto_pull_state(ap);
sanitize_client_auto_pull(ap, &authed.email);
}
repo.open_pr_error = None;
repo.credential = None;
@@ -4230,7 +4255,7 @@ async fn edit_git_sync_repository(
// existing repo re-derives it from the DB (carried over below) and a new one
// starts clean.
if let Some(ap) = new_config.repository.auto_pull.as_mut() {
clear_client_supplied_auto_pull_state(ap);
sanitize_client_auto_pull(ap, &authed.email);
}
new_config.repository.open_pr_error = None;
new_config.repository.credential = None;