Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
486f5ed
Harden thunderstorm-collector.sh
Neo23x0 Feb 22, 2026
8a17019
Add script collector tests workflow
Neo23x0 Feb 22, 2026
350c9ad
Fix filename encoding in collector
Neo23x0 Feb 22, 2026
2e21a34
Add bash collector test suite (28 tests) and fix max-age CLI override…
Colossus14 Feb 22, 2026
04515a8
Fix bugs across Python, Perl, and PowerShell collectors
Colossus14 Feb 22, 2026
c17f0b2
ci: keep windows stub-server e2e in one step
Neo23x0 Feb 22, 2026
5eed035
Refactor code structure for improved readability and maintainability
Neo23x0 Feb 22, 2026
e753fe2
Update README tested environments with file submission counts
Colossus14 Feb 23, 2026
a826873
Add filesystem exclusions, filter tests, and collection init/end markers
Colossus14 Feb 24, 2026
59e8d7b
Add -AllExtensions switch to PowerShell collectors
Colossus14 Feb 24, 2026
b93f0ae
Add cloud storage and network/special mount exclusions
Colossus14 Feb 24, 2026
b521ba9
Merge pull request #16 from Colossus14/script-robustness
Neo23x0 Feb 24, 2026
dae9ebe
Remove tmpfs and overlay from special FS exclusion list
Colossus14 Feb 24, 2026
c5430ad
Merge pull request #17 from Colossus14/script-robustness
Neo23x0 Feb 24, 2026
09e3d4d
Fix scan_id extraction in Bash/Ash collectors
Colossus14 Feb 24, 2026
bfb5b38
fix(ps): use ActiveExtensions to avoid PS 2.0 ValidateNotNullOrEmpty …
Colossus14 Feb 24, 2026
5ff8cd4
Merge pull request #18 from Colossus14/script-robustness
Neo23x0 Feb 24, 2026
3e02f38
fix(batch): add junction/symlink loop protection for Windows 7
Colossus14 Feb 24, 2026
34012ef
redesign(batch): two-phase architecture with FORFILES
Colossus14 Feb 24, 2026
b54ea62
Harmonize CLI flags across all collectors
Colossus14 Feb 25, 2026
b319660
Add cross-platform test matrix and harmonized CLI flags to README
Colossus14 Feb 25, 2026
e902824
Add Raspberry Pi 5 (aarch64/Debian 13) to test matrix — 47/47 pass
Colossus14 Feb 25, 2026
fd015c9
Merge pull request #20 from Colossus14/script-robustness
Neo23x0 Feb 25, 2026
fdda057
fix: address issues found during cross-model code review
Feb 28, 2026
01c20ec
Merge pull request #22 from Colossus14/code-review-fixes
Neo23x0 Mar 5, 2026
8354aa4
fix: complete collector script improvements
Mar 11, 2026
b522cef
Merge pull request #26 from Colossus14/script-robustness-squashed
Neo23x0 Mar 11, 2026
173e444
Merge master into script-robustness
Mar 11, 2026
4f9aa52
Merge pull request #27 from Colossus14/script-robustness
Neo23x0 Mar 11, 2026
71acacf
fix(ci): remove perl option terminator in e2e workflow
Neo23x0 Mar 11, 2026
4ca598e
chore: remove review artifacts and build outputs
Mar 11, 2026
2b9036e
fix(batch): remove PowerShell dependency and collection markers
Mar 11, 2026
054acb2
Merge pull request #30 from Colossus14/batch-simplify
Neo23x0 Mar 11, 2026
2722456
Merge pull request #29 from Colossus14/cleanup
Neo23x0 Mar 11, 2026
e060709
Fix FORFILES /D filter semantics (inverted)
Mar 12, 2026
bab9245
Merge pull request #32 from Colossus14/fix-forfiles-script-robustness
Neo23x0 Mar 12, 2026
16ec4af
fix(batch): apply MAX_AGE per-file and align docs
Neo23x0 Mar 12, 2026
0e8f118
chore: remove Go integration test from script-robustness
Colossus14 Mar 12, 2026
973648b
Merge pull request #34 from Colossus14/remove-go-test-file
Neo23x0 Mar 12, 2026
e783f2e
fix(collectors): make markers optional in ps2 and align multipart fil…
Neo23x0 Mar 12, 2026
657e772
fix(collectors): tolerate optional marker endpoint and harden tests
Neo23x0 Mar 12, 2026
70d411f
fix(python): treat HTTP 501 marker endpoint as optional
Neo23x0 Mar 12, 2026
ea374db
fix: align collector upload and async behavior
Neo23x0 Mar 13, 2026
8059cd3
fix: use filename metadata field for uploads
Neo23x0 Mar 13, 2026
bf82905
docs: align review notes with API contract
Neo23x0 Mar 13, 2026
61a366d
chore: remove generated review note
Neo23x0 Mar 13, 2026
de12bb7
fix(ps2): repair Get-JsonValue \f Replace type mismatch; fix test har…
Mar 13, 2026
da330a0
Merge pull request #35 from Colossus14/e2e-fixes
Neo23x0 Mar 14, 2026
4aa1c94
fix: remove hostname/filename form fields, send full path in Content-…
Colossus14 Mar 14, 2026
280bd6f
Add comprehensive E2E detection tests for all collectors
Colossus14 Mar 14, 2026
3fa0308
Add negative tests: directory scope, age filter, extension filter, su…
Colossus14 Mar 14, 2026
a2262d9
Add edge case & robustness tests: empty files, unicode, symlinks, spe…
Colossus14 Mar 14, 2026
ccbe326
Add server failure & retry tests, fix log scoping
Colossus14 Mar 14, 2026
8c6cccd
Fix PS2 symlink following (security) + fix retry test timing
Colossus14 Mar 14, 2026
2f98c42
Merge pull request #36 from Colossus14/script-robustness
Neo23x0 Mar 14, 2026
1825456
fix: retry test timing + add operational feature tests
Colossus14 Mar 15, 2026
f1a0731
fix: Perl collector now supports multiple --dir arguments
Colossus14 Mar 15, 2026
5c42d7d
fix: HTTP/1.0 for nc uploads, LC_ALL=C for binary grep, clearer BusyB…
Mar 17, 2026
07cd214
Merge pull request #37 from Colossus14/script-robustness
Neo23x0 Mar 17, 2026
fa9f068
fix: TOCTOU race in mktemp_portable fallback
Mar 17, 2026
fb2e454
Merge pull request #38 from Colossus14/script-robustness
Neo23x0 Mar 17, 2026
c0358f4
fix(py): sanitize backslash/NUL in filenames, guard conn.close, clamp…
Mar 17, 2026
e3bbccf
Merge pull request #39 from Colossus14/script-robustness
Neo23x0 Mar 17, 2026
c33fbfb
fix(pl): decode octal escapes in /proc/mounts, fix Encode compat for …
Mar 18, 2026
f511d3f
Merge pull request #40 from Colossus14/script-robustness
Neo23x0 Mar 18, 2026
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
253 changes: 253 additions & 0 deletions .github/workflows/script-collectors-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
name: Script Collectors E2E

on:
push:
paths:
- "scripts/**"
- ".github/workflows/script-collectors-e2e.yml"
pull_request:
paths:
- "scripts/**"
- ".github/workflows/script-collectors-e2e.yml"
workflow_dispatch:

jobs:
linux-collectors:
name: Linux scripts (bash/python/perl)
runs-on: ubuntu-latest
env:
SAMPLE_URL: https://github.com/TwoSevenOneT/EDR-Freeze/releases/download/v1.0-fbd43cf/EDRFreeze-msvc.exe
STUB_PORT: "18080"
steps:
- uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Install Perl dependency
run: sudo apt-get update && sudo apt-get install -y libwww-perl

- name: Checkout thunderstorm-stub-server
uses: actions/checkout@v4
with:
repository: Nextron-Labs/thunderstorm-stub-server
path: thunderstorm-stub-server

- name: Build thunderstorm-stub-server
working-directory: thunderstorm-stub-server
run: go build -o "$RUNNER_TEMP/thunderstorm-stub-server" .

- name: Prepare test sample
run: |
set -euo pipefail
SAMPLE_DIR="$RUNNER_TEMP/script-collector-e2e-sample"
mkdir -p "$SAMPLE_DIR"
curl -L --fail "$SAMPLE_URL" -o "$SAMPLE_DIR/EDRFreeze-msvc.exe"
EXPECTED_SHA256="$(sha256sum "$SAMPLE_DIR/EDRFreeze-msvc.exe" | awk '{print $1}')"
echo "SAMPLE_DIR=$SAMPLE_DIR" >> "$GITHUB_ENV"
echo "EXPECTED_SHA256=$EXPECTED_SHA256" >> "$GITHUB_ENV"

- name: Start thunderstorm-stub-server
run: |
set -euo pipefail
UPLOADS_DIR="$RUNNER_TEMP/stub-uploads"
LOG_FILE="$RUNNER_TEMP/stub-audit.jsonl"
STUB_LOG="$RUNNER_TEMP/stub-server.log"
mkdir -p "$UPLOADS_DIR"
"$RUNNER_TEMP/thunderstorm-stub-server" \
--port "$STUB_PORT" \
--uploads-dir "$UPLOADS_DIR" \
--log-file "$LOG_FILE" \
>"$STUB_LOG" 2>&1 &
echo $! > "$RUNNER_TEMP/stub-server.pid"
echo "UPLOADS_DIR=$UPLOADS_DIR" >> "$GITHUB_ENV"
echo "STUB_LOG=$STUB_LOG" >> "$GITHUB_ENV"
for i in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:$STUB_PORT/api/status" >/dev/null; then
exit 0
fi
sleep 1
done
echo "Stub server did not become ready in time" >&2
exit 1

- name: Run bash collector
run: |
bash ./scripts/thunderstorm-collector.sh \
--server 127.0.0.1 \
--port "$STUB_PORT" \
--dir "$SAMPLE_DIR" \
--source linux-sh-e2e \
--max-age 30 \
--max-size-kb 50000 \
--sync

- name: Run Python collector
run: |
python3 ./scripts/thunderstorm-collector.py \
-s 127.0.0.1 \
-p "$STUB_PORT" \
-d "$SAMPLE_DIR" \
-S linux-py-e2e

- name: Run Perl collector
run: |
perl ./scripts/thunderstorm-collector.pl \
--dir "$SAMPLE_DIR" \
--server 127.0.0.1 \
--port "$STUB_PORT" \
--source linux-pl-e2e

- name: Verify uploaded file integrity
run: |
python3 ./scripts/tests/verify_uploads.py \
--uploads-dir "$UPLOADS_DIR" \
--expected-sha256 "$EXPECTED_SHA256" \
--min-count 3 \
--timeout-seconds 120

- name: Stop thunderstorm-stub-server
if: always()
run: |
if [ -f "$RUNNER_TEMP/stub-server.pid" ]; then
kill "$(cat "$RUNNER_TEMP/stub-server.pid")" || true
fi

- name: Print stub server log
if: always()
run: |
if [ -n "${STUB_LOG:-}" ] && [ -f "$STUB_LOG" ]; then
echo "==== thunderstorm-stub-server log ===="
cat "$STUB_LOG"
fi

windows-collectors:
name: Windows scripts (PowerShell/Batch)
runs-on: windows-latest
env:
SAMPLE_URL: https://github.com/TwoSevenOneT/EDR-Freeze/releases/download/v1.0-fbd43cf/EDRFreeze-msvc.exe
STUB_PORT: "18080"
steps:
- uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Checkout thunderstorm-stub-server
uses: actions/checkout@v4
with:
repository: Nextron-Labs/thunderstorm-stub-server
path: thunderstorm-stub-server

- name: Build thunderstorm-stub-server
shell: pwsh
working-directory: thunderstorm-stub-server
run: go build -o "$env:RUNNER_TEMP\thunderstorm-stub-server.exe" .

- name: Prepare test sample and directories
shell: pwsh
run: |
$sampleDir = "C:\ts-e2e-sample"
$uploadsDir = "C:\ts-e2e-uploads"
New-Item -ItemType Directory -Path $sampleDir -Force | Out-Null
New-Item -ItemType Directory -Path $uploadsDir -Force | Out-Null
$samplePath = Join-Path $sampleDir "EDRFreeze-msvc.exe"
Invoke-WebRequest -Uri $env:SAMPLE_URL -OutFile $samplePath
$hash = (Get-FileHash -Path $samplePath -Algorithm SHA256).Hash.ToLower()
"SAMPLE_DIR=$sampleDir" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
"UPLOADS_DIR=$uploadsDir" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
"EXPECTED_SHA256=$hash" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8

- name: Run Windows collectors against thunderstorm-stub-server
shell: pwsh
run: |
$stdoutLogFile = Join-Path $env:RUNNER_TEMP "stub-server.stdout.log"
$stderrLogFile = Join-Path $env:RUNNER_TEMP "stub-server.stderr.log"
$auditFile = Join-Path $env:RUNNER_TEMP "stub-audit.jsonl"
$proc = $null
try {
$proc = Start-Process `
-FilePath "$env:RUNNER_TEMP\thunderstorm-stub-server.exe" `
-ArgumentList @("--port", $env:STUB_PORT, "--uploads-dir", $env:UPLOADS_DIR, "--log-file", $auditFile) `
-RedirectStandardOutput $stdoutLogFile `
-RedirectStandardError $stderrLogFile `
-PassThru

$ready = $false
for ($i = 0; $i -lt 60; $i++) {
try {
Invoke-RestMethod -Uri "http://127.0.0.1:$($env:STUB_PORT)/api/status" | Out-Null
$ready = $true
break
} catch {
Start-Sleep -Seconds 1
}
}
if (-not $ready) {
throw "Stub server did not become ready in time"
}

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\thunderstorm-collector.ps1 `
-ThunderstormServer 127.0.0.1 `
-ThunderstormPort $env:STUB_PORT `
-Folder $env:SAMPLE_DIR `
-Source windows-ps-e2e `
-MaxAge 30 `
-MaxSize 100
if ($LASTEXITCODE -ne 0) {
throw "PowerShell collector failed with exit code $LASTEXITCODE"
}

$env:THUNDERSTORM_SERVER = "127.0.0.1"
$env:THUNDERSTORM_PORT = $env:STUB_PORT
$env:URL_SCHEME = "http"
$env:COLLECT_DIRS = $env:SAMPLE_DIR
$env:RELEVANT_EXTENSIONS = ".exe"
$env:COLLECT_MAX_SIZE = "50000000"
$env:MAX_AGE = "30"
$env:SOURCE = "windows-bat-e2e"
$env:DEBUG = "1"
cmd /c scripts\thunderstorm-collector.bat
if ($LASTEXITCODE -ne 0) {
throw "Batch collector failed with exit code $LASTEXITCODE"
}

python .\scripts\tests\verify_uploads.py `
--uploads-dir "$env:UPLOADS_DIR" `
--expected-sha256 "$env:EXPECTED_SHA256" `
--min-count 2 `
--timeout-seconds 180
if ($LASTEXITCODE -ne 0) {
throw "Upload verification failed with exit code $LASTEXITCODE"
}
} finally {
if ($proc) {
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
}
if (Test-Path $stdoutLogFile) {
Write-Host "==== thunderstorm-stub-server stdout ===="
Get-Content -Path $stdoutLogFile
}
if (Test-Path $stderrLogFile) {
Write-Host "==== thunderstorm-stub-server stderr ===="
Get-Content -Path $stderrLogFile
}
if (Test-Path $auditFile) {
Write-Host "==== thunderstorm-stub-server audit jsonl ===="
Get-Content -Path $auditFile
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ curl.exe
settings.json
*.log
go/dist/
__pycache__/
Loading
Loading