Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
aaf5e74
Redact analyst paths from SARIF reports
seifreed Nov 7, 2026
59cec76
Require the patched MessagePack release
seifreed Nov 7, 2026
d63bec8
Bound structured logging collection traversal
seifreed Nov 7, 2026
494dcc4
Redact secrets in structured log keys and paths
seifreed Nov 7, 2026
53a2493
Instrument analysis and CLI operation outcomes
seifreed Nov 7, 2026
b52de46
Propagate correlation through enhanced CLI analysis
seifreed Nov 7, 2026
284ee64
Honor environment log levels in CLI
seifreed Nov 7, 2026
422e74f
Keep sample payloads out of operational logs
seifreed Nov 7, 2026
330426d
Install release dependencies before contract validation
seifreed Nov 7, 2026
459fc82
Fail CI when stable smoke tests are skipped
seifreed Nov 8, 2026
0538334
Bound the unit test CI job runtime
seifreed Nov 8, 2026
0681f01
Bound fixture workers with process-group deadlines
seifreed Nov 8, 2026
06ce35d
Terminate descendant processes on Windows timeouts
seifreed Nov 8, 2026
33974b6
Install Clang for compiler-generated Linux corpus tests
seifreed Nov 8, 2026
ed0d2eb
Install Unicorn on macOS arm64 for test collection
seifreed Nov 8, 2026
c28eca3
Reject unsupported block-reordering targets
seifreed Nov 9, 2026
69d2e26
Preserve fallthrough chains during block reordering
seifreed Nov 9, 2026
fcc540e
Fuzz block-order layout invariants
seifreed Nov 9, 2026
3015a0d
Record green CI evidence for fcc540e2
seifreed Nov 9, 2026
a111f92
Record Binary Ninja license availability evidence
seifreed Nov 9, 2026
ce0e8e2
Record maintainer approval without implying independence
seifreed Nov 9, 2026
97b0d05
Record independent VM review signoff in release evidence
seifreed Nov 9, 2026
586f1b7
Record green CI for the reviewed release evidence
seifreed Nov 9, 2026
4bd8aa8
Retry verified radare2 downloads on transient Windows errors
seifreed Nov 9, 2026
25bdaa5
Record green CI for the Windows download retry fix
seifreed Nov 9, 2026
6b41fc1
Define public API stability contract and split CLI report tests
seifreed Nov 10, 2026
3948e37
Use angr's Claripy runtime for symbolic states
seifreed Nov 10, 2026
1942151
Run PE preview smoke through available Wine runtime
seifreed Nov 10, 2026
e16d561
Verify API and CLI contract on installed wheels
seifreed Nov 10, 2026
0cdf382
Record bounded independent analysis evidence
seifreed Nov 10, 2026
eb1deab
Block stable-major releases on incomplete 1.0 evidence
seifreed Nov 10, 2026
82ea6ac
Fix symbolic evidence imports and platform mapping
seifreed Nov 10, 2026
ba7f147
Link preview support cells to exact test cases
seifreed Nov 10, 2026
9b3e2d9
Enable preview block reordering for Mach-O x86-64
seifreed Nov 10, 2026
10d8c47
Exercise Mach-O block reordering across multiple inputs
seifreed Nov 10, 2026
691df14
Enable preview block reordering for ELF x86-32
seifreed Nov 10, 2026
cd857e1
Support preview PE x86-64 block reordering
seifreed Nov 10, 2026
77339e5
Correct release contract execution and evidence scope
seifreed Nov 10, 2026
9a68508
Classify ARM32 targets as experimental
seifreed Nov 10, 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
48 changes: 48 additions & 0 deletions .github/scripts/download_verified_artifact.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
param(
[Parameter(Mandatory = $true)]
[uri] $Url,
[Parameter(Mandatory = $true)]
[string] $Output,
[Parameter(Mandatory = $true)]
[ValidatePattern('^[A-Fa-f0-9]{64}$')]
[string] $Sha256
)

$ErrorActionPreference = "Stop"
if ($Url.Scheme -ne "https" -and -not ($Url.Scheme -eq "http" -and $Url.IsLoopback)) {
throw "Artifact URL must use HTTPS."
}

$maximumAttempts = 3
$partialOutput = "$Output.$PID.partial"
$downloaded = $false
for ($attempt = 1; $attempt -le $maximumAttempts; $attempt++) {
try {
Invoke-WebRequest -Uri $Url -OutFile $partialOutput -TimeoutSec 120 | Out-Null
$downloaded = $true
break
}
catch {
Remove-Item -LiteralPath $partialOutput -Force -ErrorAction SilentlyContinue
$statusCode = 0
$response = $_.Exception.Response
if ($null -ne $response -and $null -ne $response.StatusCode) {
$statusCode = [int] $response.StatusCode
}
$transientStatus = $statusCode -eq 0 -or $statusCode -in @(408, 429) -or ($statusCode -ge 500 -and $statusCode -lt 600)
if (-not $transientStatus -or $attempt -eq $maximumAttempts) {
throw
}
Start-Sleep -Seconds $attempt
}
}

if (-not $downloaded) {
throw "Artifact download failed after $maximumAttempts attempts."
}
$actualSha256 = (Get-FileHash -Algorithm SHA256 -Path $partialOutput).Hash.ToLowerInvariant()
if ($actualSha256 -ne $Sha256.ToLowerInvariant()) {
Remove-Item -LiteralPath $partialOutput -Force
throw "Artifact SHA-256 mismatch: expected $Sha256, got $actualSha256"
}
Move-Item -LiteralPath $partialOutput -Destination $Output -Force
15 changes: 8 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v5
Expand Down Expand Up @@ -203,7 +204,9 @@ jobs:
- name: Run product smoke tests
run: |
python -W error -m pytest -v tests/product_smoke \
-m "stable" --no-cov --tb=short
-m "stable" --no-cov --tb=short \
--junitxml="$RUNNER_TEMP/stable-product-smoke.xml"
python scripts/check_critical_skips.py "$RUNNER_TEMP/stable-product-smoke.xml"

cross-platform-tests:
name: Tests (${{ matrix.os }}, Python ${{ matrix.python-version }})
Expand All @@ -230,7 +233,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y \
git build-essential gcc-arm-linux-gnueabihf qemu-user pkg-config wget cmake
git build-essential clang gcc-arm-linux-gnueabihf qemu-user pkg-config wget cmake

