From 0a57fb7d0c4d2b5976ebbe632834c8b543140a48 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:44:47 +0200 Subject: [PATCH 01/11] Update Jackson to 2.22.3 --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5f7a5c6..d30677c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,8 +12,8 @@ repositories { dependencies { compileOnly("net.portswigger.burp.extensions:montoya-api:2026.7") - implementation("com.fasterxml.jackson.core:jackson-databind:2.22.2") - implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.22.2") + implementation("com.fasterxml.jackson.core:jackson-databind:2.22.3") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.22.3") implementation("com.google.re2j:re2j:1.8") testImplementation("net.portswigger.burp.extensions:montoya-api:2026.7") From 50b316133e6fec0700820e883bca0d6c738b9246 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:44:50 +0200 Subject: [PATCH 02/11] Refresh Jackson dependency locks --- gradle.lockfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.lockfile b/gradle.lockfile index 6e46141..61fb059 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -3,10 +3,10 @@ # This file is expected to be part of source control. # To regenerate this file, run: ./gradlew :dependencies --write-locks com.fasterxml.jackson.core:jackson-annotations:2.22=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.22.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.22.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.22.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.22.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.22.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.22.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.22.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.22.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.re2j:re2j:1.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath net.portswigger.burp.extensions:montoya-api:2026.7=compileClasspath,testCompileClasspath,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath From c99c6161e13a087e0757c6a34e08b185702d8040 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:44:52 +0200 Subject: [PATCH 03/11] Harden CI artifact verification --- .github/workflows/build.yml | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52bfbf2..4773944 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Java - uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: temurin java-version: "21" @@ -29,11 +29,39 @@ jobs: uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 # v6 - name: Build and test - run: ./gradlew clean test jar + run: ./gradlew clean test jar --no-daemon + + - name: Verify distributable JAR + shell: bash + run: | + set -euo pipefail + mapfile -t jars < <(find build/libs -maxdepth 1 -type f -name 'workflowguard-*.jar' -print) + if [[ ${#jars[@]} -ne 1 ]]; then + echo "Expected exactly one WorkflowGuard JAR, found ${#jars[@]}" >&2 + exit 1 + fi + + jar_path="${jars[0]}" + if jar tf "$jar_path" | grep -q '^burp/api/montoya/'; then + echo "The distributable JAR must not bundle Montoya API classes." >&2 + exit 1 + fi + + duplicates="$(jar tf "$jar_path" | sort | uniq -d)" + if [[ -n "$duplicates" ]]; then + echo "Duplicate JAR entries detected:" >&2 + echo "$duplicates" >&2 + exit 1 + fi + + sha256sum "$jar_path" > "$jar_path.sha256" + sha256sum -c "$jar_path.sha256" - name: Upload extension JAR uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: workflowguard-extension - path: build/libs/workflowguard-*.jar + path: | + build/libs/workflowguard-*.jar + build/libs/workflowguard-*.jar.sha256 if-no-files-found: error From 84b05bab5c9fd05eae0f2194334983e80bf4f125 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:45:14 +0200 Subject: [PATCH 04/11] Add deterministic release workflow --- .github/workflows/release.yml | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..63b00c7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,104 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + + - name: Set up Java + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + with: + distribution: temurin + java-version: "21" + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 # v6 + + - name: Validate tag and project version + id: version + shell: bash + run: | + set -euo pipefail + project_version="$(./gradlew properties --no-daemon -q | awk -F': ' '$1 == "version" { print $2 }')" + tag_version="${GITHUB_REF_NAME#v}" + if [[ -z "$project_version" || "$project_version" != "$tag_version" ]]; then + echo "Tag version '$tag_version' does not match Gradle project version '$project_version'." >&2 + exit 1 + fi + echo "version=$tag_version" >> "$GITHUB_OUTPUT" + + - name: Build and test release + run: ./gradlew clean test jar --no-daemon + + - name: Verify and stage release artifacts + id: artifacts + shell: bash + run: | + set -euo pipefail + mapfile -t jars < <(find build/libs -maxdepth 1 -type f -name 'workflowguard-*.jar' -print) + if [[ ${#jars[@]} -ne 1 ]]; then + echo "Expected exactly one WorkflowGuard JAR, found ${#jars[@]}" >&2 + exit 1 + fi + + jar_path="${jars[0]}" + if jar tf "$jar_path" | grep -q '^burp/api/montoya/'; then + echo "The distributable JAR must not bundle Montoya API classes." >&2 + exit 1 + fi + + duplicates="$(jar tf "$jar_path" | sort | uniq -d)" + if [[ -n "$duplicates" ]]; then + echo "Duplicate JAR entries detected:" >&2 + echo "$duplicates" >&2 + exit 1 + fi + + mkdir -p dist + cp "$jar_path" dist/ + jar_name="$(basename "$jar_path")" + ( + cd dist + sha256sum "$jar_name" > "$jar_name.sha256" + sha256sum -c "$jar_name.sha256" + ) + + notes_path="docs/release-notes-${{ steps.version.outputs.version }}.md" + if [[ ! -f "$notes_path" ]]; then + echo "Missing release notes: $notes_path" >&2 + exit 1 + fi + echo "notes_path=$notes_path" >> "$GITHUB_OUTPUT" + + - name: Upload verified workflow artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: workflowguard-release-${{ steps.version.outputs.version }} + path: dist/ + if-no-files-found: error + + - name: Publish GitHub release + env: + GH_TOKEN: ${{ github.token }} + NOTES_PATH: ${{ steps.artifacts.outputs.notes_path }} + shell: bash + run: | + set -euo pipefail + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + echo "Release $GITHUB_REF_NAME already exists; refusing to overwrite it." >&2 + exit 1 + fi + + gh release create "$GITHUB_REF_NAME" dist/* --verify-tag --title "WorkflowGuard ${{ steps.version.outputs.version }}" --notes-file "$NOTES_PATH" From ff7880278442a02663fb2b5d51cd5c8d499e8fe9 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:45:16 +0200 Subject: [PATCH 05/11] Document release integrity process --- docs/release-integrity.md | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/release-integrity.md diff --git a/docs/release-integrity.md b/docs/release-integrity.md new file mode 100644 index 0000000..fb31f76 --- /dev/null +++ b/docs/release-integrity.md @@ -0,0 +1,44 @@ +# Release integrity and process + +This document defines the release process for WorkflowGuard. The goal is to +ensure that the binary published on GitHub, its checksum, the source tag, and +the release notes all refer to the same build. + +## Required process + +1. Update the Gradle project version and create matching + `docs/release-notes-X.Y.Z.md`. +2. Merge all intended changes to `main` and require a green Build workflow. +3. Create and push the annotated tag `vX.Y.Z` from the exact release commit. +4. Do not create the GitHub release manually before pushing the tag. +5. Let `.github/workflows/release.yml` build, test, verify, checksum, and + publish the release artifacts. +6. Download the published JAR and `.sha256` file and verify them independently + before submitting or updating the BApp Store entry. + +The release workflow fails if the tag version does not match the Gradle project +version, if more than one WorkflowGuard JAR is produced, if Montoya API classes +are bundled, if duplicate JAR entries are present, or if release notes are +missing. + +## Historical correction for 0.3.3 + +The validation record created on 2026-07-31 refers to a build with: + +- size: 2,852,241 bytes; +- SHA-256: + `8FB9CD29EC79CE5B9489A55F7BCAC321393E7B4426CE63BD84A0B9E5D29955DD`. + +The JAR currently attached to the GitHub `v0.3.3` release was uploaded on +2026-08-25 and GitHub reports: + +- size: 2,854,635 bytes; +- SHA-256: + `84422c6751fd05574b5e3cdfd20bc64c2a5fd7a6d74be28b0d2d8ccd0df8d043`. + +These are different binary builds. The July validation checksum must therefore +not be used to verify the currently attached release asset. The release page +body should be corrected manually to remove the stale size and checksum. + +Starting with the next release, the release workflow is the canonical producer +of both the JAR and its checksum. From d92218352c1af406c90a23d9a9312846ec5576a8 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:45:45 +0200 Subject: [PATCH 06/11] Refresh BApp readiness evidence --- docs/bapp-readiness.md | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/docs/bapp-readiness.md b/docs/bapp-readiness.md index 34e0931..2103e25 100644 --- a/docs/bapp-readiness.md +++ b/docs/bapp-readiness.md @@ -1,18 +1,18 @@ # BApp Store publication readiness -Assessment date: 2026-07-31 +Assessment date: 2026-09-24 -PortSwigger criteria revision checked: 2026-07-28 +PortSwigger criteria revision checked: 2026-09-22 ## Verdict -WorkflowGuard `0.3.3` satisfies the current technical BApp Store acceptance -criteria. It is ready to be exposed as a public release candidate for +WorkflowGuard `0.3.3` continues to satisfy the current technical BApp Store +acceptance criteria. The source repository is public and suitable for PortSwigger review. -Submission is intentionally not complete yet. The repository remains private, -and the repository owner must personally accept the legal confirmations in -PortSwigger's extension-portal issue form. +Submission is not recorded as complete in this repository. The repository owner +must personally accept the legal confirmations in PortSwigger's +extension-portal issue form. ## Acceptance-criteria matrix @@ -44,11 +44,14 @@ PortSwigger's extension-portal issue form. - The earlier full Community campaign additionally covered authorized loopback execution, invariant failure, cleanup verification, evidence export, issue submission behavior, and unload/reload. -- Release JAR: `workflowguard-0.3.3.jar`, **2,852,241 bytes**. -- SHA-256: +- The 2026-07-31 validation build recorded a JAR size of **2,852,241 bytes** + and SHA-256 `8FB9CD29EC79CE5B9489A55F7BCAC321393E7B4426CE63BD84A0B9E5D29955DD`. -- JAR inventory: 1,446 entries, no duplicate entries, no bundled Montoya - classes, and all expected project/dependency notices present. + The binary currently attached to the GitHub `v0.3.3` release is a different + build; see [release integrity](release-integrity.md) before using a checksum + for verification. +- The validated JAR inventory contained 1,446 entries, no duplicate entries, + no bundled Montoya classes, and all expected project/dependency notices. - Full reachable Git history and publishable files: zero Gitleaks findings. - OSV query for all bundled runtime components: zero known vulnerabilities on the assessment date. @@ -58,6 +61,18 @@ PortSwigger's extension-portal issue form. The exact final verification commands and UI observations are recorded in [community-validation-20260731.md](community-validation-20260731.md). +## Compatibility freshness + +- PortSwigger's BApp Store acceptance criteria and submission guidance were + rechecked on 2026-09-24 against documentation updated 2026-09-22. +- The latest Burp Suite Professional / Community release at this review is + `2026.9`, published 2026-09-21. +- Maven Central currently lists Montoya API `2026.7`, which remains the + compile-time API used by WorkflowGuard. +- Direct runtime/UI validation evidence in this repository remains against + Burp Suite Community Edition `2026.7.1`. This document does not claim a + completed direct `2026.9` regression campaign. + ## Submission fields The current PortSwigger submission process requires an accessible GitHub From ec4d1036721d359750ecf5762a2a0289ad3f96f7 Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:45:47 +0200 Subject: [PATCH 07/11] Clarify v0.3.3 artifact provenance --- docs/release-notes-0.3.3.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/release-notes-0.3.3.md b/docs/release-notes-0.3.3.md index cfcc765..2f0b3e7 100644 --- a/docs/release-notes-0.3.3.md +++ b/docs/release-notes-0.3.3.md @@ -40,10 +40,12 @@ Burp Suite workflow mutation extension. - Gitleaks: zero findings in reachable history and publishable files. - OSV runtime-dependency query: zero known vulnerabilities on 2026-07-31. -- Artifact: `workflowguard-0.3.3.jar` -- Size: 2,852,241 bytes -- SHA-256: - `8FB9CD29EC79CE5B9489A55F7BCAC321393E7B4426CE63BD84A0B9E5D29955DD` +The validation build used for the 2026-07-31 campaign had size 2,852,241 bytes +and SHA-256 +`8FB9CD29EC79CE5B9489A55F7BCAC321393E7B4426CE63BD84A0B9E5D29955DD`. +The binary later attached to the GitHub `v0.3.3` release is not byte-identical +to that validation build. See [release integrity](release-integrity.md) for the +current release-asset digest and the corrected verification guidance. See the [README](../README.md), [Community validation report](community-validation-20260731.md), and [BApp readiness From eda9f2b4144d52ea4949a4cb15cbb2b529c255ff Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:45:50 +0200 Subject: [PATCH 08/11] Record release hardening changes --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7170e95..77bff49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## Unreleased + +### Security + +- Update Jackson Databind and the aligned Jackson runtime components to + `2.22.3`, which includes fixes for CVE-2026-91776 and CVE-2026-91777. +- Verify the distributable JAR in CI, reject bundled Montoya API classes and + duplicate entries, and generate a SHA-256 file from the exact artifact. + +### Changed + +- Add a tag-driven release workflow that requires the tag version to match the + Gradle project version and publishes the same verified JAR/checksum pair. +- Document the `0.3.3` validation-build versus release-asset checksum + discrepancy so historical evidence is not mistaken for the attached binary. +- Refresh the BApp Store readiness review against PortSwigger's + 2026-09-22 acceptance criteria. + ## 0.3.3 - 2026-07-31 ### Security From f519921f4959a504d7d7d87f215df91b9eaaafdd Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:46:10 +0200 Subject: [PATCH 09/11] Link release integrity guidance --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index edd8fb7..d39b677 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ See [Development workflow](docs/development.md), [BApp readiness matrix](docs/bapp-readiness.md), [BApp submission text](docs/bapp-submission.md), [0.3.3 release notes](docs/release-notes-0.3.3.md), +[release integrity process](docs/release-integrity.md), [Invariant language](docs/invariants.md), [Workflow files](docs/workflow-files.md), [Architecture](docs/architecture.md), [Roadmap](docs/roadmap.md), and [Contributing](CONTRIBUTING.md) for the From 35b0ef2ebfc9ff16d4989254317de1bf2a37c4bb Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:47:30 +0200 Subject: [PATCH 10/11] Strengthen BApp uniqueness comparison --- docs/bapp-readiness.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bapp-readiness.md b/docs/bapp-readiness.md index 2103e25..92fcc5a 100644 --- a/docs/bapp-readiness.md +++ b/docs/bapp-readiness.md @@ -18,7 +18,7 @@ extension-portal issue form. | # | PortSwigger criterion | WorkflowGuard evidence | Status | | --- | --- | --- | --- | -| 1 | Unique function | Generates controlled multi-step state mutations and evaluates explicit probes, invariants, and cleanup; this differs from request-matrix, sequence-comparison, and endpoint-organization BApps. | Pass | +| 1 | Unique function | Generates controlled multi-step state mutations and evaluates explicit probes, invariants, and cleanup; this differs from Sequence Comparer, AuthMatrix, Autorize, Auth Analyzer, and API Workflow Manager, which focus on comparison, authorization replay, or endpoint organization rather than mutation of complete stateful workflows with explicit before/after state assertions. | Pass | | 2 | Clear name and description | `WorkflowGuard`, one-line summary, detailed overview, features, and usage text are prepared in [bapp-submission.md](bapp-submission.md). | Pass | | 3 | Secure operation | Untrusted request messages are validated before storage and again after rendering. The modeled method, raw method, effective target, Host, scope, request count, origin-bound credentials, extracted values, and state-change confirmation are all enforced. | Pass | | 4 | All dependencies included | Jackson and RE2/J runtime dependencies, project license, third-party notices, and dependency licenses are embedded in the release JAR. Montoya remains `compileOnly` because Burp provides it. | Pass | From af79d869b521059191360df965c6f84dcfb911ea Mon Sep 17 00:00:00 2001 From: Aleff Date: Thu, 24 Sep 2026 15:47:33 +0200 Subject: [PATCH 11/11] Expand BApp differentiation evidence --- docs/bapp-submission.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/bapp-submission.md b/docs/bapp-submission.md index aeae130..e0377d5 100644 --- a/docs/bapp-submission.md +++ b/docs/bapp-submission.md @@ -48,6 +48,10 @@ viewer and persistent project files are Professional-only. invariants. - AuthMatrix compares requests across users and roles; WorkflowGuard maintains isolated per-origin actor sessions across complete multi-step flows. +- Autorize and Auth Analyzer automatically replay requests with alternate + credentials and classify authorization outcomes; WorkflowGuard instead + mutates complete captured sequences and evaluates explicit before/after state + invariants, lifecycle ordering, stale values, and verified cleanup. - API Workflow Manager organizes endpoints; WorkflowGuard models action, probe, and cleanup roles, resolves dynamic variables, and verifies resulting state.