Skip to content

pre-commit hands validators git-QUOTED paths, so non-ASCII filenames are silently skipped (6 validators) #972

Description

@hyperpolymath

Finding

.githooks/pre-commit builds the staged-file list for every validator with:

target_files=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true)

git diff --cached --name-only quotes any path containing non-ASCII bytes,
because core.quotePath defaults to true. The validators then iterate that
list and do [ -f "$file" ] || continue, which is false for the quoted string —
so the file is silently skipped, and CHECKED is never incremented, so the
denominator under-reports too.

A validator that skips what it cannot name reports a pass.

Measured, not inferred

$ git init -q . && printf '// SPDX-License-Identifier: MPL-2.0\n' > 'café.rs' && git add -A
$ git config core.quotePath        # unset -> default true
$ git diff --cached --name-only
"caf\303\251.rs"
$ n=$(git diff --cached --name-only | head -1); [ -f "$n" ] && echo FOUND || echo "NOT FOUND"
NOT FOUND

Scope

The list is built in the shared callers, run_validator (.githooks/pre-commit:45)
and run_validator_required (:63), so this is not a validate-spdx.sh bug —
it affects every validator fed by target_files.

| Validator | Uses the list | [ -f ] || continue | Affected |
|---|---|---|---|
| validate-k9.sh | yes | yes | yes |
| validate-spdx.sh | yes | yes | yes |
| validate-spdx-workflows.sh | yes | yes | yes |
| validate-sha-pins.sh | yes | yes | yes |
| validate-permissions.sh | yes | yes | yes |
| validate-bot-directives.sh | yes | yes | yes |
| validate-lint-format.sh | yes | no | passes a non-existent path to a linter |
| validate-codeql.sh | no | — | no |
| validate-gitleaks.sh | no | — | no |

The secret gate is NOT affected, and that is worth stating explicitly:
validate-gitleaks.sh:54 runs gitleaks protect --staged, which reads the
index directly and never sees target_files. A staged secret in a non-ASCII
path is still caught.

Why it is not hypothetical here

The estate already contains a literal-space directory _RSR _SET. The
word-splitting half of this problem was fixed in validate-spdx.sh (the
<<< / IFS= read -r loop, with a comment recording exactly that casualty).
The quoting half was not, and it is the same class of defect: the path the
validator is handed is not the path on disk.

Acceptance criteria

  1. git -c core.quotePath=false diff --cached --name-only in both
    run_validator and run_validator_required — fix it at the shared
    caller
    , not in six validators, so a seventh validator cannot reintroduce it.
  2. -z is a real answer: a path that reaches a validator and is not on disk
    must be an error, not a continue. The silent skip is what made this
    invisible; changing the quoting without changing the skip leaves the next
    instance just as silent.
  3. A regression test under scripts/tests/ staging a file with a non-ASCII
    name and asserting the validator's CHECKED denominator includes it.
    ⚠ It must fail against the current code — a green suite against both
    versions proves nothing.

Found while working #967 / #970. Filed separately rather than widening #961,
which is merged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions