Skip to content

the hook could be redirected to any executable and doctor still said ok #49

Description

@MongLong0214

Reproduction

Recorded in commit 1fd0d53301edc0399a74cf244229269aee507b58:

The hook's own tamper detection could not see the channel that redirected it

commitlore hooks install
git config --local commitlore.bin /tmp/evil.sh
git commit -F <message with an invalid trailer key>
→ ATTACKER-RAN
→ the commit succeeded; validation never ran

and commitlore hooks status compared the stub byte for byte and doctor reported
the hook installed and healthy the whole time.

This is not a privilege escalation, and the fix does not pretend it is.
Measured: a malicious commitlore.bin does not survive git clone — neither
.git/config nor .git/hooks is transferred — and both sit behind the same
filesystem permission, so anyone who can set the config can overwrite the hook
directly. It is closed because our own integrity check looked at a channel the
hook does not use, and because writing a git config key is far quieter than
writing an executable into .git/hooks.

Two changes. The stub's catch-all branch — *) exec "$recorded" … — is gone: a
recorded path must end in .js or .mjs and run under the recorded interpreter,
which reduces "any executable" to "a JavaScript file run by a known node", the
authority the CLI already has. Anything else falls through to the remaining
resolution steps rather than being executed.

And hooks status and doctor now read the recorded paths and say so. A hook
whose stub is byte-perfect but whose recorded target is a stranger no longer
reports ok; it names the path, that it is not a .js, and that it sits outside
the package root. COMMITLORE_BIN is surfaced too — it legitimately overrides
everything, and an operator debugging a silent validation failure should see it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    epic:review-2026-07-27Retroactive tracking for the 2026-07-27 production re-review

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions