Watch
1
0
Fork
You've already forked RedFlag
0
Commit graph RedFlag/helper
Author SHA1 Message Date
Fimeg
ff2f30f47a v0.2.9.3: device classification + ARM support — Pixel 3 lands
DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id
combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak
hostname fallback. Hardware-bound IDs on DMI-less devices.

DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from
/sys signals — system battery (scope=Device peripherals excluded, UPS
excluded), DRM connector state, framebuffer min-dimension for phone/tablet
split. Reports device_type/device_model/os_distro in registration and
system-info paths.

SERVER-001: migration 061 — device_type, device_type_manual (operator
override, never agent-written), device_model, os_distro on agents.
effective_device_type computed into every serialized agent.

SERVER-002: PUT /admin/agents/:id/device-type — set/clear override,
enum-validated, journaled.

WEB-001: device-type icons + fleet filter, device model in list, detail
header badge with reclassify dropdown, os_distro surfaced.

INSTALL-003: arm64 install path unblocked — helper (required manifest
component) now cross-built aarch64-unknown-linux-musl via rust-lld in the
server image, signed at boot (helperArches += arm64), listed in the release
manifest. Install template already handled uname -m and pacman.

Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow
updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
2026-07-06 18:21:23 -04:00
Fimeg
bf7930f1fe v0.2.9.1: wire pacman scanner, GATE-006 TODO 2026-06-29 15:11:12 -04:00
Fimeg
35732a63fd fix(GATE-005): harden helper trusted-input — argv separator + UUID v4 request_id
- apt build_plan: add POSIX '--' before user-derived name=version tokens
- dnf build_plan: add POSIX '--' before user-derived name-version token
- validate_mint_request: enforce canonical UUID v4 on request_id at intake
- RAF components/04: document '--' separator in pipeline step 7
- RAF security/05: document hardened argv contract + UUID v4 validation
- RAF flows/03: add stale banner (5 deviations from current code)

14 tests pass. Deferred: artifact_path staging root, name/version charset
regex (both need design decisions — see task file).
2026-06-17 22:07:36 -04:00
Fimeg
99d97a07ee v0.2.9.0 — Windows desktop tray ships; unified Agents & Enrollment page
Desktop:
- Windows tray cross-compiled (cargo-xwin), installed with per-user
  autostart Run key; tray actions trigger_scan/approve_update wired to
  the local API
- Linux tray off the service child-spawn path — XDG autostart only, kills
  the double-launch
- signalDesktopRestart no longer no-ops on Windows (taskkill /F /IM)
- server serves /desktop/:platform/:arch

Web:
- TokenManagement + AgentManagement folded into one Agents & Enrollment
  settings page (useRegistrationTokens hook)

Agent/server:
- platform-aware self-update staging (constants/paths.go), no more
  hardcoded /var/lib/redflag
- consumer helper gated: sudo systemd-run on Linux, child proc elsewhere
- migration 060 drops the never-used token_seats table
- droppage of dead constructors and orphaned windows.go service methods
2026-06-15 20:51:44 -04:00
Fimeg
7d47b0769d gate: route desktop updates through the helper
Desktop self-updates ran in the agent process with their own replay
file. They now go through the privileged helper like agent and helper
self-updates, so the agent performs no binary mutation and keeps no
replay state of its own. The desktop app is a status surface only.
2026-06-14 14:24:29 -04:00
Fimeg
c35ad89b92 gate(executor): constant-time hash compare in the privileged helper
Compare artifact and closure hashes in constant time via subtle::ConstantTimeEq at the three verify sites, closing a timing oracle on the privileged executor. subtle is added as an explicit dep (was only transitive).
2026-06-14 12:57:04 -04:00
Fimeg
e2dab2845a supply-chain: gate our own deps, ship the verdict signed
dep-scan.sh gates go/npm/cargo on push and bakes an attested posture into the
release — embedded in the server, signed into the manifest. Reasoning and the
two Moby exceptions are in SECURITY.md.

