Repository navigation
Releases: Nimstead/assure
Release list
Nimstead Assure 0.5.0
A safer, clearer interface, from two rounds of UI and accessibility review (tasks/plan-0.5-ux.md, tasks/plan-0.6-ux.md; DECISIONS 41–50). Agent unchanged (0.3.0).
Upgrade from 0.4.x: run deploy/update.sh on the Docker host. No database migration. Things to know:
- Switching the trust ladder now takes Save, and switching to Auto asks you to confirm.
- Evidence packs can report
no_activityfor timeliness controls with nothing fixed and nothing overdue in the period (Cyber Essentials update management, NIST SI-2, CIS 7.3/7.4, SOC 2 CC8.1), where 0.4.0 saidmet. The pack format and verifier are unchanged; if you parse control statuses, expect a third value. The deadline text in packs now says "routine" for the tier the UI used to call "Planned". - API additions:
POST /api/remediation/jobs/{id}/cancel;GET /api/findings?overdue=true(and on the CSV export) with aduedate on each finding;asset_ids,job,busy_asset_idsandlast_attempton/api/summaryactions. Cancelled fixes no longer appear in/api/summary'sattentionlist. - Adding a machine now asks whether it's a test or production machine; there's no default.
Changed
- The trust ladder no longer switches itself to Auto. Before, choosing a mode (one click, or one arrow key) saved it at once. Now choosing only selects; Save applies it, and Auto asks first, naming how many machines it covers and the canary-first order.
- Destructive actions ask first, the same way everywhere: revoking an API token, removing someone, changing someone's role and signing out everywhere now use the same confirmation as deleting an asset. You can't demote or remove yourself from the People list.
- Fixes can be cancelled before a machine picks them up (planned or approved), and cancelling one lets you plan it again.
POST /api/remediation/jobs/{id}/cancel, admin only, recorded in the ledger. - Home links to a fix already in flight ("View fix") instead of offering "Plan fix" again. The finding drawer shows "Fix in progress" the same way. A job's summary and host link to that machine's findings.
/api/summaryactions carryasset_idsandjob. - Evidence says "No activity in period" for timeliness controls (Cyber Essentials update management, NIST SI-2, CIS 7.3/7.4, SOC 2 CC8.1) when nothing was fixed or changed in the period and nothing is overdue, instead of "Met". Overdue findings still fail. Signed packs can carry the new status
no_activity; the pack format and verifier are unchanged. The period's dates, an "as of" time and each control's counts are shown, and the period is kept in the URL (?period=30). - Onboarding asks "test or production machines?" with nothing preselected (it can't be changed after enrolment). It shows troubleshooting after two minutes without a report, and waits for you instead of redirecting on its own.
- Two-step sign-in shows a QR code to scan, drawn in the page; the typed key stays as a fallback.
- Settings is grouped into Remediation, Access, Alerts, Your account and This server, with a section bar. Saves say "Saved"; asset changes say the findings were re-ranked.
- Theme follows your system until you pick light or dark, and can go back to following it.
- On phones, Evidence is in the tab bar (Assets moved under More, with Sign out), and buttons, links and form controls are at least 44px tall.
- Read-only members see an asset's settings as text, not controls the API would refuse.
- Every dialog hands focus back to what opened it, not just the findings drawer. Focus rings are ink in both themes (crimson now only means "fix now", KEV or an error), and headings focused by the app no longer show a ring. After moving to another page, focus goes to its heading and the page title is announced.
- "Saved" and similar messages are announced through one live region; form errors sit under, and are tied to, the field they're about. A failed save shows next to the section that failed, not at the top of the page.
- Overdue is a filter.
GET /api/findings?overdue=true(and the CSV export) returns open findings past the deadline in force when they were first detected, the same rule evidence packs use; each finding carriesdue. Findings gets an "Overdue" chip, the drawer says "Due 3 Nov" or "12 days overdue", and Evidence's "Overdue and still open" links to the list. - Fixes have an address (
/remediation#job-<id>). Home, the finding drawer and Plan fix land on the fix itself. A fix planned and approved by the same person says so. - Home doesn't re-plan blind.
/api/summaryactions carrybusy_asset_idsandlast_attempt. When the last attempt failed it links to that job ("Last attempt aborted: review"), and when one host is busy you can still plan the others. Cancelled fixes no longer appear under "needs a look". - Production remediation says how to turn it on: Settings, onboarding and the refusal note name
NIMSTEAD_ALLOW_PRODUCTION_REMEDIATION=1. - The priority tier "Planned" is now labelled "Routine" in the UI and in the evidence pack's deadline text (the stored value and API stay
planned), so it can't be mistaken for a planned fix. - Command palette finds hosts too, keeps the highlighted command while results arrive, and never offers an invalid empty list.
- Assets: the agent-update explanation is said once for the list, grouped by reason; Ring and Health units are explained in place; long host names wrap.
- Findings: package names show the part that differs first (
log4j-core, then the group, muted), truncated cells carry their full text, rarer filters fold away on phones, the list dims while new filters load, and a capped list (5,000) says so. - Settings: editing one section no longer loses what you typed in another; the section bar marks where you are and fits phones; trust-ladder options have visible borders and a radio mark. The SSO and alert forms keep your edits when other data refreshes, and "Send test alert" reports success or failure.
- Evidence: the ledger says how many entries it shows of how many and names what each entry is about; mean time to remediate under a day says so.
- Sign-in and onboarding: fields focus where you'd expect, onboarding polls only once there's a command to run.
Fixed
- "Verified" next to an SSO domain was the same colour as the page in both themes.
- Admin-only buttons could not be focused, so keyboard and touch users never saw why they were off; they now stay focusable and point to a visible "Read-only" note.
- Focus returns to the finding you opened when its drawer closes.
- Keyboard focus on menus, the command palette and filters is visible (not just a faint tint); loading states are announced; the findings table names its columns on phones; reduced motion also stops transitions.
- Plan fix no longer downloads up to 5,000 findings to look up machine ids.
- The web bundle loads Settings, Evidence, sign-in and onboarding on demand (entry chunk 587 kB to 392 kB).
- Settings would crash on an API token without an expiry (none are created that way, but the column allows it).
Full list: CHANGELOG.
Nimstead Assure 0.4.0
Security round 4 and what a first team needs: people management, two-step sign-in, API tokens and CSV export. Agent 0.3.0.
Upgrade from 0.3.x: run deploy/update.sh on the Docker host. Things to know:
- Admins who sign in with a password are signed out by the upgrade and set up two-step sign-in at their next sign-in (any authenticator app), including break-glass sign-in. Save the recovery codes it shows.
- Swagger UI at
/api/docsis off unlessNIMSTEAD_API_DOCS=1(it runs scripts from a CDN);/api/openapi.jsonis still served. - The app now listens on
127.0.0.1:8000only. Your HTTPS proxy on the same host keeps working. If something on another machine reached port 8000 directly, put it behind the proxy, or setNIMSTEAD_BIND=0.0.0.0in.env. - Sign-up links sent before the upgrade stop working; ask for a new one.
- Agents update themselves to 0.3.0. Machines enrolled before 0.3.0 keep taking every channel; rerun the install command to tie one to your server's channel.
Security
- Sign-up can no longer be used to pre-set someone else's password. Emailed sign-ups, invitations and resets let the address owner choose the password on the link's page; the request never carries one.
- Two-step sign-in (TOTP) is required for admins who sign in with a password, with one-time recovery codes; anyone else can turn it on in Settings. A new admin's first session comes from signing in (after sign-up you're sent to the sign-in page), wrong codes are limited per account from every address, and promoting someone signs them out so they set it up.
- Request bodies are capped at 10 MB as they arrive, so a chunked upload can't exhaust memory.
- Per-organisation limits: assets (
NIMSTEAD_MAX_ASSETS_PER_ORG, 5,000), enrolments per token, inventories per hour, and AI calls per user and organisation. - Security headers on every response: Content-Security-Policy, HSTS (with secure cookies),
X-Frame-Options: DENY,nosniff,Referrer-Policy: no-referrer./.well-known/security.txtis served. - The evidence ledger now records organisation creation, every agent enrolment (with the token used), password sign-ins and every change to people and tokens.
- Agent 0.3.0: a fix never installs an older version (pins are compared by the package manager; dry-run downgrades are refused); rollback copies are deleted once the outcome is saved and no change starts below 1 GiB free; signed releases from a less proven channel than the machine's are refused; job fields are validated without trailing newlines; server responses are size-capped.
- Windows installs without remediation failed at "Scheduling failed" (since agent 0.2.0): removing the job-poll task that wasn't there left PowerShell exiting 1 with no output. Found on a real Windows 11 VM; the agent now removes it only if it exists, and says the exit code if scheduling ever fails. Rerun the install command on machines that showed the error.
- The Windows installer's trusted-folder check had lost a backslash, so
C:\Program Files Evil\passed it (the agent's own check still stopped it). Fixed. The Linux installer fetches over HTTPS only and prints the agent's SHA-256. deploy/update.shrefuses untracked files and Compose override files, checks out the exact verified commit, runs as root only from a checkout only root can change, and checks the backup is readable before dropping the database on rollback.- CI actions are pinned to commits with a read-only token; a CI job audits Python and npm dependencies; Dependabot covers both; the release signing step installs only hash-pinned packages.
Added
- People in Settings: invite by email, make admin or member, remove (signed out at once). An organisation always keeps one admin. Sessions end after 12 hours idle; Sign out everywhere.
- Change password and Forgot password? (emailed link, 1 hour; you still need your authenticator code).
- API tokens: read-only access for scripts to findings, assets, the summary and evidence, as
Authorization: Bearer …. Creating one needs your authenticator code; each expires within a year, and stops working when its creator is no longer an admin, signs out everywhere, or changes or resets their password. - Export CSV on Findings, with the page's filters (cells a spreadsheet would run as formulas are escaped).
- Remediation deadlines per priority in Settings, used and shown in evidence packs. Each finding is held to the deadline in force when it was detected, so relaxing one later can't make an old miss pass.
- Evidence packs map to SOC 2 CC7.1 and CC8.1 and NIS2 Art. 21(2)(e) too.
- Risk acceptance: accept one vulnerability on every host it's open on, and revoke an acceptance (both recorded).
- Each release publishes CycloneDX SBOMs of Assure's own dependencies; upload them to an application to scan Assure with Assure.
- Docs: installing an agent without trusting the server, restoring a backup, release-key rotation and the bad-release runbook (
docs/release-keys.md).
Changed
SECURITY.md: response targets per severity, safe harbour, and which releases get fixes.
Full list: CHANGELOG.
Nimstead Assure 0.3.1
Release channels. Releases now come in three channels: preview (earliest, may break), beta (feature-complete, being proven) and stable (public). Your server follows one and also takes anything more stable. There's no beta or stable release yet, so set NIMSTEAD_UPDATE_CHANNEL=preview in .env to keep getting updates; the default is stable. Agents are unchanged (still 0.2.0), so machines need nothing.
Upgrade from 0.3.0: 0.3.0's Settings doesn't show preview releases, so run deploy/update.sh on the Docker host (it checks the signature, backs up the database and rolls back if needed). Then add NIMSTEAD_UPDATE_CHANNEL=preview to .env and restart with docker compose up -d. From 0.2.0: git fetch --tags && git checkout v0.3.1 && docker compose up -d --build, then rerun the install command on each machine once.
Added
- Release channels: preview, beta and stable. Each release's signed manifest says its channel, and a server follows one (
NIMSTEAD_UPDATE_CHANNEL, defaultstable), taking its channel and anything more stable. Settings shows the channel, anddeploy/update.shinstalls the newest release the channel allows. A tag is released as preview; promoting it re-signs the same commit for beta or stable with your approval. 0.3.0 is a preview release. - Docker base images and the PostgreSQL image are pinned by digest, and Dependabot proposes updates to them and to the pinned GitHub Actions.
web/scripts/readme-shots.mjsregenerates the README screenshots from the real-hosts demo.- Each GitHub release's notes are its CHANGELOG section, not a pointer to the file.
Changed
- "Not reporting" alerts wait one report cycle after the server itself was down, so an outage doesn't page about every machine.
Full list: CHANGELOG.
Nimstead Assure 0.3.0 (preview)
Preview release. Early access for trial installs: feature-complete for what it covers and proven on real machines, but not yet a beta or stable release. Expect changes before 1.0.
Agents and the server now keep themselves up to date from signed releases, approved fixes start within minutes, and machines that stop reporting are flagged. Everything was proven on real systems: a Docker Compose host (a forged release refused, a broken one rolled back with its database restored, a good one installed), a Windows 11 VM (the scheduled task updating the agent on its own), Linux machines on real systemd, and the full suite on PostgreSQL 17.
What's new
- The agent updates itself (agent 0.2.0). At each run it installs a newer release only if it's signed by the Nimstead release key built into the agent. That key lives in this repository's protected release workflow, never on your server, so a compromised server can't push code to your machines. Older versions are never installed. The new version has to run on the machine before it replaces the old one, and the old one is kept beside it as
nimstead_agent.py.prev.- Pause updates for your organisation in Settings → Agent updates, or turn them off on one machine by enrolling with
--no-auto-update. - The Assets page says what will happen to each agent: updating, failed and why, paused, off, or reinstall needed.
- Pause updates for your organisation in Settings → Agent updates, or turn them off on one machine by enrolling with
- Approved fixes start within 15 minutes. Machines that allow remediation check for approved jobs every 15 minutes, and send inventory only when a job ran. The agent now writes its own systemd timers and scheduled tasks, so changes like this reach machines without a reinstall.
- Not reporting: a machine silent for 14 hours is flagged on Assets and Home, and your alert targets hear about it once per outage.
- Uninstall:
nimstead_agent.py uninstall --yesremoves the agent, its schedule, key and state from a machine. - Server updates:
- Settings → This server shows the version you're running and the result of the last update.
deploy/update.shinstalls a release only if it's signed and its tag points at the signed commit. It builds while the old version keeps serving, then backs up the database and starts the new version.- If the new version isn't healthy within 5 minutes, it restores the previous version and the database.
--install-timerruns it nightly (opt-in).
/api/healthreports whether the database is reachable and the schema is at this release's migration head. The Docker healthcheck uses it.
What changes for you
- Agents older than 0.2.0 can't update themselves. Rerun the install command from the app on each machine once. The enrolment is kept, and later releases then install themselves.
- Install scripts now let the agent create its schedule. It's the same 6-hourly timer or task, plus the 15-minute job check where remediation is allowed.
- Getting the next release: while releases are previews, 0.3.0's Settings → This server won't show them as available, because 0.3.0 only looks at GitHub's "Latest" release. Run
deploy/update.sh --dry-runon the Docker host to see what's newer, anddeploy/update.shto install it. From the next release on, Settings follows your chosen release channel (preview, beta or stable).
Upgrade
From 0.2.0, on the Docker host, in your checkout:
git fetch --tags && git checkout v0.3.0 && docker compose up -d --buildMigrations run on start. Then rerun the install command on each machine once (see above). Future updates: deploy/update.sh (install guide).
Verify this release
release.json is signed by the Nimstead release key (primary a91fa653…, backup 2438f2cc…, both built into the agent). Check it with the agent from a copy you already trust:
gh release download v0.3.0 --repo Nimstead/assure --pattern 'release.json*'python3 -I agent/nimstead_agent.py verify-release release.json release.json.sigIt prints the manifest: version 0.3.0, agent 0.2.0 with SHA-256 017bf2d4dcd89f75a5271c96fc0588ccbbc16f4ecfebc412f000278c3b29b6ba, and commit 18b87ee664983c935d756fb75c248d403af1624e, which is the tag. The agent file also carries a GitHub build attestation:
gh attestation verify nimstead_agent.py --repo Nimstead/assureFiles
nimstead_agent.py: agent 0.2.0, also served by your server at/agent/nimstead_agent.py.release.json: the signed manifest your server relays to agents anddeploy/update.shchecks (version, agent SHA-256, commit). It was signed before release channels existed, so it counts as a preview release.release.json.sig: its Ed25519 signature.
Known limits
deploy/update.shsupports the documented Docker Compose + PostgreSQL install only.- Install-script side effects are undone on rollback only with zypper + snapper (openSUSE/SLES). Other package managers restore package files and their database.
- The full list of what is and isn't proven is in STATUS.md. The design reasons are in DECISIONS.md (items 31–32).
Full list: CHANGELOG. This release becomes available under Apache 2.0 on 2028-10-28 (FSL-1.1-ALv2).
Nimstead Assure 0.2.0 (early access)
A security release. A Claude Security scan of the whole repository found 21 issues (12 medium, 9 low); all are fixed, each with a test, and everything that touches real systems was rerun against them: a Windows 11 VM attacked by a standard user, real Keycloak/SMTP/webhook services, real external-scan targets, the Docker Compose install, and the full suite on PostgreSQL 17. Upgrade, and read "What changes for you" first.
Security fixes
- Windows agent 0.1.3: a standard user who created
C:\ProgramData\Nimsteadbefore the agent was installed could keep reading the agent key, and a junction planted there could make the elevated agent delete another user's files. The agent now takes the folder first, never follows junctions, and locks it before the key is written. - Tenant isolation: read-only members can't upload SBOMs (which resolved findings); one organisation can't block or discover another's external targets; an unknown ecosystem from any agent can't stop everyone's hourly update; login CSRF and an open redirect in SSO start are closed.
- Hardening: a crafted Composer version can't freeze the API; the OIDC client can't reuse a TLS connection across hostnames; spread-out failed logins can't lock the real user out; webhook URLs are encrypted at rest; agent text can't inject Slack links or mentions; install commands keep the enrolment token off the command line.
- Evidence packs no longer ship their own verifier (get it from your server at
/api/evidence/verify.pyand check its SHA-256 against the one published next to the key fingerprint), and name the tenant's id and DNS-verified domains.
What changes for you
- Sign-up no longer reveals which emails have accounts. The first account on a server is created straight away; later sign-ups finish from an emailed link, so they need SMTP. Colleagues join through SSO.
NIMSTEAD_OPEN_SIGNUP=1restores instant sign-up for development and demos only. - External targets must also serve their verification value at
/.well-known/nimstead-verify.txtfrom the address being scanned (HTTPS or HTTP). Add the file to existing targets, or their scans are refused. - Alert email recipients must confirm before they receive alerts. Remove and re-add existing recipients in Settings to send them a confirmation.
Upgrade
git fetch --tags && git checkout v0.2.0 && docker compose up -d --buildMigrations run on start. Machines on an older agent then show Agent outdated on the Assets page; rerun the install command from the app on each one, Windows machines especially (enrolment is kept).
Files
nimstead_agent.py: agent 0.1.3, also served by your server at/agent/nimstead_agent.py.SHA256SUMS: checksums for the files above.
Full list: CHANGELOG. This release becomes available under Apache 2.0 on 2028-10-28 (FSL-1.1-ALv2).
Nimstead Assure 0.1.1 (early access)
A fix release for the agent. Upgrade if you use automated fixes with health checks.
Fixed
- A crash-looping service could pass the health check. After a fix, the agent asked systemd once whether each health-checked service was active. A service that kept dying and being restarted could be caught in its brief "active" moment, and the broken fix was kept. The agent now also counts systemd's restarts since the change, so it rolls back. We found this on a real Debian 13 host while making the README screenshots; on the rerun the same failure was caught as "service is activating, restarted 11 times since the change" and rolled back.
- Health check failures now say why ("service is inactive") instead of ending in an empty reason.
- Web: the home page and the approval dialog no longer repeat the host name after a fix's summary.
Upgrade
git fetch --tags && git checkout v0.1.1 && docker compose up -d --buildMachines still on agent 0.1.0 then show Agent outdated on the Assets page. Rerun the install command from the app on each one; enrolment is kept.
Files
nimstead_agent.py: agent 0.1.1, also served by your server at/agent/nimstead_agent.py.SHA256SUMS: checksums for the files above.
Full list: CHANGELOG. This release becomes available under Apache 2.0 on 2028-10-27 (FSL-1.1-ALv2).
Nimstead Assure 0.1.0 (early access)
The first early-access release of Nimstead Assure: self-hosted vulnerability management that finds what's vulnerable, fixes it safely, and proves it to an auditor.
git clone --branch v0.1.0 https://github.com/Nimstead/assure.git && cd assure && cp .env.example .envSet POSTGRES_PASSWORD in .env to a long random value, then run docker compose up -d and open http://localhost:8000. The install guide covers HTTPS, enrolling machines and turning on automated fixes.
What's in it
- Detection on Debian, Ubuntu, RHEL family, Alpine, SUSE and Windows (OS updates from MSRC, plus about 18 common apps), and in your applications from CycloneDX or SPDX SBOMs. Matched with each ecosystem's own version rules, so backported fixes aren't flagged.
- Prioritisation by what attackers actually exploit (CISA KEV, EPSS), then CVSS, criticality and exposure, with the reason written next to every score. You see upgrades, not CVE lists.
- Remediation with apt, dnf, apk, zypper and Windows cumulative updates: dry run, rollback copy first, canaries first, health checks, automatic rollback, and success only when the next inventory confirms it.
- Evidence: a hash-chained ledger with signed checkpoints, and Ed25519-signed packs mapped to Cyber Essentials, ISO 27001, NIST, PCI DSS and CIS that your auditor verifies offline.
- External scanning of internet hosts you prove you own, OIDC single sign-on, webhook and email alerts, Vault and S3 object-lock key storage.
Proven, not just tested
579 API tests on SQLite and PostgreSQL 17, plus end-to-end runs on real machines: fixes and rollbacks on Debian 13, Ubuntu 24.04, AlmaLinux 9, Alpine 3.21, openSUSE Leap 16.0 and Windows Server 2025; real Keycloak, DNS, SMTP, webhooks, Vault and S3; and this Docker Compose install with a real agent. Details and logs: STATUS.md.
Before you rely on it
This is early access. Expect rough edges and breaking changes before 1.0. Start on test machines: automated fixes only touch machines enrolled as sandbox until you turn on production remediation. Known limitations.
Files
nimstead_agent.py: the agent, also served by your server at/agent/nimstead_agent.py. One standard-library Python file (3.9+), version 0.1.0.SHA256SUMS: checksums for the files above.
Feedback
Open an issue or email dev@nimstead.systems. Security issues: security@nimstead.systems, never a public issue.
Licensed under FSL-1.1-ALv2: use and self-host it for anything except a competing product. This release becomes Apache 2.0 on 2028-10-27.