Skip to content

v4.3.0

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Sep 23:28
· 23 commits to main since this release

What's changed in v4.3.0

Highlights

Releases are signed now, and self-update verifies before it replaces the binary.

Until this release, self-update compared a .sha256 against the binary it shipped beside. Both
files live on the same release, so anyone able to publish or amend one publishes both and the check
passes. That defends against a corrupted transfer, not against substitution at the source — and the
distinction matters here more than usual, because the binary is the trust root for every instruction
file Specnaut writes into a project.

Signing is keyless, because a key pair is structurally forbidden in this repository: a stored key
would have to be an Actions secret, and this repository holds none by policy. The release workflow
exchanges its OIDC identity for a short-lived certificate; the verifier pins the issuing authority
and the exact identity permitted to sign — bound to the specific tag, so a bundle lifted from
another release of this same repository fails on identity before the bytes are ever compared.

The anchor is compiled into the binary. It cannot be fetched from the release being verified, which
is the flaw the checksum had.

v4.3.0 is the version where the gate closes. Below it, a release without a signature installs
with a checksum and a warning. From this release on, a missing signature is refused outright, and a
signature that is present and does not verify is refused at any version — publishing one is a claim,
and a claim that fails to check is worse evidence than none. There is deliberately no fallback path:
an attacker who can amend a release can also serve a bundle from an authority we do not recognise,
so a "fall back when verification fails" branch would hand them the old control back on request.

The practical consequence, stated rather than discovered: a failed update is now a result, not a
bug. The console names which control cleared the bytes, and names the reason when none did. Read the
reason before retrying. An older binary meeting a signed release ignores the new asset and keeps
working.

What a pass means is written down where it can be read: signed by the pinned identity under the
pinned authority, over these exact bytes. It is not transparency-log inclusion, and there is no
revocation check. A verifier vague about its guarantee gets cited for one it never made.

Also in this release. The agentic surface is in scope for review, bounded by the base's own
frame, and the triage gate that routes reports can now actually reach the seat it names. The diff
command takes a path, and a path it cannot resolve is now an error instead of a confident diff of an
unrelated file. On Windows, a good install is no longer reported as broken, and the hook that a
project move used to strand now survives it and can be repaired.

Features

  • Sign releases keylessly, and verify before replacing the binary
  • The agentic chapter, and a triage gate that can reach it
  • The agentic surface is in scope, bounded by the base's own frame

Bug fixes

  • Scope to a path, and fail on one that resolves to nothing
  • Stop dispatching for a checklist line nothing defines
  • The executability check called a good Windows install broken
  • Install a hook that survives a move, and stop refusing to repair it

Adoption guide

These prompts help your AI agent adopt the new features in an existing project. Copy them into your harness, or run @specnaut-guide review-upgrade to be walked through automatically.

Sign releases keylessly, and verify before replacing the binary

Nothing to do in a consuming project — this changes how the specnaut binary
updates itself. After specnaut self-update, the console now states which
control cleared the bytes: provenance: signature verified… or provenance: checksum only…. From v4.3.0 an unsigned or unverifiable release is refused
outright rather than installed, so a failed update is a result, not a bug: read
the named reason before retrying.

The shipped security base changed too. 06-supply-chain-and-integrity.md now
separates a transport check from a signature, so a review that previously
counted a same-origin checksum as "integrity verified" will stop doing so.

Read .specnaut/memory/security/06-supply-chain-and-integrity.md, section
"Unverified auto-update or plugin loading". Then find every place this project
downloads something and executes or installs it, and for each one tell me where
the verifying material comes from — and whether an attacker who could replace
the artefact could replace that too.

The agentic chapter, and a triage gate that can reach it

specnaut upgrade delivers the new chapter, the widened triage gate, and the
updated security-expert. The next security review changes behaviour on its
own: the agentic surface is now a class the base can ground a finding in, so
it stops being reported as not assessed and starts being reviewed. If you
customised 00-triage.md or the README, upgrade preserves your copy — diff
and re-apply, or the gate keeps dismissing instruction files as trusted
config.

Read .specnaut/memory/security/11-ai-and-agentic-surface.md, then review this
repository against it: every instruction file an agent auto-loads, every tool
and permission grant, the MCP configuration, the hooks, and any pipeline that
runs an agent on text a stranger wrote. Use its "When it is NOT a finding"
section before you report anything.

The agentic surface is in scope, bounded by the base's own frame

Existing projects pick this up with specnaut upgrade, which refreshes
.specnaut/memory/security/README.md and the security-expert agent. Nothing
changes on its own: the next security review will name the agentic surface as
not assessed rather than returning silence on it, and the base now says why
the class is in scope and what is still missing. If you have customised either
file, upgrade preserves your copy — diff it and re-apply.

Read .specnaut/memory/security/README.md section "Deliberate gaps", then list
every file in this repository that an autonomous agent reads and acts on —
instructions, tool permissions, MCP config, hook scripts, skill definitions.
Then tell me which of them any security review here has ever actually covered.

Internal / chores

3 internal changes
  • Drop workflow names dependabot.yml cites and this repo does not have
  • Compare which path was named, not how Windows spells it
  • The dangling-link test could not create a dangling link on Windows

Full changelog: v4.2.6...v4.3.0