CLI: include commit hash in --version output#35713
CLI: include commit hash in --version output#35713echoVic wants to merge 3 commits intoopenclaw:mainfrom
Conversation
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 DoS via blocking read of attacker-controlled .git/HEAD or ref file (FIFO/device)
Description
In an untrusted repository/worktree, an attacker can create
Vulnerable code: const safeReadFilePrefix = (filePath: string, limit = 256) => {
const fd = fs.openSync(filePath, "r");
try {
const buf = Buffer.alloc(limit);
const bytesRead = fs.readSync(fd, buf, 0, limit, 0);
return buf.subarray(0, bytesRead).toString("utf-8");
} finally {
fs.closeSync(fd);
}
};And it is invoked on paths derived from the working directory:
The surrounding RecommendationReject non-regular files (and optionally symlinks) before opening, and/or open in non-blocking mode. Option A: lstat and only allow regular files (and disallow symlinks): const safeReadFilePrefix = (filePath: string, limit = 256) => {
const st = fs.lstatSync(filePath);
// Avoid symlinks, FIFOs, devices, sockets, etc.
if (!st.isFile() || st.isSymbolicLink()) {
throw new Error(`Refusing to read non-regular file: ${filePath}`);
}
const fd = fs.openSync(filePath, fs.constants.O_RDONLY);
try {
const buf = Buffer.alloc(limit);
const bytesRead = fs.readSync(fd, buf, 0, limit, 0);
return buf.subarray(0, bytesRead).toString("utf-8");
} finally {
fs.closeSync(fd);
}
};Option B: non-blocking open (still consider lstat as defense-in-depth): const fd = fs.openSync(filePath, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);Handle Also consider using async I/O to avoid blocking the event loop if commit resolution occurs on latency-sensitive paths. Analyzed PR: #35713 at commit Last updated on: 2026-03-06T03:39:55Z |
Greptile SummaryThis PR appends the short commit SHA to the Inconsistent fallback format — The ternary at line 114 produces Missing test coverage — Only the happy path (with commit hash) is tested. A second test case with Confidence Score: 3/5
|
src/cli/program/help.ts
Outdated
| ) { | ||
| console.log(ctx.programVersion); | ||
| const commit = resolveCommitHash(); | ||
| console.log(commit ? `OpenClaw ${ctx.programVersion} (${commit})` : ctx.programVersion); |
There was a problem hiding this comment.
Inconsistent output format in fallback case
When resolveCommitHash() returns a falsy value the output falls back to the bare ctx.programVersion string (e.g. 9.9.9-test), without the OpenClaw prefix. But when a commit hash is available the output is OpenClaw 9.9.9-test (abc1234) — a completely different shape.
This means the --version output format is environment-dependent in a way that breaks the stated goal of keeping existing behaviour for environments without commit metadata. In those environments users will continue to see only the raw version number, while everyone else sees the branded, parenthesised form. The OpenClaw label (and any tooling that parses the new output) should appear consistently regardless of whether a commit hash exists.
The fallback should keep the OpenClaw prefix:
| console.log(commit ? `OpenClaw ${ctx.programVersion} (${commit})` : ctx.programVersion); | |
| console.log(commit ? `OpenClaw ${ctx.programVersion} (${commit})` : `OpenClaw ${ctx.programVersion}`); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/program/help.ts
Line: 114
Comment:
**Inconsistent output format in fallback case**
When `resolveCommitHash()` returns a falsy value the output falls back to the bare `ctx.programVersion` string (e.g. `9.9.9-test`), without the `OpenClaw` prefix. But when a commit hash *is* available the output is `OpenClaw 9.9.9-test (abc1234)` — a completely different shape.
This means the `--version` output format is environment-dependent in a way that breaks the stated goal of keeping existing behaviour for environments without commit metadata. In those environments users will continue to see only the raw version number, while everyone else sees the branded, parenthesised form. The `OpenClaw` label (and any tooling that parses the new output) should appear consistently regardless of whether a commit hash exists.
The fallback should keep the `OpenClaw` prefix:
```suggestion
console.log(commit ? `OpenClaw ${ctx.programVersion} (${commit})` : `OpenClaw ${ctx.programVersion}`);
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c80fa3efe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/cli/program/help.ts
Outdated
| ) { | ||
| console.log(ctx.programVersion); | ||
| const commit = resolveCommitHash(); | ||
| console.log(commit ? `OpenClaw ${ctx.programVersion} (${commit})` : ctx.programVersion); |
There was a problem hiding this comment.
Keep --version output machine-readable semver
Changing the top-level version output to OpenClaw <version> (<sha>) breaks existing installer and verification flows that compare openclaw --version directly against an npm semver string; for example scripts/docker/install-sh-common/cli-verify.sh:30-37 and scripts/docker/install-sh-e2e/run.sh:71-77 both do exact string equality with npm view ... version. In any environment where resolveCommitHash() returns a value (git checkout or npm package with gitHead), these checks will now fail even when the correct version is installed.
Useful? React with 👍 / 👎.
|
Thanks! I’ll follow up in #34972 to keep the discussion consolidated — agree the Codex comments there are pointing at the right shape. I’ll align this PR accordingly (and add the missing fallback test + harden commit formatting per the review notes). |
|
Pushed an update to address the review notes:
Latest commit: b91602c. |
|
@echoVic or did I miss something? #35713 (comment) |
|
Following up here. The review points about keeping the fallback output shape consistent, adding the no-commit test, and hardening commit-hash resolution were folded into this PR in the later update I pushed. If there are still two concrete snippets from the linked discussion that you want adjusted further, point me at the exact lines and I will patch them on this branch instead of splitting anything out. |
|
Follow-up pushed on this branch. This folds in the two installer/verifier call sites called out in the review so they stay semver-compatible with Updated:
Both now normalize the CLI Local verification:
|
|
🚢 |
Summary
-v/--versionoutput when availableCloses #34972