Skip to content

feat: bind security evidence to exact review and recovery (TAB-26–29) - #52

Merged
hudsonaikins merged 3 commits into
codex/tab-24-25-safe-packetsfrom
codex/tab-26-security-evidence
Sep 12, 2026
Merged

hudsonaikins merged 3 commits into
codex/tab-24-25-safe-packetsfrom
codex/tab-26-security-evidence

Conversation

@hudsonaikins

@hudsonaikins hudsonaikins commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

TAB-26 through TAB-29: provenance receives separate bounded secrets, authorization, trust, and dependency checks. Receipts bind the exact candidate, safe packet, and policy; missing/malformed/timed-out checks block, and findings exclude raw matches. Pinned scanner installation and required security checks run in CI. The integrated CLI/GitHub review keeps review and security distinct, protects publication with scoped approval and a durable reservation, and demonstrates 11 failure/recovery cases with clean-store replay. Final demo review uses its secured lineage. PRs #53–55 are merged into this branch.

Candidate 04341aebbdbb6b65afbc3cbd1385afce09414608: required local validation, hosted product validation, and hosted Quality passed. Author review found no remaining code findings; the Plane bot reference is informational.

Scope is intentionally bounded: Gitleaks 8.30.1, ast-grep 0.45.1, listed JavaScript/TypeScript rules, and declared npm dependencies that block pending separate vulnerability evidence. This is not proof of absence of all security defects. Provider fixtures and the historical blocked live demonstration satisfy the stated TAB-21/TAB-27 acceptance; they do not claim complete live-provider provenance.

Stacked on #51. Foundation Buildkite still blocks main integration. Release and deployment remain separate decisions.

hudsonaikins-crown added 2 commits September 12, 2026 17:12
Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1
Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1
@makeplane

makeplane Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

#53)

* feat: show actionable provenance review and GitHub statuses

Plane-Work-Item: TAB-27
Entire-Checkpoint: 3a4c8131eec1

* test: demonstrate failure recovery and secured review (TAB-28/TAB-29) (#54)

* test: demonstrate provenance failure and clean-store recovery (TAB-28)

Entire-Checkpoint: 3a4c8131eec1

* fix: review the secured lineage in the release demo (TAB-29) (#55)

* test: generate unsafe token fixture at runtime (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

* fix: demonstrate review of the secured provenance lineage (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>
@hudsonaikins hudsonaikins changed the title feat: run separate security checks for provenance candidates feat: bind security evidence to exact review and recovery (TAB-26–29) Sep 12, 2026
@hudsonaikins
hudsonaikins marked this pull request as ready for review September 12, 2026 23:20
@hudsonaikins
hudsonaikins merged commit 8370782 into codex/tab-24-25-safe-packets Sep 12, 2026
4 checks passed
@hudsonaikins
hudsonaikins deleted the codex/tab-26-security-evidence branch September 12, 2026 23:20
hudsonaikins added a commit that referenced this pull request Sep 12, 2026
* fix: enforce complete review packet bounds and candidate acceptance

Plane-Work-Item: TAB-25

Validates TAB-24 candidate movement and unrelated-history rejection.

Entire-Checkpoint: 7098fc8f9b88

* test: validate review packets with the native schema checker

Plane-Work-Item: TAB-25
Entire-Checkpoint: 7098fc8f9b88

* feat: exact security evidence, review, and recovery (TAB-26–29) (#52)

* feat: bind separate security checks to immutable review candidates

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* ci: require pinned provenance security scanners

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* feat: exact review results, safe publication, and recovery (TAB-27–29) (#53)

* feat: show actionable provenance review and GitHub statuses

Plane-Work-Item: TAB-27
Entire-Checkpoint: 3a4c8131eec1

* test: demonstrate failure recovery and secured review (TAB-28/TAB-29) (#54)

* test: demonstrate provenance failure and clean-store recovery (TAB-28)

Entire-Checkpoint: 3a4c8131eec1

* fix: review the secured lineage in the release demo (TAB-29) (#55)

* test: generate unsafe token fixture at runtime (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

* fix: demonstrate review of the secured provenance lineage (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>
hudsonaikins added a commit that referenced this pull request Sep 12, 2026
* feat: preserve safe source failure reasons in review packets

Plane-Work-Item: TAB-23
Entire-Checkpoint: 95aae876ef91

* feat: exact-candidate packets, security, and review (TAB-24–29) (#51)

* fix: enforce complete review packet bounds and candidate acceptance

Plane-Work-Item: TAB-25

Validates TAB-24 candidate movement and unrelated-history rejection.

Entire-Checkpoint: 7098fc8f9b88

* test: validate review packets with the native schema checker

Plane-Work-Item: TAB-25
Entire-Checkpoint: 7098fc8f9b88

* feat: exact security evidence, review, and recovery (TAB-26–29) (#52)

* feat: bind separate security checks to immutable review candidates

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* ci: require pinned provenance security scanners

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* feat: exact review results, safe publication, and recovery (TAB-27–29) (#53)

* feat: show actionable provenance review and GitHub statuses

Plane-Work-Item: TAB-27
Entire-Checkpoint: 3a4c8131eec1

* test: demonstrate failure recovery and secured review (TAB-28/TAB-29) (#54)

* test: demonstrate provenance failure and clean-store recovery (TAB-28)

Entire-Checkpoint: 3a4c8131eec1

* fix: review the secured lineage in the release demo (TAB-29) (#55)

* test: generate unsafe token fixture at runtime (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

* fix: demonstrate review of the secured provenance lineage (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>
hudsonaikins added a commit that referenced this pull request Sep 12, 2026
#49)

* feat: rebuild provenance from pinned source snapshots

Plane-Work-Item: TAB-22
Entire-Checkpoint: 95aae876ef91

* feat: explicit provenance verdicts and safe review (TAB-23–29) (#50)

* feat: preserve safe source failure reasons in review packets

Plane-Work-Item: TAB-23
Entire-Checkpoint: 95aae876ef91

* feat: exact-candidate packets, security, and review (TAB-24–29) (#51)

* fix: enforce complete review packet bounds and candidate acceptance

Plane-Work-Item: TAB-25

Validates TAB-24 candidate movement and unrelated-history rejection.

Entire-Checkpoint: 7098fc8f9b88

* test: validate review packets with the native schema checker

Plane-Work-Item: TAB-25
Entire-Checkpoint: 7098fc8f9b88

* feat: exact security evidence, review, and recovery (TAB-26–29) (#52)

* feat: bind separate security checks to immutable review candidates

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* ci: require pinned provenance security scanners

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* feat: exact review results, safe publication, and recovery (TAB-27–29) (#53)

* feat: show actionable provenance review and GitHub statuses

Plane-Work-Item: TAB-27
Entire-Checkpoint: 3a4c8131eec1

* test: demonstrate failure recovery and secured review (TAB-28/TAB-29) (#54)

* test: demonstrate provenance failure and clean-store recovery (TAB-28)

Entire-Checkpoint: 3a4c8131eec1

* fix: review the secured lineage in the release demo (TAB-29) (#55)

* test: generate unsafe token fixture at runtime (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

* fix: demonstrate review of the secured provenance lineage (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>
hudsonaikins added a commit that referenced this pull request Sep 12, 2026
…48)

* feat: normalize candidate-bound provenance source snapshots

Plane-Work-Item: TAB-21
Entire-Checkpoint: 95aae876ef91

* fix: select comparison base for manual quality checks

Plane-Work-Item: TAB-21
Entire-Checkpoint: 95aae876ef91

* feat: replay source evidence with safe review and recovery (TAB-22–29) (#49)

* feat: rebuild provenance from pinned source snapshots

Plane-Work-Item: TAB-22
Entire-Checkpoint: 95aae876ef91

* feat: explicit provenance verdicts and safe review (TAB-23–29) (#50)

* feat: preserve safe source failure reasons in review packets

Plane-Work-Item: TAB-23
Entire-Checkpoint: 95aae876ef91

* feat: exact-candidate packets, security, and review (TAB-24–29) (#51)

* fix: enforce complete review packet bounds and candidate acceptance

Plane-Work-Item: TAB-25

Validates TAB-24 candidate movement and unrelated-history rejection.

Entire-Checkpoint: 7098fc8f9b88

* test: validate review packets with the native schema checker

Plane-Work-Item: TAB-25
Entire-Checkpoint: 7098fc8f9b88

* feat: exact security evidence, review, and recovery (TAB-26–29) (#52)

* feat: bind separate security checks to immutable review candidates

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* ci: require pinned provenance security scanners

Plane-Work-Item: TAB-26
Entire-Checkpoint: 3a4c8131eec1

* feat: exact review results, safe publication, and recovery (TAB-27–29) (#53)

* feat: show actionable provenance review and GitHub statuses

Plane-Work-Item: TAB-27
Entire-Checkpoint: 3a4c8131eec1

* test: demonstrate failure recovery and secured review (TAB-28/TAB-29) (#54)

* test: demonstrate provenance failure and clean-store recovery (TAB-28)

Entire-Checkpoint: 3a4c8131eec1

* fix: review the secured lineage in the release demo (TAB-29) (#55)

* test: generate unsafe token fixture at runtime (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

* fix: demonstrate review of the secured provenance lineage (TAB-29)

Entire-Checkpoint: 3a4c8131eec1

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

---------

Co-authored-by: hudsonaikins-crown <hudson.aikins@blanoire.co>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 04341aebbd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

function execute(command, args, { cwd, signal, binary = false } = {}) {
return new Promise((resolvePromise, reject) => {
execFile(command, args, {
cwd, signal, encoding: binary ? "buffer" : "utf8", timeout: 240000, maxBuffer: 4 * 1024 * 1024,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Allow blobs up to the declared scan bound

When a tracked regular file is larger than 4 MiB, git cat-file blob exceeds this shared maxBuffer and rejects with ERR_CHILD_PROCESS_STDIO_MAXBUFFER before snapshot can apply its declared 32 MiB aggregate limit. Consequently, an otherwise valid candidate containing a 4–32 MiB asset cannot produce a security receipt, and the newly required CI security validator blocks even though the candidate remains within the scanner's explicit size bound.

Useful? React with 👍 / 👎.

}

function dependencyGroup(manifest, key) {
const dependencies = manifest[key] ?? {};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject null dependency groups

When a manifest explicitly contains a malformed group such as "dependencies": null, the nullish fallback converts it to an empty object, so no declaration is recorded and scanDependencies reports passed if the other groups are absent. This contradicts the fail-closed handling of malformed dependency manifests and can produce successful dependency evidence for an invalid package manifest; only a genuinely absent property should receive the empty-object default.

Useful? React with 👍 / 👎.

Comment on lines +43 to +46
"minItems": 4,
"maxItems": 4,
"items": {
"$ref": "#/$defs/check"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require every security category in the receipt schema

When a receipt is validated only against this published schema, the four entries may all use the same category because the array is constrained only by length. Such a schema-valid receipt can claim passed while omitting authorization, trust, and dependency checks entirely, despite the contract requiring four separate checks; encode each required category exactly once rather than accepting any four check objects.

Useful? React with 👍 / 👎.

Comment on lines +53 to +55
const target = join(directory, path);
await mkdir(dirname(target), { recursive: true });
await writeFile(target, blob.stdout, { mode: 0o600 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Detect filesystem-colliding candidate paths

On a case-insensitive filesystem such as the default macOS setup supported by the installer, a Git tree containing distinct paths such as AUTH.js and auth.js writes both blobs to the same temporary file. The later write silently replaces the earlier content while both paths remain in the digest map, so a secret or unsafe construct in the overwritten blob is never scanned and the candidate can receive a false passing result; reject colliding paths or scan without materializing them onto a case-folding filesystem.

Useful? React with 👍 / 👎.

Comment on lines +132 to +134
"path": {
"$ref": "#/$defs/text"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Constrain finding paths in the public schema

When downstream tooling uses the published JSON schema as its validation boundary, paths such as ../secret, /absolute/path, or backslash-based traversal are accepted because path references only the generic text definition. The runtime producer explicitly rejects these values, so the schema currently accepts receipts that runtime import rejects and permits external consumers to treat out-of-candidate locations as valid findings; give finding paths the same safe-relative-path constraints as finding().

Useful? React with 👍 / 👎.

Comment on lines +53 to +54
function securityDetails(lineage, receipt, policyDigest, now, repo) {
if (receipt === null) return { detailsState: "not_loaded", findings: [], checks: [] };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Require a verified receipt before reporting security success

When a lineage reaches review or review-intent through the generic import path with an arbitrary tabellio security observation marked passed, this branch leaves the receipt unloaded while the security section and GitHub status still derive a green result from that observation. Because generic lineage integrity is only a recomputable hash, this bypasses attachSecurityReview entirely and allows publication of a successful security context without any of the four receipt checks; a missing verified receipt must keep security blocked or the store must retain proof that the observation was created by receipt verification.

Useful? React with 👍 / 👎.

Comment on lines +38 to +40
const packet = buildReviewPacket(lineage, { candidate, now });
const binding = { candidateId: packet.candidate.id, packetDigest: packet.digest, policyDigest };
const results = await Promise.all(SECURITY_CHECKS.map(async (category) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject review packets containing future evidence

When an input lineage contains a validation timestamp later than the security review time, buildReviewPacket correctly records that fact as stale, but runSecurityReview ignores the packet reasons and can still issue a passed receipt. After wall-clock time advances beyond the validation timestamp, attaching that receipt produces a lineage that evaluates as fully passed even though the security receipt claims to have consumed evidence that did not yet exist; reject packet reasons other than the expected missing-security reason, or explicitly enforce that the review follows its linked validation.

Useful? React with 👍 / 👎.

Comment on lines +6 to +9
if [[ -n "${TABELLIO_SECURITY_TOOLS_DIR:-}" ]]; then
security_tools_root="$TABELLIO_SECURITY_TOOLS_DIR"
else
security_tools_root="$(mktemp -d "${TMPDIR:-/tmp}/tabellio-security-tools.XXXXXX")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize the configured tools directory to an absolute path

When TABELLIO_SECURITY_TOOLS_DIR is configured as a relative reusable directory, the installer succeeds in the repository and exports relative PATH and TABELLIO_GITLEAKS entries, but scanner subprocesses later run with the temporary scan root as their working directory. Those relative executable paths then resolve under the temporary directory and every scan becomes unavailable, so documented cache configurations such as .cache/security-tools make the required validator block; canonicalize this directory to an absolute path before exporting it.

Useful? React with 👍 / 👎.

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