- name: Install system dependencies (macOS)
if: runner.os == 'macOS'
Expand All @@ -252,11 +255,7 @@ jobs:
$archive = Join-Path $env:RUNNER_TEMP $archiveName
$url = "https://github.com/radareorg/radare2/releases/download/$version/$archiveName"
$expectedSha256 = "913e7d95e7458226a5e783240877f2c1d405398ab38ba176ce9b12e046e31f34"
Invoke-WebRequest -Uri $url -OutFile $archive
$actualSha256 = (Get-FileHash -Algorithm SHA256 -Path $archive).Hash.ToLowerInvariant()
if ($actualSha256 -ne $expectedSha256) {
throw "radare2 archive checksum mismatch: expected $expectedSha256, got $actualSha256"
}
& ".github/scripts/download_verified_artifact.ps1" -Url $url -Output $archive -Sha256 $expectedSha256
$destination = Join-Path $env:RUNNER_TEMP "radare2-$version"
Expand-Archive -Path $archive -DestinationPath $destination -Force
$bin = Join-Path $destination "radare2-$version-w64\bin"
Expand Down Expand Up @@ -320,6 +319,7 @@ jobs:
test_targets = [
"tests/unit/test_circular_imports.py",
"tests/unit/test_cli_basic_commands.py::test_cli_version_function",
"tests/unit/test_public_surface_contract.py",
"tests/unit/test_pe_handler_parsing_contract.py",
"tests/unit/test_pe_handler_struct_parse.py",
"tests/unit/test_macho_parse_basic.py",
Expand Down Expand Up @@ -438,4 +438,5 @@ jobs:
/tmp/r2morph-wheel-venv/bin/python -W error -m pytest \
tests/unit/test_circular_imports.py \
tests/unit/test_cli_basic_commands.py::test_cli_version_function \
tests/unit/test_public_surface_contract.py \
--no-cov --tb=short
7 changes: 2 additions & 5 deletions .github/workflows/differential-corpus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ concurrency:
- ".github/workflows/differential-corpus.yml"
- ".github/workflows/ci.yml"
- ".github/workflows/adversarial-benchmark.yml"
- ".github/scripts/download_verified_artifact.ps1"
- ".github/scripts/install_radare2.sh"
- "docs/compatibility-corpus.md"
- "docs/pass-maturity.md"
Expand Down Expand Up @@ -1612,11 +1613,7 @@ jobs:
$archive = Join-Path $env:RUNNER_TEMP $archiveName
$url = "https://github.com/radareorg/radare2/releases/download/$version/$archiveName"
$expectedSha256 = "913e7d95e7458226a5e783240877f2c1d405398ab38ba176ce9b12e046e31f34"
Invoke-WebRequest -Uri $url -OutFile $archive
$actualSha256 = (Get-FileHash -Algorithm SHA256 -Path $archive).Hash.ToLowerInvariant()
if ($actualSha256 -ne $expectedSha256) {
throw "radare2 archive checksum mismatch: expected $expectedSha256, got $actualSha256"
}
& ".github/scripts/download_verified_artifact.ps1" -Url $url -Output $archive -Sha256 $expectedSha256
$destination = Join-Path $env:RUNNER_TEMP "radare2-$version"
Expand-Archive -Path $archive -DestinationPath $destination -Force
$bin = Join-Path $destination "radare2-$version-w64\bin"
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ jobs:
with:
python-version: "3.12"

- name: Install release dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Extract version from tag
id: get_version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 0.4.0-alpha.3

- Clarifies campaign-specific IDA and Triton availability and limits VM resistance
claims to the finite evidence actually measured.
- Promotes instruction expansion and block reordering into the five-pass Tier 1
Linux ELF x86-64 contract after native, corpus, composition, and analyzer
evidence completed.
Expand All @@ -13,7 +15,7 @@
documented wheel gate runs from a normal development installation.
- Fixes release artifact download in the isolated PyPI publish job.
- Publishes the same verified ELF x86-64 support contract as alpha.2.
- Keeps the VM milestone blocked until external human review records signoff.
- Independent human review approval is recorded for the VM resistance campaign.

## 0.4.0-alpha.2

Expand Down
52 changes: 33 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ x86-64 or equivalent CodeVirtualization support.

The machine-readable contract is [`docs/support-matrix.json`](docs/support-matrix.json):
the generated matrix currently records 22/22 evidenced cells for the official
ELF x86-64 target (100.0% evidence) and 32/242 evidenced cells for non-official
targets (13.22% evidence). It currently classifies 5 passes as Tier 1 and
ELF x86-64 target (100.0% evidence) and 35/242 evidenced cells for non-official
targets (14.46% evidence). It currently classifies 5 passes as Tier 1 and
17 passes as experimental.
The scheduled extended maturity smoke now records output-size,
transform-duration, runtime-duration, and static metric summaries for every
Expand Down Expand Up @@ -174,13 +174,12 @@ transform duration, runtime duration, and static analyzer evidence while
comparing exit code, stdout, stderr, created files, and declared observable
effects across nine seed-derived inputs.

The latest local adversarial refresh measures all 162 repository fixtures:
The 2026-09-20 local adversarial campaign measures all 162 repository fixtures:
`angr` completed 162/162 runs, while radare2, objdump, and the custom analyzer
also completed all runs. Unicorn completed 155/162 runs; its seven unavailable
rows are retained with their instruction-support reasons. Binary Ninja, IDA,
and Triton remain explicit unavailable analyzer slots; Binary Ninja is on hold
for the current milestone. Ghidra is now provisioned by the scheduled
campaign. The bounded
rows are retained with their instruction-support reasons. In that campaign,
IDA and Triton were unavailable; these rows remain explicit and are not counted
as completed analysis. Ghidra is provisioned by the scheduled campaign. The bounded
report is
[`docs/protection-adversarial-angr-local-2026-09-20.json`](docs/protection-adversarial-angr-local-2026-09-20.json).
The earlier focused `angr` fixture remains available in
Expand All @@ -190,23 +189,38 @@ Binary Ninja is an explicit analyzer slot; the focused local
fixture records `binary-ninja` as unavailable because `module 'binaryninja' is unavailable`.
The current installed API is importable, but the headless benchmark reports
`analyzer license is unavailable`; this remains an explicit evidence gap while
the slot is on hold.
The VM review packet still has `human_signoff: not-attested` and
`release_decision: block-vm-milestone`; memory, direct/indirect calls, returns,
flags, FP/SIMD, varargs/ABI, unwinding, TLS/signals, SSA, and liveness paths
remain explicit review scope, and unsupported instructions must fail closed
instead of producing partial protected functions. Unsupported-instruction
diagnostics must include instruction address, mnemonic, type, size, bounded
opcode preview, capability, and reason.
VM ISA/opcode diversification, dispatcher/handler alternatives,
superinstructions, anti-tamper, and progressive bytecode protection remain
explicit human-review scope before the virtualizer milestone can be marked
complete.
the slot is on hold. Separately, the 159-sample evidence summarized in
[`docs/independent-review.json`](docs/independent-review.json) records
`159 samples, 159 Triton runs`, `159 samples, 318 completed analyses` for IDA,
and `159 samples, 0 IDA errors`. These are campaign-specific
results: availability in one campaign does not fill unavailable rows in another,
and the all-named-analyzers 1.0 criterion remains open.
The VM review packet records `human_signoff: attested` and
`release_decision: signoff-recorded`. Human independent review approved the
reviewed commit `a111f923df43a66826b71ab70db8a484532fbf3b`. The project owner
confirms Marc Rivero Lopez's independence and specialist experience in binary
rewriting and virtualization. He reviewed memory, direct/indirect calls,
returns, flags, FP/SIMD, varargs/ABI,
unwinding, TLS/signals, SSA, and liveness paths; unsupported instructions must
fail closed instead of producing partial protected functions. Diagnostics
include instruction address, mnemonic, type, size, bounded opcode preview,
capability, and reason. The review covered VM ISA/opcode diversification,
dispatcher/handler alternatives, superinstructions, anti-tamper, and progressive
bytecode protection, fuzz properties, failure handling, and bounded report
data. This approval applies to that commit; changes to the reviewed VM
implementation require a new independent review.
Current VM resistance artifacts cover 10 seeds with 255 handlers per seed,
0 exact normalized cross-seed handler matches, 12 handler stride values, and
target handler stride diversity recorded in
[`docs/protection-handler-clustering.json`](docs/protection-handler-clustering.json)
and [`docs/protection-bytecode-grammar.json`](docs/protection-bytecode-grammar.json).
These finite seed-diversity measurements describe generated output variation;
they do not measure generalized attack cost or establish resistance to
professional reverse engineering. The independent analysis report explicitly
limits its evidence to one fixture and one pass and states that it does not
establish general resistance to professional reverse engineering. The report
does not replace the required three-analyzer release campaign. Published
resistance results remain an open 1.0 criterion.

---

Expand Down
6 changes: 6 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# r2morph API Documentation

> **Compatibility scope:** This guide includes module-level examples that are
> useful for development but are not all stable imports. The intended 1.0
> compatibility surface and deprecation policy are defined in
> [stability-contract.md](stability-contract.md); currently the package-root
> exports and documented CLI surface are the contracted entry points.

## Overview

r2morph is a metamorphic mutation engine for binary transformation. The API is organized into several modules:
Expand Down
16 changes: 16 additions & 0 deletions docs/compatibility-corpus.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ compiled case is an additional evidence point, not a support promotion.
The Windows PE preview job also executes a real NOP-plus-register-substitution
composition and validates the repaired PE checksum; it remains preview evidence
and does not promote PE to the official support tier.
On 2026-11-10, the same PE test module ran locally on macOS 27.2 ARM64 with
MinGW-w64 GCC 16.2 and Wine 11.0: seven generated-binary mutation tests passed
and the Windows-only fixture test was skipped. This confirms an additional
Wine execution path; it is not native Windows evidence or a PE parity claim.
The PE block-reordering regression now builds a separate control-flow fixture,
executes the original and mutated images under native Windows or Wine for nine
inputs, and validates the repaired PE checksum and integrity. A passing local
run is preview evidence for this pass/target cell only; it does not promote
PE x86-64 to parity with Linux ELF x86-64.
On 2026-11-10, a connected licensed static-analysis service inspected the
original and CodeVirtualization-protected `elf_x86_64` fixture. The bounded
function and decompilation observations are in
[`protection-independent-analysis-2026-11-10.json`](protection-independent-analysis-2026-11-10.json).
The service did not expose its version; runtime equivalence was not measured.
This one-fixture result does not establish general resistance or replace the
three-analyzer release campaign.
The cross-format matrix additionally exercises `basic` and `complex` CFG
variants for those three ELF targets across the same four individual passes.
The workflow pins the collected matrix at 73 cases so loss of a preview corpus
Expand Down
11 changes: 11 additions & 0 deletions docs/human-review-signoff.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"schema_version": 1,
"reviewer": "Marc Rivero Lopez",
"review_date_utc": "2026-11-08",
"result": "APPROVE",
"reviewed_commit": "a111f923df43a66826b71ab70db8a484532fbf3b",
"independent": true,
"independence_confirmation": "confirmed by the project owner on 2026-11-09",
"specialist_expertise_confirmation": "binary rewriting and virtualization experience confirmed by the project owner on 2026-11-09",
"findings": []
}
Loading
Loading