In 2023, a serious vulnerability was discovered in the popular npm package blamer. Identified as CVE-2023-26143, this flaw allows attackers to inject arbitrary arguments into git commands executed through the blamer library. Specifically, any application using blamer versions before 1..4 and relying on the blameByFile() API is at risk.

In this article, I will break down what went wrong, how this vulnerability can be exploited, share example attack code, and offer advice for remediation. This deep dive uses simple language to ensure clear understanding, even if you’re new to security topics.

What is Blamer?

blamer is a Node.js library that retrieves blame information from a source code repository using the git blame command. Many tools and web services use blamer to display who last modified each line of code.

Example code (safe usage expected)

const blamer = require('blamer');
blamer.blameByFile('app.js', function(err, result) {
    if (err) return console.error(err);
    console.log(result);
});

What Went Wrong?

The core issue lies in how blamer passes the filename provided by the user directly to the git command without validation or sanitation. Even worse, it *does not* use the recommended -- POSIX separator to mark the end of command-line options.

This means that if a user supplies a filename like --help, it would be passed as an option to git rather than as a file, potentially altering the command’s intended function. An attacker could supply crafted arguments that the system runs with full privileges of the process owner.

Here is a hypothetical snippet from blamer (simplified for illustration)

// UNSAFE: simplified vulnerable call
const { exec } = require('child_process');
function blameByFile(filename, callback) {
    exec(git blame ${filename}, (err, stdout, stderr) => {
        callback(err, stdout);
    });
}

Step 2: Malicious Input

Suppose an attacker provides input via a web API that calls blameByFile('--help'). Instead of showing blame info for a file called --help, it executes:

git blame --help

Which just displays the git help message. This is relatively harmless but demonstrates the point.

Taking it further: Arbitrary Argument Injection

Supplying arguments like -C ../../ or using other git flags, the attacker can make the system behave in unexpected ways or leak internal information.

Suppose an attacker supplies

";cat /etc/passwd #"

Due to shell expansion and not escaping inputs, this could execute cat /etc/passwd on the server, dumping sensitive data if the tool is not careful with sanitation.

While blamer itself uses only filename in a quoted string, due to lack of validation, an attacker could provide weird paths or filenames that resemble options, breaks, or shell tricks.

Proof of Concept (PoC)

Here’s a proof-of-concept exploit in Node.js, for testing against a vulnerable local blamer install:

const blamer = require('blamer');

// Malicious filename injects a git flag
let maliciousFilename = '--output=/tmp/hacked';

// Or, if used in shell literals, a shell injection attempt
let dangerousFilename = 'my_file.txt"; touch /tmp/evil #';

blamer.blameByFile(maliciousFilename, (err, result) => {
    if (err) console.error('Exploit attempt failed:', err);
    else console.log('Exploit attempt result:', result);
});

Warning: Do not attempt this against machines without explicit permission.

Real-World Attack Scenarios

- Automated Code Review: A web app that runs blamer.blameByFile() on user-submitted filenames is vulnerable to attackers injecting arguments or shell commands.
- CI/CD Integrations: Build servers or pipelines using blamer may leak secrets or files if an attacker controls input filenames.

Upgrade: Immediately update to blamer version 1..4 or higher.

- Input Validation: Never trust user input. Sanitize and validate any file paths before passing them to child processes.
- Use --: Always use the -- flag when building git commands to separate options from filenames:

exec(git blame -- ${safeFilename})

`
- Escape Shell Args: Use spawn and pass arguments as an array, not shell strings.

---

## References

- GitHub Security Advisory (GHSA-jjfp-56qf-wc9p)
- Snyk Advisory - blamer Vulnerability
- NPM blamer package
- Mitre CVE-2023-26143
- Safe Node.js Child Process Usage

---

## Conclusion

CVE-2023-26143 demonstrates how dangerous improper handling of user input and external process arguments can be, even in well-used libraries. Always sanitize inputs and use defense-in-depth strategies like command-line argument separation and privilege reduction.

Stay safe: keep your dependencies up-to-date and your code defensive!

Timeline

Published on: 09/19/2023 05:17:00 UTC
Last modified on: 09/21/2023 19:28:00 UTC