Skip to content

Release v1.0.0

Latest

Choose a tag to compare

@Pan-Chera Pan-Chera released this 24 Sep 12:18

Release v1.0.0

Highlights

This release ships three batches of targeted hardening on the existing
feature/assembly line, plus operator-facing documentation:

  • CAD generation hardening — deterministic coder path resolution,
    last-fenced-block JSON extraction, and read-only Aider reference file.
  • Assembly validation improvements — under-connected mate-graph
    rejection, zero-volume mesh QA, and URDF preflight.
  • Web security improvements — CSRF defense, endpoint validation,
    artifact destination restrictions, and subprocess environment
    hardening.

No public API contracts were renamed. No new dependencies were added.

Bug Fixes

  • Builder registry — registered bent_jaw_xz (registry 28 → 29);
    mac_assembly/README.md builder-count reference updated.
  • Deterministic coder failures — _node_python_coder_deterministic
    now resolves the temp_design_*.py / temp_output_*.step /
    temp_output_*.stl paths before the code-generation attempt, so
    a generation failure reports a concrete script path instead of
    NameError.
  • JSON extraction — _extract_json_from_llm now takes the last
    fenced json block when an LLM emits multiple (was first),
    matching _extract_code_from_llm_response semantics. Fixes a class
    of silent parse failures when the LLM emitted an example block before
    the real answer.
  • Mating validation — connectivity / single-root / acyclicity
    checks now gate on n_graph > 1 (was plan.mates), so empty-mate
    multi-part briefs no longer silently pass. Added necessary-condition
    edge-count check (len(plan.mates) >= n_graph - 1); under-connected
    mate graphs now fail validation with a clear error.
  • Collision handling — _pair_collides in mac_assembly/assembly_qa.py
    now returns UNVERIFIABLE for zero-volume and non-finite-volume mesh
    pairs instead of false-passing on flat plates, sheet metal,
    single-triangle STLs, and NaN/inf volumes.
  • URDF validation — export_urdf runs a zero-volume mesh preflight
    before emitting any link; zero-volume links are rejected with a
    clear error instead of silently emitting a URDF with wrong dynamics
    that PyBullet/MuJoCo then reject downstream.

Security

This release closes four tracked security issues (BUG-010, BUG-011,
BUG-012, BUG-020):

  • CSRF protection — every state-changing request
    (POST/PUT/PATCH/DELETE) now requires an X-MAC-CSRF: 1
    header. The browser frontend sends it automatically; non-browser
    clients must add it manually or receive 403. Layered with loopback
    Host allowlist (when MAC_WEB_HOST is loopback), Origin
    validation, and Sec-Fetch-Site: cross-site rejection.
    DNS-rebinding-safe.
  • Endpoint validation — DS_BASE_URL is validated server-side
    before spawning a job. Scheme must be http or https (always
    enforced). Host must match the provider allowlist (loopback,
    api.openai.com, api.deepseek.com,
    generativelanguage.googleapis.com, .aliyuncs.com,
    .googleapis.com) unless MAC_WEB_ALLOW_CUSTOM_ENDPOINT=1 is set.
    The operator's real DashScope key is not forwarded via the LLM-client
    path.
  • Artifact destination restrictions — MAC_WEB_ALLOW_DEST_PATH=1
    now also requires MAC_WEB_DEST_ROOT (absolute path); dest_path
    must be relative and resolve under root. Absolute dest_path and
    .. traversal are rejected. _copy_artifacts re-checks containment
    at write time as defense-in-depth.
  • Subprocess environment hardening — both subprocess.run sites
    that execute LLM-authored Python now pass an explicit env= built
    from a minimal allowlist (PATH, HOME, TMPDIR, TMP, TEMP,
    LANG, LC_ALL, LC_CTYPE, PYTHONPATH, PYTHONIOENCODING,
    LD_LIBRARY_PATH, DYLD_LIBRARY_PATH) plus ITERATION set per
    child. Every provider key in the threat model
    (DASHSCOPE_API_KEY, OPENAI_API_KEY, OPENAI_API_BASE,
    ANTHROPIC_API_KEY, DEEPSEEK_API_KEY, MAC_CONFIG_FILE, etc.) is
    stripped. Operator override via MAC_CHILD_ENV_ALLOW=VAR1,VAR2.

Generated Python execution is not a sandbox. The env-secret
stripping closes one specific vector — env-var secret leakage — it does
not sandbox the generated Python. The generated code still runs with the
operator's UID and retains filesystem, network, and process-spawn
access. Run MAC only with trusted prompts and dependencies, preferably
in a disposable container or restricted account. See SECURITY.md.

Known Limitations

  • Generated Python still has filesystem, network, and process-spawn
    capability.
    Env-var stripping reduces secret leakage only; it is
    not a sandbox. Real isolation is the operator's responsibility
    (disposable container / restricted account) until a future release.
  • Full sandbox isolation is future work. Container / namespace /
    seccomp / setrlimit sandboxing is deferred to a future minor
    release.
  • No resolved-address SSRF check. The DS_BASE_URL host allowlist
    matches on hostname/suffix; a DNS name that resolves to an internal
    IP is not pre-resolved and rejected.
  • No AST scan / static analysis of generated Python. Considered and
    explicitly rejected for this patch — would market a partial control
    as a sandbox.
  • No cross-origin frontend deployment support. The CSRF defense
    assumes a same-origin frontend or non-browser client. A future
    cross-origin frontend would need a real CORS + token contract.
  • Aider subprocess env. Aider (separate from the generated-Python
    subprocess) still inherits the parent env. Separate concern; not
    touched by this release.
  • Five pre-existing baseline test failures
    (tests/test_llm_timeouts.py × 4 — LLM_API_TIMEOUT config drift;
    tests/test_natural_language_benchmark_prompts.py × 1 — benchmark
    count drift) on files outside the Batch A/B/C diff scope. Not
    regressions; should be triaged in a separate follow-up.

Commit range: d63de09..d1de0a1 (7 commits).
Branch: feature/assembly.
Release-contract suite: 89 passed, 3 skipped.
Full repository suite: 507 passed, 5 baseline failures (out of
scope), 6 skipped.