diff --git a/docs/deployment.md b/docs/deployment.md index efa1ffb..546052f 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -147,8 +147,6 @@ These are known deployment risks tracked as follow-up work: - Queue events are shape-validated but not authenticated. Protect `$GIT_DIR/sip/queue` with service-owned permissions and add event signing or a MAC before relying on queue provenance. -- Queued event refs need the same `git check-ref-format` validation used for - protected workflow refs. - Pull and merge namespaces should remain rejected until their system-owned semantics are defined. - Wasmtime resource limits are not yet configured. diff --git a/src/main.rs b/src/main.rs index bb119c2..2a6804e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -185,7 +185,7 @@ fn run_worker(repo: &Path) -> Result<(), String> { .ok_or_else(|| format!("invalid queue filename {}", event_path.display()))? .to_string(); - let event = match parse_event(&event_path) { + let event = match parse_event(repo, &event_path) { Ok(event) => event, Err(_) => { fail_event(&event_path, &dirs.failed, &name)?; @@ -240,7 +240,7 @@ fn git_dir(repo: &Path) -> Result { } } -fn parse_event(path: &Path) -> Result { +fn parse_event(repo: &Path, path: &Path) -> Result { let body = fs::read_to_string(path) .map_err(|err| format!("could not read {}: {err}", path.display()))?; let mut lines = body.lines(); @@ -270,6 +270,9 @@ fn parse_event(path: &Path) -> Result { if !(reference.starts_with("refs/heads/") || reference.starts_with("refs/tags/")) { return Err("invalid event ref namespace".to_string()); } + if !git_status(repo, ["check-ref-format", reference])? { + return Err("invalid event ref format".to_string()); + } if actor.is_empty() || !actor.bytes().all(is_actor_byte) { return Err("invalid actor".to_string()); } diff --git a/tests/integration.rc b/tests/integration.rc index 61ba7a0..5a4e38d 100755 --- a/tests/integration.rc +++ b/tests/integration.rc @@ -440,6 +440,10 @@ fn test_malformed_event_is_failed { printf '1\tbad\tbad\trefs/heads/main\tactor\t0\tcreate\n' >$remote^/sip/queue/bad.event printf '2\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads/main\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-version.event printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/notes/main\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-ref.event + printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads/../ci/pwn\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-ref-traversal.event + printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads//x\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-ref-slash.event + printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads/topic.lock\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-ref-lock.event + printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads/bad..name\tactor\t1\tcreate\n' >$remote^/sip/queue/bad-ref-dotdot.event printf '1\t0000000000000000000000000000000000000000\t1111111111111111111111111111111111111111\trefs/heads/main\tactor\t1\tupdate\n' >$remote^/sip/queue/bad-kind.event $root^/bin/sip-worker.rc $remote >/dev/null >[2]/dev/null @@ -449,6 +453,14 @@ fn test_malformed_event_is_failed { fail unsupported event version should move to failed queue if(! test -f $remote^/sip/failed/bad-ref.event) fail unknown event ref namespace should move to failed queue + if(! test -f $remote^/sip/failed/bad-ref-traversal.event) + fail traversal-like event ref should move to failed queue + if(! test -f $remote^/sip/failed/bad-ref-slash.event) + fail event ref with double slash should move to failed queue + if(! test -f $remote^/sip/failed/bad-ref-lock.event) + fail event ref with lock suffix should move to failed queue + if(! test -f $remote^/sip/failed/bad-ref-dotdot.event) + fail event ref with dotdot should move to failed queue if(! test -f $remote^/sip/failed/bad-kind.event) fail inconsistent event kind should move to failed queue }