Skip to content

AbstractCore v2.25.1

Choose a tag to compare

@github-actions github-actions released this 08 Oct 01:13
· 259 commits to main since this release

Security

  • macOS command sandbox, "Deny everything, allow listed workspaces": the shared temp folders are
    denied too.
    The profile denied only user data (/Users, /Volumes, /private/var/root,
    $HOME), so an unlisted file under /private/tmp or /private/var/folders stayed readable. Both
    are now denied (read and write); system folders (/usr, /System, /Library, /opt,
    /usr/local, /Applications) stay readable and unwritable; xcrun's cache files and the run's
    private TMPDIR keep working. Test: tests/tools/test_sandbox_macos.py.
  • browser_probe serves local pages from a scoped loopback origin, never file://. A page in
    an allowed workspace could embed file:// subresources (img, iframe, stylesheet) from a refused
    folder, and Chromium loaded them. Local targets are now served from a private
    http://<random name>.localhost:<port> origin that answers only for files the run's _sandbox
    stamp can read (new sandbox.path_readable, the most-specific-row rule; symlinks resolved);
    file:// URLs and out-of-scope files are refused and listed in the report ("Local files
    BLOCKED"). A page outside the scope is refused before the browser starts; on a host that called
    configure_host a local page without a stamp is refused; library use without a host policy serves
    what the process can read. browser_probe accepts the hidden _sandbox argument (not in the
    model-facing schema). Side effect: ES-module and fetch() pages render as they do over http (the
    file:// CORS blank no longer happens). Tests: tests/tools/test_browser_probe.py.

Fixed

  • Linux command sandbox: an allowed folder inside a refused one is reachable under bubblewrap.
    The bwrap profile masked a refused folder with a tmpfs and remounted it read-only at once, so
    bwrap could not create the mount point of a more specific allowed folder inside it ("bwrap: Can't
    mkdir …/parent/child: Read-only file system") and every command failed. The masks are now made
    read-only after every row is bound, so the most specific row wins on Linux as on macOS (a refused
    folder inside the allowed child still refuses its subtree). Landlock already granted the child of
    a refused parent; a test now proves it. Tests: tests/tools/test_sandbox_spec.py
    (argv order) and tests/tools/test_sandbox_linux.py (real bwrap and Landlock runs, CI job
    linux-sandbox).
  • Every provider a capability route can name has a local-weights answer. The gateway console's
    Voice Input row (faster-whisper / large-v3) read "not checked: AbstractCore has no local-weights
    probe for provider 'faster-whisper'" on a machine that had Systran/faster-whisper-large-v3
    cached, and output sound and music (stable-audio-3) said the same. model_materializer.probe now
    maps each engine's own model id to its storage with that engine's table: faster-whisper
    (AbstractVoice's aliases, then faster-whisper's _MODELS, read from its source so CTranslate2
    and torch are never imported), transformers-asr, audiodit, omnivoice, qwen3-tts, piper, f5_tts,
    chroma, stable-audio-3, stable-audio, acestep, sdcpp and mlx-gen / mflux presets, triposr,
    trellis2, step1x and hunyuan3d. Hugging Face storage is judged by the same reader as every other
    HF route; acemusic and elevenlabs-music are remote. A voice route's provider is resolved the way the
    route runs it before the probe (local / hf on input.voice, AbstractVoice's remote / compatible /
    proxy aliases are remote). The engines that resolve to a Hugging Face
    repo download it (abstractcore models download faster-whisper large-v3). supported_providers()
    lists them. Only an id no route offers still answers unknown (no materializer), now naming
    the provider and what to do. Tests: tests/config/test_engine_weight_probes.py (cache layouts
    per provider, no network or subprocess allowed, every route provider covered).
  • ModelPresence.summary: one short sentence per answer ("In the Hugging Face cache.", "Not in
    Piper's voice folder.") that grids print under the state; the long detail stays for tooltips.
    Always present in to_dict().
  • Web console Email: no "Advanced" disclosure. Your own sign-in client is the visible section
    Sign-in app and the recipient rules, send limits and watched folder are Recipients and
    limits
    (the operator's rule: no "Advanced" anywhere; the names the consoles share). The sign-in
    refusal says "add your own client id under Sign-in app". Tests: tests/test_console_email_tab.py.