(posture-builder runs rustup; bookworm's cargo is too old for cargo-audit.)
2026-06-14 11:43:23 -04:00
Fimeg
e4afe1f605 feat: helper trust-file self-validation (SEC-021)
The privileged executor no longer trusts its keyring, agent_id, or
replay-guard state by content alone. Before any read, each trust input
and its immediate parent must be root-owned, not group/other-writable,
and not a symlink — otherwise deny with EXIT_TRUST_PATH (26), fail
closed. This makes the gate self-defending: a packaging or installer
mistake that leaves a trust path writable can no longer be parlayed
into key injection, token rebinding, or replay-record clearing.

An agent_id file that exists but fails validation is a denial, never a
fall-through to the next location. The replay dir is validated after
ensure-exists so a pre-planted attacker-owned dir is refused, not
adopted.
2026-06-11 07:55:34 -04:00
Fimeg
aff48376b9 v0.2.8.0 — changelog + version lockstep bump 2026-06-11 02:01:43 -04:00
Fimeg
8b1884eadc fix: nil logger on Windows scan path, rpmEVRAhead equal-version false positive, desktop-self replay token burned before install
- NewOrchestrator initialises a log-only TeeLogger (nil buffer) so the
  Windows service path never carries a nil logger into executeScan
- rpmEVRAhead returns false when all epoch/version/release components
  compare equal; adds test cases for "0:2.0-1" vs "2.0-1" normalisation
- processDesktopSelfToken splits replayCheckAndRecordAgent into
  replayCheckAgent (before install) + recordAgentTokenConsumed (after
  successful install) so a transient install failure does not permanently
  consume the token
- Comments on helperSelfStagingPath (Go) and DEFAULT_HELPER_SELF_SOURCE
  (Rust) name each other as the cross-language counterpart
2026-06-11 02:01:43 -04:00
Fimeg
821bc00099 feat: self-update capability tokens (agent, helper, desktop)
Add AllowedSelfUpdatePackageTypes and allowedCapabilityPackageType() so the
consumer accepts redflag_agent_self / redflag_helper_self / redflag_desktop_self
tokens without putting them in the package-manager allowlist. ProcessToken
dispatches self-update types to dedicated processAgentSelfToken,
processHelperSelfToken, processDesktopSelfToken handlers. ArtifactDownloader
interface extracted; inferred from reporter when available. Tests added for
allowlist invariants, stageClosureArtifact (local file path), and
installDesktopBinary (backup-and-replace).
2026-06-11 02:01:43 -04:00
Fimeg
469d61c0dc ui: command primitives extracted; agent page split-button sizing restored
CommandCard and CommandStatusBadge pulled out of Agents.tsx; restart
host split button back to flush edges with stretched trigger.
2026-06-11 02:01:43 -04:00
Fimeg
4896fb6856 ci: Gitea Actions pipeline — release gate, embedded UI build, guided release script
ci.yml: vet, race tests, clippy, full web build, AI-attribution and
action-pin enforcement. release.yml: gate job verifies tag against
versions.go/docker-compose/Cargo/CHANGELOG, forward-only and on public,
before anything builds; web UI staged into the embed path (gitignored
dist made a bare go build ship an empty dashboard); binaries and docker
image must self-report the tag; release created via Gitea's own API.
scripts/release.sh is the operator path: checks runner, secret, branch,
versions, changelog — asks before every mutation, watches the run after.
bump-version.sh gains current-version display, dirty-tree warning,
duplicate check, changelog check, confirmation. build-secure-agent.sh
retired (bare go build, no version injection, single Makefile caller).
2026-06-11 02:01:42 -04:00
Fimeg
2084019be7 fix: grant CAP_SYS_PTRACE on agent binary for display/process discovery
The agent runs as redflag-agent user and cannot read /proc/[pid]/environ
from the logged-in user's session processes (owner-only permissions).
Without this, discoverSessionDisplay() finds nothing — screenshot fails
on Wayland because XDG_RUNTIME_DIR/WAYLAND_DISPLAY are never discovered.

- Installer: setcap cap_sys_ptrace=eip after placing the binary
- Helper (agent self-update): restore setcap after atomic replace,
  since rename() creates a new inode and strips file capabilities

Non-fatal if setcap is unavailable — agent degrades gracefully,
just loses screenshot and per-process telemetry.
2026-06-11 02:01:42 -04:00
Fimeg
e8b7742422 feat: standalone local authority — helper mint mode + local approval flow
FEAT-003 core (design: RAF/security/06-standalone-authority.md, approved
2026-06-10). On a host with no fleet server, the trust boundary preserved is
root-vs-unprivileged: a root-owned 0600 Ed25519 key signs capability tokens
via a new privileged helper invocation; redflag-local membership lets you
request a mint, never perform one.

Helper gains the mint subcommand: validates forward-only ops, mintable-type
allowlist (no agent-self), host agent-id bind, closure shape (64-hex sha256
fail-closed), hard-coded 15-minute gate-evidence freshness with future-dating
rejection, override-reason requirement for vulnerable/unreachable/overridden
verdicts, duplicate request_id dedupe, journal-before-emission. --init-key /
--retire-key manage the authority lifecycle (retire = the fleet-join swap).
Deny taxonomy 22-25. Round-trip test proves a minted token passes the execute
path's own verification and parses as the wire CapabilityToken.

Agent gains POST /v1/actions/approve-update (single-flight, 409/503 mapping):
fleet-mode refusal, dnf/apt dry-run closure resolve + hash pin (no pin, no
mint), best-effort OSV.dev closure check with honest verdicts (unreachable is
never silent-clear), mint via sudo systemd-run mirroring the execute grant,
then the unchanged verify+execute path. Provisioning script sets up the
journal dir (root:redflag-local 2750 setgid), mint request dir, key init, and
the pinned mint sudoers line.
2026-06-10 09:04:06 -04:00
Fimeg
62f2764260 v0.2.5.1: lifecycle, live operations, unified history
Lifecycle:
- ReopenUpdate + ResolveUpdate replace RetryUpdate; routes for
  GET /updates/:id/lifecycle and POST reopen/resolve
- confirmUpdateCommand marks update_agent completed on version attestation
- migration 048: started/running added to update_logs.result
- helper atomic_replace_binary: copy-to-sibling then rename() (ETXTBSY)

Live operations:
- event_stream service + /events endpoints, LiveOperations page
- capability-token queries for the live view

History + CVE:
- History page reads /events/recent: filterable lifecycle/command/
  system/orchestrator timeline with agent crosslinks
- CVE drill-down: OSV parse carries CVSS vector, fixed version, published
  date, severity; issuer-linked aliases (CVE->NVD, GHSA->GitHub, ALSA->errata)
- DependencyClosureTree: one shared closure component in update detail
- STARTED (blue spinner) and PARTIAL (amber) result badges
2026-06-05 09:13:42 -04:00
Fimeg
0dcfe25705 unified agent+helper upgrade: closure carries both binaries
Server: mintAgentSelfToken includes helper in closure, sends
helper_download_url + helper_checksum in command params.

Agent: downloads and stages both binaries, passes --helper-file to helper.

Helper: parses --helper-file, separates closure into agent+helper entries,
self-updates helper binary first, then installs agent. Falls back to
agent-only if closure has 1 entry (backward compatible).
2026-06-05 09:13:42 -04:00
Fimeg
b30261791d fix: result file 0644 so agent can read back from root-owned helper
The helper runs as root via systemd-run. With 0640 root:root, the
unprivileged agent user cannot read the result. The result directory
is 0700 agent-owned which already blocks other local users.
2026-06-05 09:13:42 -04:00
Fimeg
482e5a9aad security: path traversal, file perms, sudoers/polkit scope, staging cleanup
- consumer.go: safeTokenFilename() blocks path traversal via token ID
- consumer.go: TOCTOU sanity check on result token_id
- main.rs: result file written 0640 (was 0644)
- linux.sh.tmpl: sudoers wildcards restricted to tokens/* and results/*
- linux.sh.tmpl: polkit scoped to manage-transient-units
- agent_update.go: clean up pending-upgrade.bin on failure
- updates.go: clear is_updating flag on failed update_agent
- bump 0.2.3.7
2026-06-05 09:13:42 -04:00
Fimeg
5758b26875 swap uuid lib, windows installer pass, README/RAF copy
- google/uuid -> gofrs/uuid/v5 across server + agent
- windows.go: cross-platform binding cleanup
- linux install template: disable sudo lecture for TTY-less service user
- README: XZ/SolarWinds lede, stable-release note, single attack-surface block
2026-06-03 15:39:49 -04:00
Fimeg
0d908ba512 feat: zero-sudo agent, helper self-upgrade, OSV expansion, docker handler rewrite, staging UI
Agent privilege reduction:
- apt discovery unprivileged (sandbox opts like dnf)
- docker commands use group membership, no sudo
- agent self-upgrade delegated to helper via agent-self capability token
- sudoers template stripped to single systemd-run helper line

Helper (Rust):
- agent-self package type: stage, hash-verify, backup, install, chmod, restart
- TOCTOU-safe: copy-then-hash, never hash a path re-read later
- --no-block restart so helper finishes before agent SIGTERM

Server:
- mintAgentSelfToken signs agent-self tokens for manual and bulk update paths
- OSV.dev checks at discovery time (async, deduped) + startup backfill
- apt/dnf added to OSV ecosystem mapping
- docker handler rewritten against DockerQueries (proper image/container split)
- status filter server-side on aggregated packages (HAVING clause)
- dead code removed: UpdatePackage model, UpsertUpdate, ListUpdates

Frontend:
- LiveOperations -> Staging with staged-packages section
- Docker severity from data, not hardcoded
- Updates status filter delegated to server
2026-05-30 12:56:40 -04:00
Fimeg
1c18a6b55a feat: signed release manifest + fail-closed binary distribution
No unsigned binary path: build refuses when signing is disabled, downloads
return 404 when no signed package resolves. Signed release manifest endpoint,
installer verifies manifest signature and pins binary hash, Windows token
mandatory, Rust helper verify-binary.
2026-05-29 10:47:41 -04:00
Fimeg
08b698303f chore: ignore helper/ Rust build output 2026-05-28 14:53:36 -04:00
Fimeg
ea068c2213 feat: supply-chain capability-token gate (executor, signing, mint/deliver, agent consumer)
Server mints Ed25519-signed capability tokens authorizing one package
operation over a resolved closure; a privileged network-less Rust executor
verifies signature + artifact hashes and performs the op. Replaces the
rs-helper socket-decision daemon's role with signed tokens (trust root off-host).

- helper/: Rust executor keystone (stdin token -> window/bind/keyring/verify_strict
  -> artifact hash -> replay guard -> one op, no shell, env_clear, fail-closed)
- capability/ (mirrored in server + agent): token type, canonical encoder,
  sign/verify; cross-language byte-identity proven by contract tests
- server: SignCapabilityToken, CapabilityMinter (mint at approval after Layer-1
  hash), capability_tokens queries, migration 042, delivery + receipt endpoints
- agent: supplychain consumer (bind-check + allowlist + invoke executor + receipt),
  client methods, polled each check-in via loop.processCapabilityTokens
2026-05-28 14:53:05 -04:00