Skip to content

Releases: nlink-jp/image-forge

v0.29.2

Choose a tag to compare

@magifd2 magifd2 released this 22 Sep 06:11

Changed

  • nlink-jp/pathguard v0.3.0 (no behaviour change here).

v0.29.1

Choose a tag to compare

@magifd2 magifd2 released this 22 Sep 05:07

Security

  • Whether an input image exists no longer changes the answer. An init,
    mask, control or upscale input that is a .env, lies in this server's
    own directories (a workspace can contain them: work_dir=~/.local with
    workspace_id=share), or is where a link directly inside a credential directory
    points was refused when the file was there and answered input_not_found
    when it was not, so the answer told the caller which of them exist. It is
    now judged before anything looks for it (ADR-0010, amendment). Raw LoRA,
    ControlNet and hires model paths were already judged first; tests now pin
    that, through the renderer's answer too.

v0.29.0

Choose a tag to compare

@magifd2 magifd2 released this 22 Sep 01:49

Changed

  • Path judgement moved to nlink-jp/pathguard
    (ADR-0010). internal/mcp/workdir is now an adapter onto it; the MCP server
    wires its guards in one place, mcpGuards. Places
    are compared by file identity and by names folded the way the disk folds
    them, instead of by name.
  • A work_dir is now refused in this server's config directory
    (~/.config/image-forge, or the $XDG_CONFIG_HOME form — a config file set
    elsewhere with IMAGE_FORGE_CONFIG protects the file, not the directory it
    sits in), in the models directory when models_dir moves it
    outside the data directory, in the real places under your home from
    the list gem-agent and lagent use (newly ~/.kube, ~/.config/gh, ~/.azure,
    ~/.terraform.d, ~/.gemini, ~/.config/mcp-bridge, ~/.netrc, ~/.npmrc,
    ~/.pypirc, ~/.git-credentials, ~/.vault-token, ~/.docker/config.json,
    ~/.claude.json, ~/.bash_history, ~/.zsh_history), under every spelling of
    any refused place, wherever a link directly inside one of those directories
    points (a ~/.ssh/config that links into a sync folder protects the file it
    points at), in the account's own home too when $HOME names another, and
    whenever the home directory cannot be determined. work_dir_denied carries
    reason in its details.
  • A relative XDG_DATA_HOME is ignored, as the XDG spec says; it put the data
    directory under the working directory. Other relative server directories — a
    relative IMAGE_FORGE_HOME, IMAGE_FORGE_MODELS_DIR or models_dir, or an
    unset HOME — now make every MCP call fail with work_dir_denied naming the
    path, rather than protecting nothing; give them absolute paths. A relative
    XDG_CONFIG_HOME is ignored like XDG_DATA_HOME, and a relative
    IMAGE_FORGE_CONFIG is judged from the working directory, as it is read.

Security

  • Raw LoRA, ControlNet and hires model paths from MCP are judged. They are
    read wherever they lie and were not checked at all, so a credential file
    could be loaded as a LoRA. One in a credential or agent-control location, in
    this server's config file or directory or the legacy config file in the data
    directory (which may hold hf_token), a .env file, or
    a path holding a NUL byte (C stops at it) is now refused with
    path_not_allowed before the render — and before anything stats it, so a
    refusal does not say whether the file exists. An installed name is resolved by
    the registry, as before, and is not judged as a path. The CLI and the GUI's
    serve loop are unchanged. A workspace input (init, mask, control,
    input) that resolves into one of this server's own directories is refused
    too: a workspace may contain one (work_dir=~/.local, workspace_id=share).
  • The workspace directory is judged, not only work_dir. work_dir=~/.config
    with workspace_id=gh made the workspace ~/.config/gh, a credential
    directory; PNGs were written into it and workspace-relative inputs read from
    it. <work_dir>/<workspace_id> is now refused with work_dir_denied wherever
    work_dir itself would be. The hole was present since the work-directory
    contract (ADR-0009).

Tests

  • TestWorkDirComesFromRequestMeta waits for its job; returning first raced the
    removal of the temporary directory the job writes into.

v0.28.0

Choose a tag to compare

@magifd2 magifd2 released this 21 Sep 21:42

A LoRA or ControlNet made for another architecture is refused before loading (only trusted arches compared); --arch is validated; models list reports arch_trusted; hires default wording corrected; ADRs made consistent. See CHANGELOG.md.

v0.27.0

Choose a tag to compare

@magifd2 magifd2 released this 21 Sep 05:04

