Repository navigation
Conversation
UX Review (Opus 5.5, fork) — ⏭️ skippedRevision |
Design Review (Opus 5.5, fork) — ✅ PASSDesign-level review of Design-Verdict: PASS Nothing blocks: the relaxation is a narrow allow-list of one shape that returns any other text unchanged, and the new payload sources can only add refusals. Notes
[DESIGN-REVIEWED] 5f189da Description read[DESCRIPTION-READ] 7782606ebd25a9979b32d70de9e48f710a7c0aaeee53b9e51d9174336568d310 That sha256 names everything this verdict read: the PR description, plus the 1 evidence file(s) the workflow collected from it and handed this review. It covers that evidence because the media strip replaces every attachment URL with the same placeholder, so an edit swapping one attachment for another would leave the description's captured text identical while what this review judged changed. Recompute it with |
First Principles Review (Opus 5.5, fork) — ✅ PASSPremise-level review of First-Principles-Verdict: PASS Nothing blocks. The payload-walk riders are an unrelated pre-existing bypass and redundant hole-closers, which the backslash guard mostly makes moot. Notes
What this change shipsInventory (10 items) — 7 justifiedIntent: let agents open gh PRs, issues and releases whose multi-line body contains a
[FIRST-PRINCIPLES-REVIEWED] 5f189da Description read[DESCRIPTION-READ] 410d9249675a130b1413c8828467e2266dedb77acafe7486f046d25e51064f3d That sha256 names the PR description this verdict read. Recompute it with |
Opus 5.5 Review (fork) — ✅ no blocking findingsReviewed |
GPT 6.1 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
Security Scope Review (fork) — ✅ PASSWhich legitimate operations does adjudicated, zero confirmed regressions Scope-Verdict: PASS Reason: The tightening adds sources to the git-publish floor only, and only for commands that contain a backslash: each nested shell payload is also read the way bash reads it, without printf decoding. All of it runs through the shell deny composite, so the candidates below can be adjudicated. The harness has not confirmed any regression yet. Windows coverage is limited to spellings that contain a backslash, and the per-leg verdicts come from the fold, not from this review. TIGHTENING: git-publish floor payload sources in ADJUDICATED: 15 candidates, 0 confirmed newly-refused PLATFORM COVERAGE: The diff assumes three things about platform spelling: a backslash anywhere in the command triggers the undecoded walk, a newline is a separator, and [SCOPE-REVIEWED] 5f189daSecurity scope review -- adjudicated candidates
No candidate flipped from allowed to refused. |
5cfa597 to
4f965df
Compare
4f965df to
62f8c7d
Compare
62f8c7d to
55b4419
Compare
55b4419 to
a41888b
Compare
ff8ebe6 to
4c6c008
Compare
4c6c008 to
76e12e8
Compare
dodgeblaster
left a comment
There was a problem hiding this comment.
Review — fixes #20846, blocked only by the fork + sensitive-path structure
I verified this change behaviourally against the gate on this PR's head (02e9f2e3e5) and read the full diff. The fix is correct and the reds are all structural fork gates, not code defects.
Behavioural verification (is_denied on head vs. origin/main): all pass.
| case | verdict |
|---|---|
gh pr create --body "notes⏎git push⏎more" (the issue repro, double and single quotes) |
now allowed ✅ |
gh issue comment -b "…⏎git push origin main⏎…", gh release create --notes "…⏎git push⏎…" |
now allowed ✅ |
one-line gh pr create --body "notes git push more" |
allowed on both (unchanged) ✅ |
real bare git push on its own line after the body, and after && |
still denied ✅ |
gh pr merge -m "…⏎git push⏎…" (-m is the boolean --merge here, not a data flag) |
still denied (per-line reading kept) ✅ |
bash -c '…git push…' wrapper |
still denied (conservative, nested reading unchanged) ✅ |
The narrowing is exactly the stated shape: one simple gh pr|issue|release command of plain words + whole quoted words, the push line only spaced when it is the value of -b/--body, -t/--title, --subject or -n/--notes. Anything with a separator / expansion / escape / other owner outside the quotes is returned unchanged and keeps today's verdict. _QUOTED_NEWLINE_MAY_END_COMMAND correctly keeps the old per-line reading on Windows, where cmd.exe can end a command at a quoted newline. It only ever moves the gate in the allow direction, for this one data-only shape — it fails closed on everything it cannot prove, so it is not a bypass.
Diff quality is good: the owning spec (docs/system-specs/modules/security.md) gets the matching bullet, the _PACKAGE_LINE_BUDGET re-pin carries its reason, and TestQuotedGhTextValueIsNotAPush pins 5 allow + 32 deny + 5 Windows cases with a mutation check.
Why CI is red — all structural, none a code defect:
- Sensitive Change Review fails by design: this is a fork PR and it touches
src/kiro_crew/security/*, which the gate lists as a sensitive glob. Its own message says it plainly — "A fork PR cannot pass this gate. A maintainer takes it over on a branch of this repository (keep the author withCo-authored-by:and writeSupersedes #<n>), runs the real sandbox, and drives that PR green." - Coverage Gate (
frontend-test=skipped — failing closed) and Harness Parity Gate (x-capture) fail closed downstream because the heavy jobs are skipped on the fork fast-path. - Await Fast Gate / PR Readiness just aggregate the above.
Recommendation: the change is sound and ready. Because it is a fork PR touching a sensitive security path, it cannot clear CI as-is, and I can't push to the fork branch. A maintainer should take it over onto a branch of this repository per the Sensitive Change Review instructions — Co-authored-by: Marcello Quarta <…>, Supersedes #20853 — run the real sandbox, and drive it green. Nothing in the code needs to change for that.
|
Rebased onto current Thanks @dodgeblaster for the review. Could a maintainer approve the fork workflows on |
|
Re the GPT 6.1 blocking finding on 329c88c ( Repro on 329c88c: all 5 allow cases pass Fix: Tests ( Sweep: the 42-command probe, run bare and prefixed against Could a maintainer approve the fork workflows on dcafc72? Thanks. |
|
Hold at 1fac724. This is reserved for a human reviewer.
I found no concrete bypass. Glued quotes, expansions inside double quotes, curly quotes, — crew-pr-reviewer (r119) |
|
@iamwhatever thanks for the r119 review. I've rebased it onto today's As you say, only a maintainer can clear |
|
Thanks to the Opus 5.5 review on One correction for the record: this shape is allowed on
Checked:
The new head will need a maintainer to approve the fork workflows. Thanks! |
iamwhatever
left a comment
There was a problem hiding this comment.
Requesting changes at f3e3c8f.
This PR changes what the protected-branch push floor admits, so it stays reserved for a human security reviewer. Separately, the current head has a bypass that both AI lanes flagged and that I confirmed by reading the code:
echo $'gh pr create --body \\x27\ngit push origin main\n\\x27' | bash(or theprintf '%s' ... | bashform)._self_tokensANSI-C decodes the producer token; the evaluator-pipe branch then printf-decodes it unconditionally (shell_normalizer.py#L1393-L1404), even on the newprintf_decode=Falsewalk. The decoded payloadgh pr create --body '<NL>git push origin main<NL>'passes_gh_data_newlines_as_spaces, so the filter at deny_gate.py#L643-L646 drops it, and no other source holds a newline-led push. Bash reads\x27asx27, so the second line pushes tomain. Onmainthe decoded payload is still read line by line and denied, so this is a regression.
Smallest fix: pass printf_decode into _nested_shell_payloads so the pipe branch keeps the raw token when it is False (and add the pipe rows to TestPrintfEscapeInAShellPayloadIsNotAQuote), or drop a source only when every variant the walks produced for it reads as gh-only.
Also open on this head: Backend Tests (3.12, 3), Backend Tests (Windows) 3/5/7 and Coverage Gate are red, and Sensitive Change Review is cancelled.
— crew-pr-reviewer (r121 deep)
|
@iamwhatever thanks, and thanks to the Opus 5.5 and GPT 6.1 reviews on
You're right that the Checked:
On the red CI from the last run: the Backend Tests (3.12, 3) and Windows (3) failures were in Understood on the human security review. The new head will also need a maintainer to approve the fork workflows. Thanks! |
|
Thanks to the GPT 6.1 review on Cause. A Fix. In the evaluator-pipe branch, the bash-read walk (
Checked on
Could a maintainer please approve the workflow runs for |
|
Thanks to the Opus 5.5 and GPT 6.1 reviews on Cause (one root for both).
Fix (fail closed,
The Checked on
Could a maintainer please approve the workflow runs for |
|
Opus 5.5 and GPT 6.1 findings on f30a26b (printf FORMAT Root cause. The escape decoder reads Checked (stub git, real bash):
Line budget re-measured: 32,660. @iamwhatever @bolichen97 could you approve the fork workflow runs on 6ed2bff? The human security review request still stands. |
iamwhatever
left a comment
There was a problem hiding this comment.
Requesting changes at cdaf83d.
This PR loosens the protected-branch push floor, so it stays reserved for a human security reviewer even once the item below is fixed. The bypass from my r121 review is closed: a command holding any backslash, or a % other than %%, now keeps main's per-line reading (deny_gate.py#L651-L658), and the literal-body reading only accepts plain words and whole quoted words. I found no new bypass in that shape.
Defect: the security spec describes a different rule than the code. security.md#L1738 says the reading is withheld for "a backslash before an upper-case letter (deny_gate._UPPER_ESCAPE_RE)". No such symbol exists at this head, and is_denied withholds it for any backslash. A reader auditing the floor from the spec gets the narrower, wrong rule. Smallest fix: change that clause to "any command holding a backslash (undecoded in deny_gate.is_denied)" and drop the symbol name. The Opus lane raised the same point on this head and it has no reply yet.
Also open: Sensitive Change Review is red on this head (the reasoning template is not posted for cdaf83daff), and Design and First Principles both suggest splitting the printf_decode=False walk into its own PR; please reply to those notes.
— crew-pr-reviewer (r124)
The push splitter ends a segment at every newline, quoted or not, so the middle line of `gh pr create --body "notes<NL>git push<NL>more"` was judged as a bare push (rule git-publish-push-bare) although bash hands the whole value to gh as one word. shell_normalizer_walk._gh_data_newlines_as_spaces reads one closed shape as its single-line spelling: the whole command is one `gh pr|issue|release ...` of plain words and whole literal quoted words (each closed, between blanks, no curly quote mark, no `$`/backtick/backslash in double quotes), and every multi-line quoted word is the value of -b/--body, -t/--title, --subject or -n/--notes. is_denied reads that view before it hands a source to the git-publish floor, so such a command is no publish and records no push_allowed audit. Every other text is returned unchanged and keeps its per-line reading. kiro-cli titles a shell call `Running: <command>` and the deny tiers judge that title as a subject of its own, so the helper reads through ONE exact leading `running: ` (the lowercased view) and keeps it: the title gets the reading of the command it displays. The constant moves from denied_rules to shell_normalizer_walk, below both readers, so _exception_applies and the helper share it. A second prefix, another spelling, or one that does not start the text is read as text. The payload walk printf-decodes every nested payload, so in `bash -c $'gh pr create --body \\x27<NL>git push origin main<NL>\\x27'` the `\x27` read as a quote and the push line as gh body text, while bash reads an unquoted `\x27` as `x27` and runs the push (also `\x22`, `\u0027`, `\047`, `sh -c`). Main allows it too. _shell_payload_walk gains printf_decode=False, and the publish gate also judges each payload as bash reads it, so the floor only adds sources and never drops one. The evaluator pipe gets the same reading: the bash-read walk passes printf_decode=False down to _nested_shell_payloads, so an `echo` or `printf '%s'` producer piped into bash or sh is judged by its undecoded token, as the shell on the other end reads it. The `printf '%s' ... | bash` form was let through by this change while main refused it; the `echo ... | bash` form is let through on main too. A printf FORMAT producer decodes exactly once, so `printf 'gh pr create --body \x5cx27\x0agit push origin main\x0a\x5cx27' | bash` prints `\x27`, a real newline and the push line, and bash runs the push. The decoded walk decoded it twice (making a quote) and the undecoded token had no newline, so neither view saw the push while main refused it. The bash-read walk now also yields the once-decoded producer text and never decodes it again. The gh-body reading only holds where the source IS the script the shell runs, and escape decoders break that. is_denied lowercases before the walk, so in `printf 'gh pr create --body \X27\x0a<push to main>\x0a\X27' | bash` (also `\X22`, `echo -e`) the `\X27` that printf prints as text, and the shell reads as `X27`, became `\x27` and decoded to a quote. A printf FORMAT reads `\0047` as `\004` + `7`, and bash's `echo -e` reads `\47` as text, yet the walk decoded both to a quote. And a printf FORMAT is yielded with its conversions unfilled: in `printf 'gh pr create --body "n%s\x0a<push to main>\x0a%s"' '"' ': "' | bash` the `%s` argument closes the body before the push line. All pushed main and were allowed, while main refuses them. The publish gate now spaces a source only when the command holds no backslash at all and the source holds no `%` other than `%%`; any other source keeps its per-line push reading, as on main. Feature-branch twins stay allowed and are now audited pushes. Closes kirodotdev#20846
|
@iamwhatever thanks for the r124 pass, and for confirming the r121 bypass is closed with no new one in that shape. Spec defect: fixed on the new head The same push also rebases onto today's Design + First Principles: "split the Sensitive Change Review: a fork PR can't post its reasoning template or pass that gate. As its own message says, a maintainer takes it over on a branch of this repository ( |
Problem / Motivation
Goal: A
gh pr|issue|releasecommand whose literal--body/--title/--notesvalue contains a line readinggit pushis allowed, while every real push and every shape the quote walk cannot prove keeps today's verdict.gh pr create --body "notes⏎git push⏎more"is refused withrule=git-publish-push-bare("the push names no branch …") although nothing pushes._split_push_command_segmentsends a segment at every newline, quoted or not, so the middle line of the quoted body is read as a baregit push. Single quotes refuse the same way; the same text on one line is allowed. Follow-up of #15438, which lists this as a non-goal (a different detector from the target-unverifiable rule it changes).Why it matters
Agents write PR and issue bodies as multi-line
gharguments all the time, and release notes or PR descriptions that say "rungit push" on their own line are ordinary. Each one is refused with a reason pointing at a push that does not exist, and the agent has to reword the body or retry. It fails closed, so it is a false positive, not a bypass.Not a goal
git commit -m,echo,printf,bash -c,sh -c,eval.bash -c/sh -c/evalrun their argument, andgit commit -mis fix(security): keep a quoted newline inside its word on the push path #15438's territory.ghas part of a compound command (cd r && gh …, a pipe, a redirect, an env prefix), aghvalue that is a positional or a non-text flag,gh api, and gh aliases/extensions. Those keep today's per-line reading.env PATH=… git pushprefix (push gate: an env-prefixed push after a multi-line commit message is refused #20847).What changed (motivation → approach → change)
Symptom: a quoted gh body line reading
git pushis refused as a bare push.Cause: the push splitter (and the
_GIT_PUBLISH_RE\nanchor) treat a newline inside a quoted argument as a command boundary.Change:
shell_normalizer_walk._gh_data_newlines_as_spaces(the lexical layer, beside_split_push_command_segments; re-exported fromshell_normalizer) returns the single-line spelling of one closed shape and the text unchanged otherwise. The shape is the whole command being onegh pr|issue|release …made of:[A-Za-z0-9._/:=+,-](no%, so no PowerShell--%stop-parsing token; no@splat), and'a''b'), holds no curly quote mark (PowerShell reads‘ ’ ‚ ‛ “ ” „as quotes), and, when double-quoted, no$, backtick or backslash;-b/--body,-t/--title,--subjector-n/--notes(-mis left out: ongh pr mergeit is the boolean--merge).The quote state comes from
_iter_shell_chars, the module's one quote/escape machine: the checks above run over its steps and the spaced view is rebuilt from them, each quoted newline as a space (First Principles review of 62f8c7d; same verdicts on the 42-command probe).With no separator, comment, heredoc, escape or expansion outside the quotes, bash's and PowerShell's quote reading of that text is the walk's, and gh is the only program the shell runs. On Windows the helper returns every text unchanged (
_QUOTED_NEWLINE_MAY_END_COMMAND = os.name == "nt"): cmd.exe ends a command at a newline even inside double quotes, and nothing proves which shell runs an agent's command there, so the old per-line reading stays. gh refuses an alias or extension named after a core command, sopr/issue/releasecannot be redefined to run their arguments.is_denied(deny_gate.py) filters publish sources on that view, so such a command is not a publish and records nopush_allowedaudit. That filter is the only place the view is read:_git_publish_floor_tagsonly ever receives sources that passed it, so it is unchanged.The shell-call title gets the same reading. kiro-cli titles a shell call
Running: <command>andGateFacts.deny_targetsjudges that title throughis_deniedbeside the command, so a title the helper rejected kept the old deny and the real tool call was still refused on the default harness (GPT 6.1 review of 329c88c). The helper now reads through ONE exact leadingrunning:(the lowercased view) and keeps it in the returned text. It reusesmain's_SHELL_TITLE_PREFIX, whichdenied_rules._exception_appliesalready strips the same way; the constant moves fromdenied_rulestoshell_normalizer_walk(re-exported fromshell_normalizer, imported back bydenied_rules) becausedenied_rulesimportsshell_normalizer. A second prefix,running:without the space,xrunning: …, or a prefix later in the text is read as text.The spaced view only ever equals the command's single-line spelling, which
mainalready allows. Rejected text is returned unchanged, so every other command reads exactly as onmain.docs/system-specs/modules/security.md: one bullet under the protected-branch gate.test_security_gate_liveness.py: package line budget re-pinned from 32,527 to 32,669 (measured onorigin/main@ ec2619c), with a reason comment.A printf escape in a
-cpayload is no quote (fail closed, pre-existing onmain)._shell_payload_walkprintf-decodes every nested payload, so inbash -c $'gh pr create --body \\x27⏎git push origin main⏎\\x27'the\x27read as'and the push line as gh body text, while bash reads an unquoted\x27asx27and runs the push (also\x22,\u0027,\047,sh -c,mainline; stub-git confirmed).mainand the earlier heads of this PR allow it too. The walk gainsprintf_decode=False, andis_deniedalso judges every payload as bash reads it as a publish source. It only adds sources, so no command refused before is allowed now.The same reading for an evaluator pipe. The bash-read walk passes
printf_decode=Falsedown to_nested_shell_payloads, so anecho $'…'orprintf '%s' $'…'producer piped intobash/shis judged by its undecoded token, as the shell on the other end reads it. Theprintf '%s' … | bashform was let through by the previous revision whilemainrefused it; theecho … | bashform is let through onmaintoo.A printf FORMAT decodes once.
printf 'gh pr create --body \x5cx27\x0agit push origin main\x0a\x5cx27' | bashprints\x27, a real newline and the push line, and bash runs the push. The decoded walk decoded it twice (making a quote) and the undecoded token had no newline, so neither view saw the push whilemainrefused it (GPT 6.1 on f211678;\x5cx22and octal\134x27too). The bash-read walk now also yields the once-decoded producer text and never decodes it again.The gh-body reading needs the literal script (Opus + GPT on 1069d2c).
is_deniedlowercases before the walk, so inprintf 'gh pr create --body \X27\x0agit push origin main\x0a\X27' | bash(also\X22,echo -e) the\X27that printf prints as text, and the shell reads asX27, became\x27and decoded to a quote. A printf FORMAT is also yielded with its conversions unfilled, so inprintf 'gh pr create --body "n%s\x0agit push origin main\x0a%s"' '"' ': "' | bash(also%b, single-quoted body) the%sargument closes the body before the push line. Both pushedmainunder stub git and were allowed;mainrefuses them. The decoder also misreads two more escapes (Opus + GPT on f30a26b): a printf FORMAT reads\0047/\0042as\004+7/2, and bash'secho -eprints\47/\42as text, yet the walk decoded all four to a quote, soprintf 'gh pr create --body \0047\x0agit push origin main\x0a\0047' | bashpushedmainand was allowed. The publish gate now spaces a source only when the command holds no backslash at all and the source holds no%other than%%; any other source keeps its per-line reading (fail closed: a body line pushingmainnext to any backslash,C:\Usersor50%is refused again, as onmain). Thefeat/xtwins stay allowed and are now audited pushes.Backwards compatibility
Compatible: the gate moves in the allow direction only for the one gh shape above; the printf-decode fix only moves commands to deny (13,969-command sweep vs 53e4d92: 308 flips, all allow to deny; 168 push a protected or unverifiable target under stub git, the other 140 are payloads whose bash-read text the gate already refuses when typed unwrapped). Every other command gets the same verdict and rule as on
main(probe below).Removes nothing: no rule, tag, export or reader is removed; the new helper only narrows when the push floor runs.
Tests
test/test_push_branch_gate.py::TestQuotedGhTextValueIsNotAPush:Every allow, deny and Windows row runs twice: as the command and as its
Running:title.test_a_push_line_in_a_literal_gh_text_value_is_allowed(5 cases: double/single quotes,-R/--head/--titleflags withgit push origin mainin the body,gh issue comment -b,gh release create --notes):is_deniedreturns None, nopush_allowedaudit.test_every_other_shape_keeps_its_per_line_reading(32 cases): the helper returns the text unchanged and the command is still denied. Covers a real push on its own line or after;/&&,$b/brace/$'main'targets, comment apostrophe, heredoc, backslash-newline, unbalanced and glued quotes,$(/backtick/escaped quote in a double-quoted value, PowerShell--%and curly-quote closers, positional /gh pr merge -m/ alias /gh apivalues,bash -c,sh -c,eval,git commit -m, env prefix,cd &&, pipe, redirect, subshell.test_only_one_exact_title_prefix_is_read_through(5 cases):xRunning:,Running:with no space,Running:+ tab,Running: Running:, and aRunning: git push origin mainline after a closed body. The helper returns each unchanged and each is denied.test_on_windows_a_quoted_newline_keeps_the_per_line_reading(the 5 allow cases): with_QUOTED_NEWLINE_MAY_END_COMMANDset, the helper returns the text unchanged and every one is denied. The class pins the flag off for the other rows through an autouse fixture on_floor_monkeypatch(so a test callingmonkeypatch.undo()cannot lift it), so they run alike on every CI platform.test/test_push_branch_gate.py::TestPrintfEscapeInAShellPayloadIsNotAQuote(19 cases): the 6 printf-escape payloads above, a double-quotedbash -ctwin, 5 evaluator-pipe rows (echo/printf '%s'intobash/sh) and 3 printf-FORMAT pipe rows are denied, thefeat/xtwins (direct, piped and printf-format) are allowed with theirpush_allowedaudit, and the real-quote$'…\'…'form keeps its body reading. 7 of the 9 fail on the previous head 53e4d92.test/test_push_branch_gate.py::TestPrintfOutputIsNotItsSourceText(16 cases): 11 rows pushingmain(\X27,\X22,echo -e,%s,%b, single-quoted%s, printf\0047/\0042, echo\47/\42, and a%%printf body, refused as onmain) are denied, the\X27,%s,\0047and echo\47feat/xtwins are allowed with theirpush_allowedaudit, and a literalghbody with no backslash keeps its body reading.Mutation check: with the helper forced to return its input, the 5 allow cases fail (the 32 deny cases still pass); the same 5 fail when only the
is_deniedfilter is reverted (the audit assertion). On 329c88c (no title read-through) the 5Running:allow rows fail and everything else passes.Run with
pytest -n 4:test_push_branch_gate.py,test_security_gate_liveness.py,test_argv_floor_inline_and_brace_scope.py,test_denied_commands_security.py,test_denied_commands_authority.py,test_security_facade.py,test_deny_guidance.py,test_inert_search_display_prefix.py,test_push_branch_gate_parser.py,test_security_split_patch_reach.py,test_denied_rules_facade.py,test_argv_floor_facade.pyandtest_denied_commands_security_*.py: 2171 passed, 1 skipped, 0 failed. black, isort, flake8, mypy on the touched sources,scripts/check_comment_history.py(baseorigin/main) andscripts/docs_lint.pypass.Manual verification
Verdict probe, 42 commands through
is_denied, each bare and as itsRunning:title, head vsorigin/main@ 098bc0a in a detached worktree:push-bare/push-protected-branch-nameon main): the 5 allow cases above, bare and as titles.gh pr create --body "x⏎"⏎git push origin main(protected-branch-name),… && git push origin ma$b/{main,x}/$'main'(target-unverifiable),bash -c 'gh pr create --body "a⏎git push⏎"'(push-bare: conservative, the nested reading is unchanged), and the single-linegh pr create --body "notes git push more"(allowed on both).Related Issues
Closes #20846
Follow-up of #15438 (listed there as a non-goal). Refs #12631.
Pattern harvest
Not generalizable: the class (a newline inside a quoted word read as a command boundary) is the splitter's deliberate fail-closed design; this PR proves one data-only owner rather than changing the splitter, and #15438 handles the commit-message owner.
Checklist
feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert: ...)Contribution License Agreement
Contributions are accepted under the project's Apache-2.0 license.