Repository navigation
Releases
Releases · InfraWard/infraward
v0.6.0
Added
- Accept the risk of a finding: from the CVE page, the vulnerability list (in bulk) or by CVE across a project, with a mandatory reason and an optional expiry date (up to one year). Accepted findings stop counting as open but still show as affected in the CVE search; when the expiry date passes they reopen automatically with a notification, and a scan that no longer sees them marks them fixed. Accepting and reopening are audited and need the new
findings.acceptpermission (admin and editor). - Outbound alerts: the notifications of the in-app bell can also go out by webhook (JSON POST, optionally signed with HMAC-SHA256) or email (the worker's SMTP), configured by admins in Settings › Alertas with a per-channel filter and a test button. The webhook URL and signing secret are kept in the secrets manager, and the worker protects against SSRF (HTTPS only by default, no loopback, link-local or private targets unless allowed, no redirects, connects to the validated address). Deliveries run on their own
alertsqueue (ALERTS_CONCURRENCY) with retries, and a notification is only marked as sent once its deliveries are queued. - Log of every collection, discovery and scan, viewable from the asset page ("Recolecciones" tab): the steps, every command the worker ran (ssh, ansible-playbook, trivy…) with its duration and exit code, the Ansible tasks, the end of the stderr of whatever failed and the result. Secrets, keys and tokens are redacted before saving, each run's log is capped (
COLLECTION_LOG_MAX_KB, 256 KiB) and logs are deleted afterCOLLECTION_LOG_RETENTION_DAYS(30 days). Failed runs are highlighted and a running job refreshes until it finishes. New endpointsGET /assets/{id}/runsandGET /assets/{id}/runs/{runId}/log; reading a log requires theassets.operatepermission (admin, editor, operator), since it carries error output from the servers. - Redesigned Activity page. Each run now says where it came from: a bulk operation, another task (a collection that triggered a discovery, a reconciliation that queued collections…), the periodic inventory check, a manual request or an enrollment, with a link to the task or bulk operation that launched it, and the list can be filtered by origin. Clicking a run opens its own page (
/activity/{id}) with its timing, the tasks it launched and its log, also for runs without an asset. The asset's "Recolecciones" tab, the "Actividad reciente" widget and the bulk-operation result link to it. New endpointsGET /jobs/runs/{id}andGET /jobs/runs/{id}/log(the log requiresassets.operate) and theoriginfilter onGET /jobs. Runs recorded before this version show no origin. - Podman support (part of #10): hosts with Podman get the new
podman-hostrole and their containers, images, volumes and networks are inventoried with the nativepodmanCLI, withoutpodman-dockeror a root socket. Pods (the pod's infra container is skipped) and quadlet/systemd containers (PODMAN_SYSTEMD_UNIT) are shown on the container. Rootless Podman users are detected automatically with read-only signals (running containers, an active user socket, or container storage in their home) and listed in the new «Usuarios de Podman» card of the server; their containers are inventoried, through each user's own Podman socket and marked with their user, once the user is enabled. «Habilitar» shows a command to copy and run with sudo (it turns on linger and the user'spodman.socketand adds the user to/etc/infraward/podman-users, which remains the server-side consent) or, if the server has the admin access and you can open a terminal, runs it asinfraward-adminin a new read-only terminal where you see the command and its output without being able to type. The enrollment option--podman-users=<user,…>is kept as an optional override. Detected users that are not enabled, and enabled users without an active socket, raise a warning on the server. Images are scanned withpodman save --format docker-archive, the web terminal opens in rootful Podman containers, and Docker and Podman can coexist on the same host. A read-only terminal action never runs when the page loads: it waits for you to press «Ejecutar». Queries to a rootless user's socket run as that user (runuser), never as root, and an image taken from a rootless user's store is only scanned if its config and every layer match the image ID. Requires sudoers v8: re-run the enrollment script on Podman hosts.
Removed
- The Contributor License Agreement (
CLA.md,CLA.es.md) and the CLA Assistant check on pull requests. Contributions are now accepted under the project's license (AGPL-3.0) without signing anything.
Fixed
- A failed run's error was shown twice at the end of its log ("Fallo: …" and "Fallido: …").
- The web terminal never opened in production builds ("No se pudo cargar la terminal"): xterm.js is a CommonJS package and the production bundle only exposes it as a default export, so the terminal class was not found. "Reconectar" now also retries loading the terminal, and leaving the page to confirm your identity no longer triggers the browser's "leave site?" prompt while no session is open.
- Confirming your identity with an OIDC provider (step-up before opening a terminal and other sensitive actions) failed with authentik from the second time in the same provider session: authentik ignores
max_age=0and does not ask for credentials again on laterprompt=loginrequests, so the returnedauth_timewas stale. The request now usesmax_age=30, which authentik enforces. - A fully patched RHEL-family server (e.g. Rocky Linux 10) showed hundreds of open HIGH vulnerabilities with a patch available: dnf keeps the previous kernels installed (
installonly_limit) and Trivy reports, for each package of each older kernel, every CVE fixed since then. Findings on kernels that are not running (and on kernel headers and tools) no longer count in the asset, inventory tree, project and dashboard summaries; the asset overview shows them apart, and the asset's Vulnerabilities tab now hides them by default like the main list, saying how many were left out, with an "Incluir lo oculto" toggle.
Full changelog: v0.5.2...v0.6.0
v0.5.2
Added
CHANGELOG.mdwith the changes of every version since 0.1.0. GitHub releases now take their notes from it.
Fixed
- Collecting from a host failed with "Failed to create temporary directory" when the worker runs with a read-only root filesystem (as in the example compose file): Ansible's local temporary directory now lives in the job's tmpfs. The error shown for a failed collection is no longer cut off mid-word and recognises this case.
Full changelog: v0.5.1...v0.5.2
v0.5.1
Fixed
- Publishing the web, API and worker images to
ghcr.io/infraward: the registry login in the release pipeline failed (CI components updated to v1.1.1).
Full changelog: v0.5.0...v0.5.1
v0.5.0
First public release of the source code on GitHub.
Added
REDIS_PASSWORD_FILEfor the API, worker and gateway, as an alternative toREDIS_PASSWORD. The example compose file now passes the Redis password as a secret (created byinit.sh), so it no longer appears in any container's environment.OIDC_ALLOW_UNVERIFIED_SIGNUPfor providers that verify email addresses but do not send theemail_verifiedclaim (such as Entra ID). It only allows sign-up, never linking to an existing local account.- OCI labels (title, description, license, source and creation date) on the web, API and worker images.
SECURITY.mdwith the vulnerability reporting policy, anddocs/SECURITY-NOTES.mdwith the authorization model and a deployment checklist.CONTRIBUTING.mdand an individual Contributor License Agreement (based on the Apache ICLA v2.2).
Changed
- The project name is written as InfraWard in every text: web, API, worker, enrollment script and documentation. This includes the TOTP issuer; authenticators that are already set up keep their label. Lowercase identifiers (
infraward, paths and keys) are unchanged. - The API docs (
/docsand/openapi.json) are off by default in production; setDOCS_PUBLIC=trueto enable them. PUBLIC_URLmust use HTTPS in production, except for loopback addresses.
Fixed
- The web terminal no longer loses the output of commands that finish immediately.
Security
- Patched vulnerable dependencies (including fastify, zod, fast-uri, body-parser, multer, undici and vite) and hardened the pnpm supply chain (minimum release age, no trust downgrades, no exotic sub-dependencies).
- Login is also rate-limited per account, not only per IP (
LOGIN_ACCOUNT_THROTTLE_*, with counters in Redis viaTHROTTLE_STORAGE). Only failures count, a successful login resets the counter, and networks the account has recently signed in from are not blocked, so a single IP cannot lock out another account. - Resetting or changing a password now also revokes the user's API tokens.
- Automatic OIDC sign-up requires a verified email address, so nobody can create an account with someone else's email.
- The enrollment script refuses a symlinked (or foreign-owned)
~/.sshorauthorized_keysin the inventory user's home and writes them as that user, so it can no longer be tricked into overwriting root's keys. - The OpenBao client never follows HTTP redirects, so AppRole credentials and tokens cannot be forwarded to another host.
- Scan exclusion patterns are matched without regular expressions, which removes a ReDoS on patterns with many
*. - The web terminal does not accept input until the API has recorded the session opening.
- The enrollment token is no longer written to the nginx access log.
- nginx sends X-Frame-Options, CSP
frame-ancestors, HSTS,nosniffand Referrer-Policy on every location, and the production build no longer needsscript-src 'unsafe-inline'. - Container images: updated base images (nginx 1.31 on Alpine 3.24), npm and corepack removed from the API image, Trivy 0.76.1, and every image is scanned for fixable critical vulnerabilities before it is pushed. The worker runs on Ubuntu 26.04 for the OpenSSH client fix (CVE-2026-60002).
- Example compose file: Redis password, an internal network for PostgreSQL, Redis and OpenBao,
cap_drop: ALL,no-new-privileges, read-only root filesystems and non-root users.