Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/morwn/github-threat-detector/llms.txt

Use this file to discover all available pages before exploring further.

Commit metadata is easy to forge. Git does not enforce any relationship between an author’s claimed identity, their email address, or the timestamps embedded in a commit object — and GitHub faithfully records whatever the client sends. Two distinct attack techniques exploit this: rebase injection, where an attacker backdates malicious commits to blend into historical activity; and tooling fingerprints left by specific attacker frameworks that incorrectly serialize commit metadata. Both rules in this category require commit data collected via --commits and are critical severity.

commit-date-gap

Severity: critical
Required data: Commits (--commits)

What it detects

A commit where the committer date is more than 90 days later than the author date. In normal development, these two timestamps are nearly identical or differ by at most a few days (e.g. a long-lived feature branch). A gap exceeding 90 days indicates the commit was authored far in the past but only recently introduced into the repository’s history — the hallmark of a rebase injection attack.

How rebase injection works

In a rebase injection attack, an attacker:
  1. Creates a malicious commit and backdates its author timestamp to a point in the past when the repository was presumably less scrutinized — for example, a date before the current maintainers joined the project.
  2. Performs an interactive rebase (git rebase -i) to splice the backdated commit into the middle of the repository’s history.
  3. Force-pushes the rewritten history to the default branch.
The commit appears in git log between legitimate commits from months or years ago, making it far less likely to be noticed during a normal code review or audit. The author date is the forged past timestamp; the committer date is the actual time the rebase occurred — and this gap is what the rule detects. The threshold is defined in commit_tamper.py:
DATE_GAP_DAYS = 90

How detection works

The analyzer queries the push_commits table (populated by --commits) for rows where committer_date exceeds author_date by more than 90 days.
SELECT sha, repo_name, author_login, author_date,
       committer_login, committer_date, message_headline, before_sha
FROM push_commits
WHERE author_date IS NOT NULL
  AND committer_date IS NOT NULL
  AND committer_date > author_date + INTERVAL '90 days'

Finding description

Commit <sha[:12]> authored <gap_days>d before it was committed — potential rebase injection by <committer_login>

Evidence fields

FieldDescription
shaFull commit SHA
author_dateClaimed timestamp of original authorship
committer_dateActual timestamp when the commit was introduced via rebase
gap_daysComputed difference in days between the two timestamps
message_headlineFirst line of the commit message
before_shaThe SHA that was HEAD before this push (for history comparison)
A large author/committer date gap in a commit that was introduced via a force push is a strong indicator of rebase injection. Use before_sha to reconstruct the pre-push history and diff it against the current tree to identify exactly what the injected commit introduced.Remediation: Restore the branch from before_sha, reapply branch protection to prevent force pushes, and audit the injected commit for malicious content. If the repository is a dependency of other projects, notify downstream consumers immediately and publish a patched release from a known-clean state.

Collecting commit data

Commit-level metadata is not included in GitHub’s public event stream and requires a separate collection step:
github-threat-detector collect --repo owner/repo --commits

null-committer-email

Severity: critical
Required data: Commits (--commits)

What it detects

A commit where the committer email is the literal string 'null' — not an empty string, not a missing value, but the four-character string null. This is a known fingerprint left by ForceMemo, an attacker tooling framework that incorrectly serializes Git commit metadata when constructing crafted commits for injection attacks.

The ForceMemo fingerprint

ForceMemo is a toolset used in targeted supply chain attacks to automate the construction and injection of backdated commits. A bug in its commit serialization layer causes it to write the string null as the committer email when the committer identity is not explicitly configured — rather than using the author’s email or raising an error. This fingerprint is stable across known ForceMemo versions and is not produced by any legitimate Git client or CI system. A single occurrence of committer_email = 'null' in a repository’s commit history is sufficient to indicate that the commit was produced by attacker tooling, regardless of what the commit itself contains.

How detection works

The analyzer queries the push_commits table for an exact string match on the committer email field.
SELECT sha, repo_name, author_login, committer_login,
       committer_email, committer_date, message_headline, before_sha
FROM push_commits
WHERE committer_email = 'null'

Finding description

Commit <sha[:12]> has committer email set to literal 'null' — known attacker tooling fingerprint

Evidence fields

FieldDescription
shaFull commit SHA
committer_emailThe literal string 'null'
committer_dateTimestamp when the commit was introduced
message_headlineFirst line of the commit message
before_shaThe SHA that was HEAD before this push
There is no legitimate reason for a committer email to be the string 'null'. Any finding from this rule should be treated as a confirmed attacker tooling artifact.Immediately:
  1. Identify all commits in history with this fingerprint using git log --format="%H %ae %ce" | grep " null$".
  2. Diff each such commit against its parent to determine what was injected.
  3. Restore the repository from a pre-injection state using the before_sha evidence field.
  4. Report the incident to GitHub Security via their coordinated disclosure program.

Collecting commit data

Both commit tampering rules require commit metadata collection:
github-threat-detector collect --repo owner/repo --commits
Run both rules together by analyzing after collection:
github-threat-detector analyze --repo owner/repo

Build docs developers (and LLMs) love