fix(daemon): accept localized schtasks running states#41034
fix(daemon): accept localized schtasks running states#41034Narcooo wants to merge 4 commits intoopenclaw:mainfrom
Conversation
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Locale-dependent Scheduled Task status misclassified as STOPPED, causing unsafe process termination during restart health checks
DescriptionThe Windows scheduled-task runtime derivation now defaults to
Vulnerable logic: if (!isRunningTaskStatus(parsed.status)) {
return { status: "stopped" };
}Data-flow / impact chain:
RecommendationTreat unrecognized localized Suggested change (safer default): const normalizedResult = normalizeTaskResultCode(parsed.lastRunResult);
if (normalizedResult && RUNNING_RESULT_CODES.has(normalizedResult)) {
return { status: "running" };
}
// If the status is not confidently recognized, don't assume stopped.
if (!isRunningTaskStatus(parsed.status)) {
return {
status: "unknown",
detail: "Unrecognized Scheduled Task status string; locale-dependent and no numeric Last Run Result available.",
};
}
// Status looks like running; only treat as stopped if we have a non-running numeric result.
if (normalizedResult) {
return {
status: "stopped",
detail: `Task Last Run Result=${parsed.lastRunResult}; treating as not running.`,
};
}
return { status: "running" };Additionally:
Analyzed PR: #41034 at commit Last updated on: 2026-03-09T13:33:32Z |
Greptile SummaryThis PR fixes Key changes:
Issues found:
Confidence Score: 3/5
|
| function isRunningTaskStatus(value?: string): boolean { | ||
| const normalized = normalizeTaskStatus(value); | ||
| return normalized === "running" || normalized.startsWith("wird ausgef"); | ||
| } |
There was a problem hiding this comment.
Non-German localized running states fall back to stopped
isRunningTaskStatus only recognises English ("running") and German ("wird ausgef…"). Any other locale's running status text — e.g. French "En cours d'exécution", Spanish "En ejecución", Japanese "実行中" — that arrives without a lastRunResult of 0x41301 (e.g. very early in startup before the result code is populated) will now reach the !isRunningTaskStatus branch and return { status: "stopped" }.
Before this PR those cases returned { status: "unknown" }, which at least did not lie to the caller. Silently flipping to "stopped" is a regression for those locales.
If the intent is to keep the old "unknown" fall-through for unrecognised running states rather than reporting "stopped", the guard in step 3 should be narrowed so it only fires for statuses that are positively known to be non-running (e.g. "ready", "disabled", etc.), or the function should return "unknown" when a non-empty status is present but unrecognised:
// Possible alternative for unrecognised status text with no result code
if (!isRunningTaskStatus(parsed.status)) {
// A non-empty status we don't recognise could still be a localized
// running state; prefer "unknown" over a false "stopped".
return normalizedResult ? { status: "stopped" } : { status: "unknown" };
}Prompt To Fix With AI
This is a comment left during a code review.
Path: src/daemon/schtasks.ts
Line: 170-173
Comment:
**Non-German localized running states fall back to `stopped`**
`isRunningTaskStatus` only recognises English (`"running"`) and German (`"wird ausgef…"`). Any other locale's running status text — e.g. French `"En cours d'exécution"`, Spanish `"En ejecución"`, Japanese `"実行中"` — that arrives **without** a `lastRunResult` of `0x41301` (e.g. very early in startup before the result code is populated) will now reach the `!isRunningTaskStatus` branch and return `{ status: "stopped" }`.
Before this PR those cases returned `{ status: "unknown" }`, which at least did not lie to the caller. Silently flipping to `"stopped"` is a regression for those locales.
If the intent is to keep the old `"unknown"` fall-through for unrecognised running states rather than reporting `"stopped"`, the guard in step 3 should be narrowed so it only fires for statuses that are positively known to be non-running (e.g. `"ready"`, `"disabled"`, etc.), or the function should return `"unknown"` when a non-empty status is present but unrecognised:
```ts
// Possible alternative for unrecognised status text with no result code
if (!isRunningTaskStatus(parsed.status)) {
// A non-empty status we don't recognise could still be a localized
// running state; prefer "unknown" over a false "stopped".
return normalizedResult ? { status: "stopped" } : { status: "unknown" };
}
```
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: adb53b41e3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!isRunningTaskStatus(parsed.status)) { | ||
| return { status: "stopped" }; |
There was a problem hiding this comment.
Return unknown for unrecognized localized running states
This branch now classifies any non-empty status text that is neither English Running nor German Wird ausgef… as stopped when Last Run Result is missing/non-numeric, which regresses the previous behavior of reporting unknown. On localized Windows hosts where running text differs (for example French) and no parseable result code is present, an actually running task will be reported as stopped, which can trigger incorrect status output and control decisions from deriveScheduledTaskRuntimeStatus.
Useful? React with 👍 / 👎.
Summary
Last Run ResultProblem
openclaw node statusonly recognized the EnglishRunningschtasks state, so localized Windows hosts like GermanWird ausgeführtwere incorrectly reported as stopped.Verification
Fixes #39057