OWASP / OWASP/OpenCRE

DiffParser silently drops or misattributes diffs for non-ASCII / space-containing file paths

Open
#1,032 4 comments 0 reactions 1 assignee View on GitHub

@DevPatils is already working on this.

Since Sep 6, 2026.

bug
Dominant language
Python
Stars
180
Forks
137
Avg merge
3d 23h
Merged PRs (30d)
21

Description

Description

application/utils/harvester/diff_parser.py's DiffParser.parse() extracts changed files from a git diff using a regex on the diff --git a/<path> b/<path> header line: match = re.match(r"diff --git a/(.+?) b/", line) then current_file = match.group(1) if match else None.

This regex makes two incorrect assumptions about real-world git diff output, causing two distinct failure modes: silent data loss for non-ASCII filenames, and silent path corruption for filenames containing " b/".

Reproduction

I wrote a small, self-contained script that creates a real temporary git repository, commits real files, generates a real git diff from it, and runs that through the actual DiffParser class — no mocked/synthetic diff text, just real git output.

Bug reproduction video:

https://github.com/user-attachments/assets/d8c8442a-3efd-4596-80d9-4dbba8f308fa

Expected behavior

  • Bug A: should return 1 DiffBlock with file_path='café.md' and added_lines=['added line']
  • Bug B: should return 1 DiffBlock with file_path='foo b/bar.md'

Actual behavior

  • Bug A: returns 0 blocks — the entire change is silently discarded, no error or warning
  • Bug B: returns 1 block, but with file_path truncated to 'foo', silently mis-attributing the change to a nonexistent path

Root cause

The regex in diff_parser.py:39 assumes the header always starts with a literal a/ and that the first " b/" substring found is the real separator. Neither assumption holds:

  • Git C-quotes (wraps in "...", escapes non-ASCII bytes) any path with non-ASCII characters by default (core.quotePath=true is git's default), so the header doesn't start with a literal a/ at all in that case — the regex simply fails to match.
  • The non-greedy match stops at the first " b/" substring in the line, which is ambiguous whenever the real file path itself contains that exact substring.

Existing tests in application/tests/harvester_test/diff_parser_test.py only cover plain ASCII, single-word filenames with no path-quoting or embedded " b/" — this class of edge case is completely untested.

Impact

The harvester watches external standard repositories for changes so OpenCRE can stay in sync. A real update to a file with a non-ASCII name (plausible for translated/localized docs in an international project) would be silently missed entirely — no error, no log, just as if the change never happened. A file whose path contains " b/" would have its change detected but filed under the wrong document identity, corrupting downstream traceability.

Suggested fix direction

Parse the file path from the --- a/<path> / +++ b/<path> lines instead of the diff --git header line — git provides these separately per side, avoiding the ambiguity of a single combined header line. Would also need proper un-quoting of git's C-quoted path format. Happy to open a PR for this.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.