GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Preserve Git config escape semantics by Byron · Pull Request #2213 · gitpython-developers/GitPython

Conversation

@Byron

@Byron Byron commented Aug 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Tasks

This section is for Byron only. Models continuing this PR must not add, remove, check, uncheck, rename, or reorder checkboxes here.

  • refackiew

Everything below this line was generated by Codex GPT-5.

Created by Codex on behalf of Byron. Byron will review before this is ready to merge.

Reported issue

P1 Badge Preserve Git semantics for quoted escaped values

When an existing config contains a standard quoted escape such as k = "first\nsecond", _read() retains the quoted spelling because it does not decode single-line quoted values containing escapes. Re-escaping that representation here rewrites it as data, so an unrelated update makes Git see literal outer quotes and a literal \n rather than the original newline; quoted backslashes and escaped quotes are similarly altered. Normalize these parsed values before escaping, or preserve their original representation.

P1 Badge Keep non-ASCII text intact through the escape decoder

When a value combines non-ASCII text with any trigger for this branch, such as café\path or a non-ASCII value containing a tab, this forced multiline form is later processed by _read()'s string_decode, which encodes using the filesystem encoding and decodes with unicode_escape. On UTF-8 systems that changes café to café; GitPython therefore returns corrupted data after the first write, and a later unrelated write persists the mojibake into the config file. Escape decoding needs to operate without reinterpreting the encoded non-ASCII bytes.

Also:

The new writer escapes LF/tab/backspace/quote/backslash, but it still allows carriage returns and NULs to be written verbatim. Because the reader’s string_decode(...).decode('unicode_escape') can materialize \r or \x00 into actual \r/\x00 characters in-memory, an attacker-controlled config could be rewritten into a file containing unsafe control characters when an unrelated write occurs. Please either (a) escape \r during serialization (similar to \n) and (b) reject NULs on write, or otherwise ensure \r/NUL cannot reach disk.

Fix

  • Decode Git's quoted value escapes without passing non-ASCII text through unicode_escape.
  • Normalize existing single-line quoted escaped values before serialization.
  • Reject parsed CR and NUL values before opening or truncating the destination config.

Git behavior was checked against cf5497b14c5a, specifically config.c::parse_value().

Validation

  • pytest -q test/test_config.py — 37 passed, 2 skipped
  • ruff check git/config.py test/test_config.py
  • ruff format --check git/config.py test/test_config.py
  • mypy git/config.py
  • git diff --check
  • pre-commit run --all-files
  • Codex review completed for c35c2ac8; its P1 pre-truncation validation finding was fixed.
  • Codex review completed without findings for 1c015bd5.
  • Codex review completed without findings for ef3fb518 after the CI lint fix.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

chatgpt-codex-connector[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@Byron
Byron force-pushed the config-sanitizer-follow-up branch from 1c015bd to ef3fb51 Compare August 10, 2026 12:52
@Byron Byron linked an issue Aug 11, 2026 that may be closed by this pull request
Using # or ; in config values #2214
Closed
@Byron
Byron force-pushed the config-sanitizer-follow-up branch 2 times, most recently from fa66d1e to cc7b973 Compare August 11, 2026 11:57
@Byron
Byron marked this pull request as ready for review August 11, 2026 11:57
Copilot AI lite review requested due to automatic review settings August 11, 2026 11:58
Copilot started reviewing on behalf of Byron August 11, 2026 11:59
View session
Copilot AI reviewed Aug 11, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates GitConfigParser’s read/write behavior to preserve Git’s config quoted-escape semantics (e.g., \n, \", \\) without corrupting non-ASCII text, and adds safety checks to prevent rewriting configs that would emit unsafe control characters.

Changes:

  • Replace the unicode_escape-based escape decoder with a Git-oriented backslash escape translation that avoids non-ASCII mojibake.
  • Decode well-formed single-line quoted values with backslash escapes, while preserving malformed quoted values containing unescaped quotes.
  • Add write-time validation to abort rewrites if any stored value contains CR or NUL; expand writer quoting triggers and add regression tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
git/config.py Adjusts quoted escape decoding, expands quoting rules during serialization, and rejects CR/NUL values before truncating/writing.
test/test_config.py Extends writer escaping tests and adds coverage for preserving escaped + non-ASCII values, plus CR/NUL rewrite rejection.
Suppressed comments (1)

test/test_config.py:236

  • The subprocess assertion compares git config --get output bytes to value.encode() (UTF-8). Since GitConfigParser writes the file using defenc, and git config will output the raw bytes it reads, this comparison should also use defenc to avoid false failures when defenc != 'utf-8'.
                self.assertEqual(
                    subprocess.run(
                        ["git", "config", "--file", config_path, "--get", "section.%s" % key],
                        stdout=subprocess.PIPE,
                        check=True,
                    ).stdout,
                    value.encode() + b"\n",
                    "git should read rewritten values with the same semantics",

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread test/test_config.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Byron @codex
Preserve Git config value semantics
eefa7e4
<!-- agent -->
Decode Git-supported quoted value escapes directly instead of routing UTF-8 text
through Python unicode_escape. This preserves newlines, quotes, backslashes, and
non-ASCII text when an unrelated config update rewrites existing values.

Quote values containing Git comment delimiters (# and ;) or leading/trailing
whitespace so Git does not truncate or trim their data. Escape LF, tab,
backspace, quote, and backslash, while rejecting carriage returns and NULs
before opening the destination.

Regression coverage round-trips these values through both GitPython and git
config and verifies unsafe control characters cannot alter the original file.
Behavior follows Git config.c parse_value() and write_pair().

Assisted-by: GPT 5.6
Co-authored-by: GPT 5.6 <[email protected]>
Copilot AI review requested due to automatic review settings August 11, 2026 12:20
@Byron
Byron force-pushed the config-sanitizer-follow-up branch from cc7b973 to eefa7e4 Compare August 11, 2026 12:20
Copilot started reviewing on behalf of Byron August 11, 2026 12:21
View session
Copilot AI reviewed Aug 11, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

git/config.py:786

  • In the CR/NUL preflight check, _value_to_string(raw_value) is called twice per value. This is redundant work and can be surprisingly expensive if _value_to_string does non-trivial formatting. Compute it once and reuse it for both checks.
                    for raw_value in values:
                        if "\r" in self._value_to_string(raw_value) or "\x00" in self._value_to_string(raw_value):
                            raise ValueError("Git config values must not contain CR or NUL")

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@Byron
Byron merged commit 4b9afe9 into main Aug 11, 2026
54 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@Byron
Byron deleted the config-sanitizer-follow-up branch August 11, 2026 13:11
@JingHao-Leon JingHao-Leon mentioned this pull request Oct 19, 2026
fix(config): decode escapes in unquoted config values #2297
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Using # or ; in config values

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@Byron
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.