Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,37 @@ permissions:
contents: read

jobs:
investigator:
name: windows investigator build and saved-case tests
runs-on: windows-latest
timeout-minutes: 20
steps:
- name: checkout
uses: actions/checkout@v4
- name: Rust toolchain
shell: pwsh
run: rustup toolchain install 1.93.0 --profile minimal --component clippy,rustfmt
- name: Rust checks
shell: pwsh
run: |
cargo +1.93.0 fmt --manifest-path investigate/Cargo.toml --check
if ($LASTEXITCODE) { exit $LASTEXITCODE }
cargo +1.93.0 clippy --locked --manifest-path investigate/Cargo.toml --all-targets -- -D warnings
if ($LASTEXITCODE) { exit $LASTEXITCODE }
cargo +1.93.0 test --locked --manifest-path investigate/Cargo.toml
if ($LASTEXITCODE) { exit $LASTEXITCODE }
cargo +1.93.0 build --locked --manifest-path investigate/Cargo.toml
if ($LASTEXITCODE) { exit $LASTEXITCODE }
.\investigate\target\debug\opsforge-investigate.exe --help
if ($LASTEXITCODE) { exit $LASTEXITCODE }
- name: private-directory helper parser
shell: powershell
run: |
$tokens = $null
$parseErrors = $null
[void][System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path investigate/src/private-directory.ps1), [ref]$tokens, [ref]$parseErrors)
if ($parseErrors.Count) { throw ($parseErrors | Out-String) }

powershell:
name: powershell validation
runs-on: windows-latest
Expand Down
5 changes: 3 additions & 2 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

opsforge combines a Rust investigator with native Bash and PowerShell checks.
Scripts degrade clearly when optional commands are missing. The existing
investigator is Linux x86_64; Windows investigator support is planned and must
not be inferred from Windows script CI results.
collector is Linux x86_64. Windows saved-case commands are implemented, with
native CI validation pending. Windows collection remains planned and must not
be inferred from Windows script CI results.

The [approved roadmap](investigator-roadmap.md) targets x64 Windows 10 22H2,
Windows 11, and Windows Server 2022/2025 alongside the Linux validation matrix.
Expand Down
17 changes: 16 additions & 1 deletion docs/investigator-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This file records implementation work, not a support claim.
| Slice | Implementation | Validation |
|---|---|---|
| Policy and architecture alignment | documentation updated | diff reviewed |
| Portable case/runtime foundation | pending | pending |
| Portable case/runtime foundation | native directory permissions, portable artifact paths, Windows job containment and Linux collection separation implemented | Linux regressions and Windows cross-compilation passed; native Windows CI pending |
| Saved-case verification and rebuilding | Linux CLI and review TUI implemented | eleven saved-case tests, three UI tests, PTY verify/bundle/linked workflows and all nine browser pages in both modes passed; cross-platform gates pending |
| Windows collection and check parity | pending | pending |
| Disk acquisition and recovery | pending | pending |
Expand Down Expand Up @@ -71,6 +71,21 @@ Isolate native discovery, elevation, private directories, and child cancellation
from shared parsers/reporting. Windows requires private ACLs and owned child-tree
cleanup; saved-case commands never enter collection or request elevation.

The Windows binary currently exposes saved-case commands only. Linux collection,
embedded Bash checks and their integration fixtures remain Linux-only; this is
not Windows collection parity. New Linux acquisitions record format version,
platform and architecture; old cases remain readable without these fields.

Windows rebuilding uses the installed Windows PowerShell 5.1 to create a private
directory with a protected current-user ACL before writing evidence. It checks
that the filesystem retained that ACL and refuses reparse-point ancestors.
Files are streamed into new destinations so source ACLs are not copied. The
`process-wrap` backend assigns child processes to a job before they run; normal
completion, cancellation and guard cleanup retain ownership of descendants.
Forced termination of the investigator is not a validated cleanup guarantee.
Cases and output parents must remain stable throughout review. Cross-volume
linked output and Windows device/ambiguous artifact names are rejected.

Windows must cover browser profiles (Chromium/Edge/Firefox), existing application
and transfer formats, EVTX and structured Event Logs, PowerShell activity,
TCP/UDP owners, software inventory, retained DNS/VPN/proxy/firewall records,
Expand Down
190 changes: 188 additions & 2 deletions investigate/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions investigate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ clap = { version = "4", features = ["derive"] }
crossterm = "0.29"
jiff = "0.2"
ratatui = "0.30"
rusqlite = { version = "0.37", features = ["bundled", "backup"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sha2 = "0.10"
signal-hook = "0.3.18"
walkdir = "2"

[target.'cfg(unix)'.dependencies]
rusqlite = { version = "0.37", features = ["bundled", "backup"] }
signal-hook = "0.3.18"

[target.'cfg(windows)'.dependencies]
ctrlc = "3.5"
process-wrap = { version = "10.0.1", default-features = false, features = ["std", "job-object"] }

[lints.rust]
unsafe_code = "forbid"

Expand Down
Loading
Loading