Fixed

  • anima-turbo reported the wrong licence, and said commercial use was permitted. The entry carried NVIDIA's Open Model License — the terms of the Cosmos base model Anima was trained from — while the weights it downloads are published by CircleStone Labs under their Non-Commercial License v1.2: non-commercial and non-production use only, with revenue-generating use requiring a licence from them (generated outputs may still be used commercially, §2.e). It is now reported as that, flagged non-commercial, and carries the attribution notice the licence requires. A test pinned the old flags, so the mistake had a guard holding it in place.

    If you pulled anima-turbo and relied on what models list said about it, this is the entry to re-read.

  • A licence correction now reaches an already-installed model. models list took the licence recorded in the registry at install time and consulted the catalog only when it was empty, so a model pulled before a correction kept reporting the old terms beside corrected flags.

  • controlnet-canny-sd15 is reported as OpenRAIL, which is what lllyasviel/ControlNet-v1-1 declares, rather than CreativeML OpenRAIL-M (a different licence).

  • illustrious-xl-v1 now states that the Hugging Face card for those weights declares other / sdxl-license while the Civitai listing states no derivatives and credit required. Both exist; the stricter is reported.

  • make verify-release fails closed. Its last block ended a chain of unzip / --version / spctl in || true, so a zip that did not unpack exited 0 and the upload proceeded.

Added

  • license_source on every catalog entry, surfaced in models list --json. It names the card or listing the licence was read from — which for most entries is not the repository the bytes come from, since they download from a quantization or mirror repo. Verified against the publishers on 2026-09-21 and pinned per entry by a test that also compares the entry count, so a model cannot be added without stating where its terms came from.

Apple Silicon only (CGO + Metal). Full notes: CHANGELOG.md

v0.26.5

Choose a tag to compare

@magifd2 magifd2 released this 21 Sep 01:33

Security

  • A symlink planted at <work_dir>/<workspace_id> no longer redirects the
    whole workspace.
    os.Root confines operations inside a root but resolves
    the root path itself normally, so if anything else with write access to your
    work directory (another tool, sandboxed code) left a link at the workspace's
    name, every read and write anchored on the link's target: images were written
    outside the directory you named and the call reported success. The workspace
    directory is now created through an os.Root on work_dir and then verified
    by real path; a workspace whose name resolves elsewhere is refused with
    path_not_allowed, naming the id and what it resolved to.
  • A symlink planted at the engine's temp output path is no longer written
    through.
    generate and upscale hand the diffusion engine an absolute
    path (output/<name>.tmp.png), which the engine opens with plain
    os.Create — following any link left there and writing the render outside
    the workspace. The tool then failed while reading the result back, so the
    out-of-workspace write had already happened silently. That name is now
    unlinked through the containment root before the path is handed out, so the
    engine always creates the file fresh.

v0.26.4

Choose a tag to compare

@magifd2 magifd2 released this 13 Sep 16:19

Added

  • TestEveryRequiredNameIsDeclared — a schema that lists a name in required
    without declaring it in properties makes a strict client refuse the whole
    tool list (Vertex AI: "schema at top-level requires unspecified property").
    data-toolbox-mcp shipped exactly that and broke a session outright; the
    existing contract test checked declared ⇒ required only, so the fleet is
    pinned in both directions now.

v0.26.3

Choose a tag to compare

@magifd2 magifd2 released this 13 Sep 15:56

Fixed

  • input_not_found named nothing. "input %q is not in the workspace —
    place it there first" does not say where the workspace is, and it reaches the
    model on every init, mask, control and upscale input. It now names the
    absolute path it looked at. (Found on voice-scribe with a real agent, which
    answered that sentence by inventing a directory and spent four rounds
    recovering; these servers share the workspace code.)

v0.26.2

Choose a tag to compare

@magifd2 magifd2 released this 13 Sep 15:17

Fixed

  • The initialize instructions field never mentioned work_dir. It is the
    first thing the model reads about this server — before any tool list — and it
    still described "a workspace directory you prepare" while every tool required
    an argument it did not name. It now states the contract: work_dir is the
    absolute path of a directory you can read back, required, with no default.

Added

  • TestInstructionsNameTheWorkDirContract — the schema and description tests
    walked tools/list; nothing walked what initialize returns (ADR-0009).

v0.26.1

Choose a tag to compare

@magifd2 magifd2 released this 13 Sep 14:48

Fixed

  • A stale comment still described MCPConfig as falling back to a built-in
    default workspace root; 0.26.0 removed both the key and the default.
  • Both READMEs still showed image-forge mcp [--workspace-root <dir>] — a
    flag 0.26.0 deleted — and the paragraph under it had been left half-rewritten
    in either language.

Added

  • TestNoToolDescriptionNamesARetiredWorkDirName — the schema test pinned the
    argument name, nothing pinned the sentences beside it.