Skip to content

Release v0.0.52 - #297

Merged
queil merged 3 commits into
mainfrom
release-v0.0.52
Sep 24, 2026
Merged

queil merged 3 commits into
mainfrom
release-v0.0.52

Conversation

@queil

@queil queil commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@strix-security

strix-security Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Strix Security Review

Warning

This pull request has 7 commits after the last Strix review (743da29). Strix has not reviewed these changes.
Automatic review on push is off for this repository. To review the latest changes, tag @strix-security in a comment, or turn on re-review on push.

1 open security finding on this PR:

Review summary

Reviewed all 27 changed files in PR #297 (release v0.0.52), inlined into the manifest. The change set primarily adds REPL/UX features (kill-ring, #history, quiet command-failure status), the $$<<< splice heredoc, the line reifier, the exec process-replacement reifier, Path.home/XDG helpers, a newTempDir cleanup warning, a top-level if/else parse fix, an az -o table separator skip, and CI/release-smoke hardening. One issue was identified and filed: the new exec reifier bypasses the plan runtime guard on POSIX, allowing an indirectly-invoked cmd | exec inside a plan dry-run block to execute (and replace the process) instead of being refused. The remaining changes are documentation, tests, typography, and checker warnings with no confirmed security impact.

Fixed the findings? re-run the review, or tag @strix-security in a PR comment to run a fresh review.

Updated for 743da29.


Reviewed by Strix
Re-run review · Configure security review settings

@queil
queil force-pushed the release-v0.0.52 branch 2 times, most recently from 3c23e72 to d14c5ad Compare September 24, 2026 14:03

@strix-security strix-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strix flagged a new security finding below. See the pinned summary comment for the full PR status.

Comment thread src/Weir/Proc.fs
Comment on lines +311 to +312
let exec (s: Spec) : unit =
// the same boundary spawn enforces [D:spawn-nul-funnel]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 exec reifier bypasses the plan runtime guard on POSIX, executing a command inside a dry-run plan

Severity: LOW

The new cmd | exec process-replacement reifier (Proc.exec) reproduces the NUL-byte refusal boundary of Proc.spawn but omits the runtime plan guard. On POSIX it calls execvp directly without checking Session.planGuardActive(), so an indirect command inside a plan block (a helper function that itself invokes exec) runs and replaces the process instead of being refused.

Suggested change
let exec (s: Spec) : unit =
// the same boundary spawn enforces [D:spawn-nul-funnel]
let exec (s: Spec) : unit =
// runtime plan refusal [D:plan-proc-runtime-guard]: process replacement
// must obey the same boundary spawn enforces — POSIX execvp does not
// funnel through spawn, so the guard is applied here directly.
if Session.planGuardActive () then
failwith
$"'{s.Prog}' runs a command, and 'proc' is refused inside 'plan' — a spawned binary reads and writes opaquely, so its effects cannot be captured; plan covers weir-native mutation only (File/Dir/Http)"
// the same boundary spawn enforces [D:spawn-nul-funnel]
Prompt to fix with AI
This is a security vulnerability found during a code review.

Vulnerability: `exec` reifier bypasses the `plan` runtime guard on POSIX, executing a command inside a dry-run plan
Severity: LOW

The new `cmd | exec` process-replacement reifier (`Proc.exec`) reproduces the NUL-byte refusal boundary of `Proc.spawn` but omits the runtime `plan` guard. On POSIX it calls `execvp` directly without checking `Session.planGuardActive()`, so an *indirect* command inside a `plan` block (a helper function that itself invokes `exec`) runs and replaces the process instead of being refused.

Location: src/Weir/Proc.fs:311-312
Context: Add plan-guard refusal at the top of exec
```
// Before:
let exec (s: Spec) : unit =
    // the same boundary spawn enforces [D:spawn-nul-funnel]
// After:
let exec (s: Spec) : unit =
    // runtime plan refusal [D:plan-proc-runtime-guard]: process replacement
    // must obey the same boundary spawn enforces — POSIX execvp does not
    // funnel through spawn, so the guard is applied here directly.
    if Session.planGuardActive () then
        failwith
            $"'{s.Prog}' runs a command, and 'proc' is refused inside 'plan' — a spawned binary reads and writes opaquely, so its effects cannot be captured; plan covers weir-native mutation only (File/Dir/Http)"
    // the same boundary spawn enforces [D:spawn-nul-funnel]
```

How to fix:
Add the same runtime plan refusal that `Proc.spawn` performs at the entry of `Proc.exec`, before argv/env processing and before the platform split. Applying the check unconditionally in `exec` keeps POSIX behavior consistent — the Windows branch is already guarded because it funnels through `spawn` — and closes the gap where a helper reference defeats the syntactic `firstPlanRefusal`. Reuse the same located message that `spawn` raises, naming the offending program.

Please fix this vulnerability. If you propose a fix, make it concise and minimal.

React 👍 / 👎 to tune Strix for this repo. A repo collaborator (or the PR author) can resolve this thread to dismiss the finding.

@queil
queil force-pushed the release-v0.0.52 branch 2 times, most recently from b63174e to 145fede Compare September 24, 2026 17:25
@queil
queil changed the base branch from main to release-v0.0.51 September 24, 2026 17:32
@queil
queil force-pushed the release-v0.0.52 branch 2 times, most recently from 7237dbc to 29f6dca Compare September 24, 2026 19:01
@queil
queil changed the base branch from release-v0.0.51 to main September 24, 2026 19:09
@queil
queil merged commit a568166 into main Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant