Align Cargo and NixOS package versions and collect the accumulated changes in a dated release entry. Put Security first, followed by Fixed and Added, and place the optional historical event audit guidance under Security.
The vulnerabilities were reported from code review with no exploitation reported to us. Admission protection takes effect on upgrade; an offline historical scan is an optional precaution, and purging follows inspection of its report. Preserve the stopped-service requirement and historical recovery limits in both release notes and the repair guide.
This commit changes release metadata and guidance only; it does not alter runtime behavior or publish the release. Validation: locked offline Cargo metadata, Nix module parsing, cargo fmt and git diff checks passed. Implementation CI is checked separately against dfbed25e.
Assisted-by: GPT-6
4.8 KiB
Verify and purge stored events
Optionally use ngit-grasp event-integrity-check after upgrading to v3.0.9
to check data retained by an older relay. The reported vulnerabilities were
found by code review; no exploitation has been reported to us. Upgrading enables
the admission checks without requiring this historical scan. The command
recomputes each event ID and verifies its signature independently of the SDK cache. It supports the persistent LMDB
backend; an in-memory database does not survive shutdown.
Stop the relay for both report-only and execute runs, and keep it stopped until the repair is complete. This is an offline maintenance command, not a request to the running relay. Running it against live stores can race admission and checkpoints. Use the effective data paths of the instance being repaired, including any configured private-mode path suffix.
Back up and inspect
Stop your instance using its service manager (for example,
systemctl stop ngit-grasp-<instance> for a NixOS instance). Make a backup while
it is stopped. The following commands use explicit example paths; replace them
with your instance's paths and a new backup directory:
mkdir /srv/grasp-backup-before-event-repair
cp -a /var/lib/ngit-grasp/relay /srv/grasp-backup-before-event-repair/relay
cp -a /var/lib/ngit-grasp/git /srv/grasp-backup-before-event-repair/git
ngit-grasp event-integrity-check \
--relay-data-path /var/lib/ngit-grasp/relay \
--git-data-path /var/lib/ngit-grasp/git \
> event-integrity-report.jsonl
Without --execute, no events or checkpoints are changed. An invalid-payload
finding makes the command exit nonzero after writing its summary. Read errors,
invalid checkpoint formats, and missing required paths also exit nonzero; they
must not be mistaken for a completed clean scan. A mistyped LMDB path is rejected
instead of creating an empty database.
Each invalid_event JSON line records its store, claimed ID, claimed author,
kind, claimed repository identifier (if present), and verification error. These
identity fields are untrusted. The final summary gives checked, invalid and
purged payload counts and reset negative-cache counts per store. Preserve the report alongside the backup.
Purge invalid payloads
With the relay still stopped, run:
ngit-grasp event-integrity-check \
--relay-data-path /var/lib/ngit-grasp/relay \
--git-data-path /var/lib/ngit-grasp/git \
--execute > event-integrity-purge.jsonl
# A successful repair should now produce a clean summary.
ngit-grasp event-integrity-check \
--relay-data-path /var/lib/ngit-grasp/relay \
--git-data-path /var/lib/ngit-grasp/git
The command scans the main database, existing tombstone, holding and replacement
history stores, the purgatory and rejected-event checkpoints, and the durable
.grasp/pending-saves/ journal under the Git directory. It removes
invalid payloads and their linked internal history/deletion metadata. It also
resets payload-free expiry and rejection caches: their authenticity cannot be
checked without the original events, and retaining them could block genuine
recovery after an interrupted repair. This may increase sync traffic temporarily. Valid payloads in another
store are preserved even if an invalid copy claimed the same ID. PR placeholders
without an event and valid pending events are preserved.
Removal uses exact stored IDs and the deletion lifecycle's request-removal primitive. It does not issue a signed NIP-09 request, create a permanent ID tombstone, cascade through a forged event's tags, or delete Git archives. A subsequently recovered genuine event can therefore reuse its correct ID. If an execute run fails partway through, leave the relay stopped, resolve the reported error, and rerun it; removal is idempotent. Database scanning uses pages plus a complete timestamp-boundary bucket, so memory usage depends on the largest number of events sharing one timestamp rather than all stored payloads.
Restart the upgraded relay after the clean scan. In-memory authority indexes will be rebuilt from the remaining events. For a known affected repository, the existing online integrity command can check and repair its Git storage and refs against retained authoritative event state:
ngit-grasp integrity-check --identifier my-repository \
--git-data-path /var/lib/ngit-grasp/git --repair
This queues work in the running relay; inspect the service logs for its outcome.
Payload purging cannot reconstruct previously overwritten events, deleted Git
objects, or data no longer retained locally or by a trusted peer. It also cannot
prove that a correctly signed event was authorized by the repository's policy.
Keep the backup for investigation and recovery of those cases. Do not substitute
holding-eject for this command: that command permanently removes retained
repository recovery data.