Compare commits
merge into: ceos:main
ceos:main
ceos:dependabot/github_actions/actions-344d71ed27
ceos:studio-settings-polish
ceos:studio-profile-stats
ceos:studio-accent-primary
ceos:fix/setup-sh-wget-fallback
ceos:studio/api-monitor-and-per-model-settings
ceos:fix/offline-load-unreachable-hub
ceos:ci/clean-machine-install
ceos:ci/interrupted-install-recovery
ceos:dependabot/pip/python-security-fec1d00dd4
ceos:dependabot/pip/python-b733189857
ceos:pip-amd-extra-and-url-guard
ceos:pip
ceos:bnb-rocm-fallback-floor-pip
ceos:fix/main-extras-guard
ceos:fix/pip-amd-extra
ceos:dependabot/cargo/studio/src-tauri/cargo-tauri-3292897c27
ceos:fix/marker-read-write-encoding
ceos:fix/rocm-version-test-isolation
ceos:fix/windows-amd-rocm-install
ceos:pre-commit-ci-update-config
ceos:fix/studio-install-readiness
ceos:docker-blackwell-build
ceos:windows-torch-211
ceos:fix/torchcodec-torch211
ceos:woa-nvidia-wsl-fallback
ceos:studio-wheelmap-torch212
ceos:add-cu128-torch2110-extra
ceos:dh/recover-3324-rocm-dockerfile
ceos:studio-autoload-on-device-only
ceos:agent/fix-local-mtp-drafter-discovery
ceos:image-generation
ceos:dependabot/cargo/studio/src-tauri/cargo-tauri-security-082059d156
ceos:dependabot/npm_and_yarn/studio/backend/core/data_recipe/oxc-validator/npm-oxc-validator-7bee95dfb2
ceos:pr-7219-deep-research
ceos:fix/setup-clear-stale-webview-caches
ceos:fix/uninstall-webview-runtime-data
ceos:ui-font-size-token-scaling
ceos:agent/fix-ui-font-scaling
ceos:pr/daniel-unsloth-start-audit
ceos:agent/harden-auto-permission-network-gates
ceos:fix/llama-strix-system-rocm
ceos:fix/studio-gc-standard-offloader
ceos:volta-v100-cu128-guard
ceos:studio-remote-update-confirm
ceos:studio-sandbox-fs-confinement
ceos:studio-mtp-tool-markup-leak
ceos:studio-sandbox-isolation-hint
ceos:fix-sidebar-leading-tight-regex
ceos:launcher-no-browser
ceos:video-diffusion-improvements
ceos:fix/sidebar-descender-test-regex
ceos:studio-picker-followup
ceos:studio-inkling-support
ceos:fix/studio-torchao-export-windows-rocm
ceos:studio-no-inpage-bootstrap-seed
ceos:danielhanchen/studio-os-sandbox
ceos:fix/fused-lora-fp32-dtype
ceos:danielhanchen/harden-code-exec-sandbox
ceos:ci-harden-smoke-http-retries
ceos:resume-ci-schedule
ceos:fix/gptoss-generate-poisons-compiled-training
ceos:torch-211-readiness-canary
ceos:flash-attn-blackwell-6961
ceos:danielhanchen/block-markerless-code-tools
ceos:shimmyshimmer/studio-launcher-install-id-repair
ceos:danielhanchen/confirm-code-execution
ceos:fix-mlx-gguf-reload-context
ceos:diffusion-train-perf
ceos:fla-gated-deltanet-advisory
ceos:fix/stop-tool-xml-in-final-pass
ceos:fix/cache-frontend-build
ceos:fix/studio-ld-library-path-cuda
ceos:fix/windows-setup-no-gpu
ceos:studio-tools-multi-format-v3
ceos:pr-6866-assets
ceos:pr-6763-assets
ceos:fix-compressed-export-transformers-ceiling
ceos:fix-llmcompressor-reinstall-guard
ceos:harden-llmcompressor-install
ceos:diffusion-phase6-features
ceos:merge_to_fp8
ceos:pr6658-image-generation
ceos:dependabot/npm_and_yarn/studio/frontend/npm-frontend-security-360cad5ee5
ceos:studio-cpu-numa-gguf-hardening
ceos:fix-tokenizer-extra-special-tokens-list
ceos:studio-trim-log-noise
ceos:studio-mtp-draft-kv-fullctx
ceos:pr6392-ui-assets
ceos:doc-extraction-fast
ceos:pr-6634-canvas-evidence
ceos:demo/pr-6666-preview
ceos:studio-preview-link-media
ceos:fix-torch-index-family-env
ceos:studio-model-idle-ttl
ceos:fix-gemma4-openai-api-streams
ceos:fix/stray-forward-poisons-compiled-training
ceos:fix-installer-studio-autostart
ceos:gemma4-eseries-generation-usecache
ceos:studio-llama-update-toast-tag
ceos:fix-gpt-oss-merged-reload-model-name
ceos:studio-readme-server-flags
ceos:reduce-comments-package
ceos:studio-orphan-llama-server-reaper
ceos:studio-security-headers-pure-asgi
ceos:daniel/studio-sliding-window-compaction
ceos:fix/lemonade-marker-update-to-fork
ceos:studio-consolidate-spinners
ceos:studio-sidebar-hover-pills
ceos:studio-toast-loading-spinner
ceos:studio-update-installer-oneliner
ceos:cleanup/pr5940-comments
ceos:auto-install-upgrade-setuptools-pip
ceos:studio-diffusiongemma-disable-tools-enable-artifacts
ceos:studio-prebuilt-attach-diffusion-visual-server
ceos:fix-prediction-step-return-logits-restore
ceos:dg-onto-main
ceos:studio/fix-llama-update-downgrade
ceos:diffusiongemma-studio-media
ceos:fix/llama-update-banner-downgrade
ceos:diffusiongemma-studio-support
ceos:security/studio-tauri-2-11-1
ceos:pr-6016-nan-loss-fixes
ceos:fix-responses-empty-tool-output
ceos:pr-6049
ceos:fix-5999-win-llama-gpu-selection
ceos:studio-composer
ceos:fix/studio-reset-password-hint-windows-path
ceos:feature/rag
ceos:feature/mcp-config-file
ceos:feature/docker-studio-0.1.43-beta-2026.5.10-2026-JUN-03-r5
ceos:grpo-fullft-return-hidden-states
ceos:fix/llama-gpu-offload-validation
ceos:pr-5916-hub-evidence
ceos:studio-tokenless-llama-prebuilt
ceos:studio-rag-5910-assets
ceos:tool-call-confirmation
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31-r2
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31-r3
ceos:studio-rag-trimmed
ceos:studio-rag-fast-indexing
ceos:test-v100-grpo-fullft-all
ceos:feature/docker-studio-0.1.42-beta-2026.5.8-2026-MAY-31-r2
ceos:macos-prebuilt-setup
ceos:fix/amd-optional-bnb
ceos:fix/macos-arm64-venv-autodetect
ceos:parked/external-rag-prefetch
ceos:feat/expose-sampling-params-core
ceos:feat/codex-provider
ceos:feat/html-svg-chat-rendering
ceos:studio/openai-web-search-actions-and-image-overlay
ceos:chat-artifacts
ceos:studio-diffusion-images
ceos:fix-tool-reprompt-overfire
ceos:feature/docker-studio-0.1.41-beta-2026.5.7-2026-MAY-24-r2
ceos:studio-sandbox-hardening
ceos:feature/docker-studio-0.1.41-beta-2026.5.7-2026-MAY-24
ceos:feat/model-picker-filter-fixes
ceos:followup-mtp-reload-guards
ceos:feature/docker-studio-0.1.41-beta-2026.5.6-2026-MAY-22-r2
ceos:feature/docker-studio-0.1.41-beta-2026.5.6-2026-MAY-22
ceos:daniel/studio-chat-template-kwargs-registry
ceos:daniel/studio-validation-retry-loop
ceos:daniel/studio-respond-tool-injection
ceos:feat/openai-image-generation-pill
ceos:followup-lockfile-audit-regressions
ceos:studio-spec-pmin-and-ngram-map
ceos:debug/anthropic-tool-call-trace
ceos:revert-5390-fix/anthropic-claude-code-tools
ceos:feature/docker-studio-0.1.41-beta-2026.5.5-2026-MAY-20
ceos:feature/docker-studio-v0.1.41-beta-2026.5.5
ceos:studio/settings-panel-closed-tab-trap
ceos:studio/keep-shutdown-dialog-open-on-error
ceos:studio/clear-stale-thread-search-after-delete
ceos:studio/code-block-h-scroll
ceos:studio/responsiveness-tool-bursts
ceos:studio/export-markdown-filename
ceos:studio/sidebar-thread-title-tooltip
ceos:ci/npm-ci-followup-5604
ceos:studio/autoload-polish-follow-up
ceos:studio/auto-continue-mid-plan
ceos:ci/frozen-lockfile-installs
ceos:studio-frontend-vitest
ceos:check/windows-torch
ceos:studio-test-5434-and-5517
ceos:followup-active-only-grouped
ceos:studio-toaster-bottom-right
ceos:feat-gemma4-moe-4bit-swap
ceos:fix-issue-5344-quantization-guardrail
ceos:studio/hardening-followup
ceos:feature/docker-studio-v0.13.9-beta-2026.5.2-may13-snapshot
ceos:feature/docker-studio-vxxxx-beta-2026.5.3
ceos:combine-dependabot-2026-05-11
ceos:dependabot/bun/studio/frontend/bun-frontend-57b05fa4fc
ceos:fix/mlx
ceos:feature/docker-studio-v0.13.9-beta-2026.5.2
ceos:tests-docs-runner
ceos:feature/docker-studio-v0.13.8-2026.5.1
ceos:feature/gemma4-trans5.5.2
ceos:feature/docker-studio-v0.13.7-beta-2026.4.8-may-snapshot
ceos:fix/image-only-chat-validation
ceos:fix/tauri-tray-and-installer
ceos:danielhanchen/flex-moe-qwen3
ceos:feature/docker-studio-v0.13.7-beta-2026.4.8
ceos:feature/docker-studio-v0.13.6-beta-2026.4.7
ceos:flex-fast-inference-gate
ceos:transformers-continuous-batching-qwen3
ceos:fix/bnb-multidevice-inference-hooks
ceos:gemma4-fp16-force-float32
ceos:feature/tool-choice-kwarg-openai-format
ceos:fix/ui-fix
ceos:fix/gemma4-force-float32
ceos:feature/docker-studio-v0.13.6-beta-2026.4.6
ceos:fix/gemma4-fp16-force-float32
ceos:studio-tool-nudge-small-models
ceos:fix/windows-studio-update-launcher-lock
ceos:feature/docker-studio-spark-v0.13.6-beta-2026.4.5
ceos:feature/docker-studio-v0.13.6-beta-2026.4.5
ceos:studio/batch-gguf-exports
ceos:studio/api-keys
ceos:feature/chat-ui-polish
ceos:studio/anthropic-api
ceos:feature/docker-studio-v0.1.36-beta-2026.4.4
ceos:feat/access-endpoint
ceos:feature/docker-studio-v0.1.35-beta-2026.4.4
ceos:fix/transformers-v5-tiers
ceos:pr-4852-head
ceos:feature/docker-studio-v0.1.35-beta-2026.4.2
ceos:feature/update-details-manifest
ceos:tests/preference-dataset-format
ceos:feature/docker-studio-v0.1.35-beta
ceos:fix/lazy-import-llama-cpp
ceos:fix/llama-tag-latest
ceos:fix/llama-cpp-b8637
ceos:fix/studio-install-from-git-main
ceos:fix/uv-venv-clean
ceos:fix/mac-llamacpp-binary
ceos:test/kv-cache-estimation-tests
ceos:fix/kv-cache-5path-estimation
ceos:fix/web-search-ssl-sni
ceos:feature/docker-studio-v0.1.3-beta
ceos:fix/transformers-v5-compat
ceos:pr-4741-5147102380432514182
ceos:fix/fitness-oom-calculator
ceos:flexattn_refactor_fixed
ceos:feat/chat-ui-enhancements
ceos:feature/rocm-support
ceos:feature/rocm-test-suite
ceos:feature/rocm-hardware-flag
ceos:feature/rocm-llama-prebuilt
ceos:feature/rocm-python-stack
ceos:feature/rocm-install-sh
ceos:fix/rocm-audit-bugfixes
ceos:optimal-device-map
ceos:feat/local-hf-export-toggle
ceos:feature/docker-studio-v0.1.25-beta
ceos:bump-version-2026.3.16
ceos:fix/tool-call-nudge-and-xml-strip
ceos:fix/streaming-tool-detection
ceos:feat/studio-dedicated-streaming-server
ceos:fix/colab-install-python-stack
ceos:fix/colab-llama-cpp-install
ceos:fix/colab-missing-ml-deps
ceos:fix/colab-setup-local-flag
ceos:fix/studio-sse-streaming-overhead
ceos:feature/docker-studio-25march
ceos:dh/fix-colab-studio-launch
ceos:dh/bump-installer-version-2026.3.12
ceos:fix/skip-broken-bun-versions
ceos:fix/replace-unicode-dashes
ceos:fix/one-line-launch-windows
ceos:feature/docker-hf-space
ceos:feature/docker-container-studio
ceos:fix/studio-ts-build-errors
ceos:feature/strip-authentication-hf
ceos:fix/venv-t5-tokenizer-backends
ceos:fix/studio-venv-t5-tiktoken
ceos:fix/studio-venv-colab
ceos:feature/docker-studio-folder
ceos:test/hf-space
ceos:dh/combine-grpo-mixed-precision-fixes
ceos:fix/fp8-moe-bug-fixes
ceos:studio/fix-stale-gguf-metadata
ceos:fix/checking-dataset-logic
ceos:fix/ordering-of-training-models
ceos:fix/python-candidate-version
ceos:studio/training-progress-deferred-llama-cpp
ceos:feat/gguf-only-cpu
ceos:fix/qwen3_5-fused-ce-clean
ceos:fix/fp8-moe-loader-guard
ceos:studio/extract-param-count-from-name
ceos:fix/4155-training-args-config-guard
ceos:fix/gguf-audio
ceos:fix/cancel-hf-help-model
ceos:studio/toast-dismiss-ux
ceos:fix/flex-attention-pre-ampere
ceos:fix/windows-fixes
ceos:test/test-setup
ceos:fix/test-utils-structlog-caplog
ceos:dh/recover-1764-tool-calling-demo
ceos:dh/recover-3897-metrics
ceos:dh/recover-3125-phi2
ceos:dh/recover-3653-past-kv
ceos:dh/recover-3740-amd-radeon
ceos:dh/recover-3819-qwen3-omni
ceos:dh/recover-3823-context-parallel
ceos:dh/recover-3918-asft
ceos:dh/recover-3950-apple-silicon
ceos:dh/recover-4038-tool-calling-compat
ceos:dh/recover-4184-colab-export-docs
ceos:dh/recover-3856-mlx
ceos:test-branch-some-work
ceos:backup/pre-history-recovery-2026-03-12
ceos:rolandtannous-patch-1
ceos:dh/recover-4196-grpo-resume
ceos:dh/recover-4145-moe-alias
ceos:dh/recover-3875-device-context
ceos:dh/recover-3708-moe-target-parameters
ceos:dh/recover-4191-trl-bump
ceos:dh/recover-4183-hermes-chat-template
ceos:dh/recover-4179-lora-chat-template
ceos:dh/recover-4177-modernbert-num-labels
ceos:dh/recover-4090-idefics3
ceos:dh/recover-4077-ddp-vlm-tiled-mlp
ceos:dh/recover-3891-cggr
ceos:dh/recover-3816-vllm-revision
ceos:dh/recover-3804-zero-stride-fix
ceos:dh/recover-3153-seq2seq
ceos:dh/recover-3691-ruff-version
ceos:dh/recover-3469-filelocks
ceos:dh/recover-3660-trl-native-datasets
ceos:dh/recover-3241-lr-strict-mode
ceos:dh/recover-3341-reference-docs
ceos:dh/recover-3234-eval-steps-warning
ceos:dh/recover-3793-revision-chat-template
ceos:dh/recover-3436-qwen25-coder
ceos:dh/recover-3425-gpt-oss-bf16
ceos:dh/recover-1225-load-checkpoint-add-new-tokens-rebased
ceos:dh/recover-974-cuda-visible-devices-rebased
ceos:dh/recover-4035-sm100-vllm-env-only-rebased
ceos:dh/recover-4114-full-finetune-precision-rebased
ceos:dh/recover-3975-trl-025-grpo-reward-vision-v2-rebased
ceos:dh/recover-4207-stale-wheel-urls
ceos:dh/recover-3958-compat-guards-rebased
ceos:nightly
ceos:fix/sm-gating-compile-options
ceos:fix-broken-wandb-import
ceos:dh/fix-4082-full-finetune-precision
ceos:fix/trl-experimental-compat
ceos:fix/temp-O-shape-batched-inference
ceos:fix/hip-amdgpu-ids-model-import-filter
ceos:pr-4049-head
ceos:fix/sm100-vllm-env-only
ceos:rocm-gpt-oss-bf16-aiter
ceos:fix-import-vllm-mma
ceos:fix/silence-peft-target-parameters-warning
ceos:fix/silence-training-warnings
ceos:fix/trl-experimental-thin-wrapper-compilation
ceos:fix-torchcodec-runtime-error
ceos:pip-add-torch-2.10-support
ceos:fix/trl-025-grpo-reward-vision-v2
ceos:fix/trl-025-grpo-reward-vision
ceos:fix/trl-027-grpo-compatibility
ceos:fix/compat-guards
ceos:fix/pr3812-moe-kernels
ceos:pr-3719
ceos:safer-vllm-notebook-patch
ceos:pluesclues-patch-1
ceos:shimmyshimmer-patch-1
ceos:fix/fbgemm-cutlass-errors-sm100
ceos:grpo-fix-on-pr3754
ceos:fix-grpo-version-compat
ceos:grpo-fix-rlpy
ceos:fix-pdl-use-vllm-version-check
ceos:fix-vllm-pdl-blackwell
ceos:fix-vllm-chat-template-sync
ceos:quant-config-respect
ceos:rl-fixes
ceos:fix-sentence-transformer-quant-config
ceos:fix/fast-generate-wrapper-helpful-errors
ceos:fix-gemma3-qat-stability
ceos:fix/correctness-bugs-batch2
ceos:fix/correctness-bugs
ceos:danielhanchen-patch-2
ceos:danielhanchen-patch-1
ceos:pr/3673
ceos:fix-flash-attn-masking
ceos:fix-grpo-trainer-rpc-error
ceos:amd
ceos:v0.1.501-beta
ceos:v0.1.50-beta
ceos:v0.1.49-beta
ceos:v0.1.481-beta
ceos:v0.1.48-beta
ceos:v0.1.471-beta
ceos:v0.1.47-beta
ceos:v0.1.464-beta
ceos:v0.1.463-beta
ceos:v0.1.462-beta
ceos:v0.1.461-beta
ceos:v0.1.46-beta
ceos:v0.1.451-beta
ceos:v0.1.45-beta
ceos:v0.1.44-beta
ceos:v0.1.431-beta
ceos:v0.1.43-beta
ceos:v0.1.42-beta
ceos:v0.1.416-beta
ceos:v0.1.415-beta
ceos:v0.1.41-beta
ceos:v0.1.405-beta
ceos:v0.1.40-beta
ceos:v0.1.39-beta
ceos:v0.1.38-beta
ceos:v0.1.37-beta
ceos:v0.1.36-beta
ceos:v0.1.35-beta
ceos:v0.1.3-beta
ceos:v0.1.25-beta
ceos:v0.1.2-beta
ceos:b8475
ceos:b8457
ceos:v0.1.0-beta
ceos:March-2026
ceos:February-2026
ceos:December-2025
ceos:November-2025
ceos:October-2025
ceos:September-2025-v3
ceos:September-2025-v2
ceos:August-2025-v2
ceos:August-2025
ceos:July-2025
ceos:June-2025
ceos:May-2025
ceos:2025-03
ceos:2025-02-v2
ceos:2025-02
ceos:2025-01
ceos:December-2024
ceos:November-2024
ceos:October-2024
ceos:September-2024
ceos:August-2024
ceos:July-Llama-2024
ceos:July-Mistral-2024
ceos:July-2024
...
pull from: ceos:studio-sandbox-hardening
ceos:main
ceos:dependabot/github_actions/actions-344d71ed27
ceos:studio-settings-polish
ceos:studio-profile-stats
ceos:studio-accent-primary
ceos:fix/setup-sh-wget-fallback
ceos:studio/api-monitor-and-per-model-settings
ceos:fix/offline-load-unreachable-hub
ceos:ci/clean-machine-install
ceos:ci/interrupted-install-recovery
ceos:dependabot/pip/python-security-fec1d00dd4
ceos:dependabot/pip/python-b733189857
ceos:pip-amd-extra-and-url-guard
ceos:pip
ceos:bnb-rocm-fallback-floor-pip
ceos:fix/main-extras-guard
ceos:fix/pip-amd-extra
ceos:dependabot/cargo/studio/src-tauri/cargo-tauri-3292897c27
ceos:fix/marker-read-write-encoding
ceos:fix/rocm-version-test-isolation
ceos:fix/windows-amd-rocm-install
ceos:pre-commit-ci-update-config
ceos:fix/studio-install-readiness
ceos:docker-blackwell-build
ceos:windows-torch-211
ceos:fix/torchcodec-torch211
ceos:woa-nvidia-wsl-fallback
ceos:studio-wheelmap-torch212
ceos:add-cu128-torch2110-extra
ceos:dh/recover-3324-rocm-dockerfile
ceos:studio-autoload-on-device-only
ceos:agent/fix-local-mtp-drafter-discovery
ceos:image-generation
ceos:dependabot/cargo/studio/src-tauri/cargo-tauri-security-082059d156
ceos:dependabot/npm_and_yarn/studio/backend/core/data_recipe/oxc-validator/npm-oxc-validator-7bee95dfb2
ceos:pr-7219-deep-research
ceos:fix/setup-clear-stale-webview-caches
ceos:fix/uninstall-webview-runtime-data
ceos:ui-font-size-token-scaling
ceos:agent/fix-ui-font-scaling
ceos:pr/daniel-unsloth-start-audit
ceos:agent/harden-auto-permission-network-gates
ceos:fix/llama-strix-system-rocm
ceos:fix/studio-gc-standard-offloader
ceos:volta-v100-cu128-guard
ceos:studio-remote-update-confirm
ceos:studio-sandbox-fs-confinement
ceos:studio-mtp-tool-markup-leak
ceos:studio-sandbox-isolation-hint
ceos:fix-sidebar-leading-tight-regex
ceos:launcher-no-browser
ceos:video-diffusion-improvements
ceos:fix/sidebar-descender-test-regex
ceos:studio-picker-followup
ceos:studio-inkling-support
ceos:fix/studio-torchao-export-windows-rocm
ceos:studio-no-inpage-bootstrap-seed
ceos:danielhanchen/studio-os-sandbox
ceos:fix/fused-lora-fp32-dtype
ceos:danielhanchen/harden-code-exec-sandbox
ceos:ci-harden-smoke-http-retries
ceos:resume-ci-schedule
ceos:fix/gptoss-generate-poisons-compiled-training
ceos:torch-211-readiness-canary
ceos:flash-attn-blackwell-6961
ceos:danielhanchen/block-markerless-code-tools
ceos:shimmyshimmer/studio-launcher-install-id-repair
ceos:danielhanchen/confirm-code-execution
ceos:fix-mlx-gguf-reload-context
ceos:diffusion-train-perf
ceos:fla-gated-deltanet-advisory
ceos:fix/stop-tool-xml-in-final-pass
ceos:fix/cache-frontend-build
ceos:fix/studio-ld-library-path-cuda
ceos:fix/windows-setup-no-gpu
ceos:studio-tools-multi-format-v3
ceos:pr-6866-assets
ceos:pr-6763-assets
ceos:fix-compressed-export-transformers-ceiling
ceos:fix-llmcompressor-reinstall-guard
ceos:harden-llmcompressor-install
ceos:diffusion-phase6-features
ceos:merge_to_fp8
ceos:pr6658-image-generation
ceos:dependabot/npm_and_yarn/studio/frontend/npm-frontend-security-360cad5ee5
ceos:studio-cpu-numa-gguf-hardening
ceos:fix-tokenizer-extra-special-tokens-list
ceos:studio-trim-log-noise
ceos:studio-mtp-draft-kv-fullctx
ceos:pr6392-ui-assets
ceos:doc-extraction-fast
ceos:pr-6634-canvas-evidence
ceos:demo/pr-6666-preview
ceos:studio-preview-link-media
ceos:fix-torch-index-family-env
ceos:studio-model-idle-ttl
ceos:fix-gemma4-openai-api-streams
ceos:fix/stray-forward-poisons-compiled-training
ceos:fix-installer-studio-autostart
ceos:gemma4-eseries-generation-usecache
ceos:studio-llama-update-toast-tag
ceos:fix-gpt-oss-merged-reload-model-name
ceos:studio-readme-server-flags
ceos:reduce-comments-package
ceos:studio-orphan-llama-server-reaper
ceos:studio-security-headers-pure-asgi
ceos:daniel/studio-sliding-window-compaction
ceos:fix/lemonade-marker-update-to-fork
ceos:studio-consolidate-spinners
ceos:studio-sidebar-hover-pills
ceos:studio-toast-loading-spinner
ceos:studio-update-installer-oneliner
ceos:cleanup/pr5940-comments
ceos:auto-install-upgrade-setuptools-pip
ceos:studio-diffusiongemma-disable-tools-enable-artifacts
ceos:studio-prebuilt-attach-diffusion-visual-server
ceos:fix-prediction-step-return-logits-restore
ceos:dg-onto-main
ceos:studio/fix-llama-update-downgrade
ceos:diffusiongemma-studio-media
ceos:fix/llama-update-banner-downgrade
ceos:diffusiongemma-studio-support
ceos:security/studio-tauri-2-11-1
ceos:pr-6016-nan-loss-fixes
ceos:fix-responses-empty-tool-output
ceos:pr-6049
ceos:fix-5999-win-llama-gpu-selection
ceos:studio-composer
ceos:fix/studio-reset-password-hint-windows-path
ceos:feature/rag
ceos:feature/mcp-config-file
ceos:feature/docker-studio-0.1.43-beta-2026.5.10-2026-JUN-03-r5
ceos:grpo-fullft-return-hidden-states
ceos:fix/llama-gpu-offload-validation
ceos:pr-5916-hub-evidence
ceos:studio-tokenless-llama-prebuilt
ceos:studio-rag-5910-assets
ceos:tool-call-confirmation
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31-r2
ceos:feature/docker-studio-0.1.43-beta-2026.5.9-2026-MAY-31-r3
ceos:studio-rag-trimmed
ceos:studio-rag-fast-indexing
ceos:test-v100-grpo-fullft-all
ceos:feature/docker-studio-0.1.42-beta-2026.5.8-2026-MAY-31-r2
ceos:macos-prebuilt-setup
ceos:fix/amd-optional-bnb
ceos:fix/macos-arm64-venv-autodetect
ceos:parked/external-rag-prefetch
ceos:feat/expose-sampling-params-core
ceos:feat/codex-provider
ceos:feat/html-svg-chat-rendering
ceos:studio/openai-web-search-actions-and-image-overlay
ceos:chat-artifacts
ceos:studio-diffusion-images
ceos:fix-tool-reprompt-overfire
ceos:feature/docker-studio-0.1.41-beta-2026.5.7-2026-MAY-24-r2
ceos:studio-sandbox-hardening
ceos:feature/docker-studio-0.1.41-beta-2026.5.7-2026-MAY-24
ceos:feat/model-picker-filter-fixes
ceos:followup-mtp-reload-guards
ceos:feature/docker-studio-0.1.41-beta-2026.5.6-2026-MAY-22-r2
ceos:feature/docker-studio-0.1.41-beta-2026.5.6-2026-MAY-22
ceos:daniel/studio-chat-template-kwargs-registry
ceos:daniel/studio-validation-retry-loop
ceos:daniel/studio-respond-tool-injection
ceos:feat/openai-image-generation-pill
ceos:followup-lockfile-audit-regressions
ceos:studio-spec-pmin-and-ngram-map
ceos:debug/anthropic-tool-call-trace
ceos:revert-5390-fix/anthropic-claude-code-tools
ceos:feature/docker-studio-0.1.41-beta-2026.5.5-2026-MAY-20
ceos:feature/docker-studio-v0.1.41-beta-2026.5.5
ceos:studio/settings-panel-closed-tab-trap
ceos:studio/keep-shutdown-dialog-open-on-error
ceos:studio/clear-stale-thread-search-after-delete
ceos:studio/code-block-h-scroll
ceos:studio/responsiveness-tool-bursts
ceos:studio/export-markdown-filename
ceos:studio/sidebar-thread-title-tooltip
ceos:ci/npm-ci-followup-5604
ceos:studio/autoload-polish-follow-up
ceos:studio/auto-continue-mid-plan
ceos:ci/frozen-lockfile-installs
ceos:studio-frontend-vitest
ceos:check/windows-torch
ceos:studio-test-5434-and-5517
ceos:followup-active-only-grouped
ceos:studio-toaster-bottom-right
ceos:feat-gemma4-moe-4bit-swap
ceos:fix-issue-5344-quantization-guardrail
ceos:studio/hardening-followup
ceos:feature/docker-studio-v0.13.9-beta-2026.5.2-may13-snapshot
ceos:feature/docker-studio-vxxxx-beta-2026.5.3
ceos:combine-dependabot-2026-05-11
ceos:dependabot/bun/studio/frontend/bun-frontend-57b05fa4fc
ceos:fix/mlx
ceos:feature/docker-studio-v0.13.9-beta-2026.5.2
ceos:tests-docs-runner
ceos:feature/docker-studio-v0.13.8-2026.5.1
ceos:feature/gemma4-trans5.5.2
ceos:feature/docker-studio-v0.13.7-beta-2026.4.8-may-snapshot
ceos:fix/image-only-chat-validation
ceos:fix/tauri-tray-and-installer
ceos:danielhanchen/flex-moe-qwen3
ceos:feature/docker-studio-v0.13.7-beta-2026.4.8
ceos:feature/docker-studio-v0.13.6-beta-2026.4.7
ceos:flex-fast-inference-gate
ceos:transformers-continuous-batching-qwen3
ceos:fix/bnb-multidevice-inference-hooks
ceos:gemma4-fp16-force-float32
ceos:feature/tool-choice-kwarg-openai-format
ceos:fix/ui-fix
ceos:fix/gemma4-force-float32
ceos:feature/docker-studio-v0.13.6-beta-2026.4.6
ceos:fix/gemma4-fp16-force-float32
ceos:studio-tool-nudge-small-models
ceos:fix/windows-studio-update-launcher-lock
ceos:feature/docker-studio-spark-v0.13.6-beta-2026.4.5
ceos:feature/docker-studio-v0.13.6-beta-2026.4.5
ceos:studio/batch-gguf-exports
ceos:studio/api-keys
ceos:feature/chat-ui-polish
ceos:studio/anthropic-api
ceos:feature/docker-studio-v0.1.36-beta-2026.4.4
ceos:feat/access-endpoint
ceos:feature/docker-studio-v0.1.35-beta-2026.4.4
ceos:fix/transformers-v5-tiers
ceos:pr-4852-head
ceos:feature/docker-studio-v0.1.35-beta-2026.4.2
ceos:feature/update-details-manifest
ceos:tests/preference-dataset-format
ceos:feature/docker-studio-v0.1.35-beta
ceos:fix/lazy-import-llama-cpp
ceos:fix/llama-tag-latest
ceos:fix/llama-cpp-b8637
ceos:fix/studio-install-from-git-main
ceos:fix/uv-venv-clean
ceos:fix/mac-llamacpp-binary
ceos:test/kv-cache-estimation-tests
ceos:fix/kv-cache-5path-estimation
ceos:fix/web-search-ssl-sni
ceos:feature/docker-studio-v0.1.3-beta
ceos:fix/transformers-v5-compat
ceos:pr-4741-5147102380432514182
ceos:fix/fitness-oom-calculator
ceos:flexattn_refactor_fixed
ceos:feat/chat-ui-enhancements
ceos:feature/rocm-support
ceos:feature/rocm-test-suite
ceos:feature/rocm-hardware-flag
ceos:feature/rocm-llama-prebuilt
ceos:feature/rocm-python-stack
ceos:feature/rocm-install-sh
ceos:fix/rocm-audit-bugfixes
ceos:optimal-device-map
ceos:feat/local-hf-export-toggle
ceos:feature/docker-studio-v0.1.25-beta
ceos:bump-version-2026.3.16
ceos:fix/tool-call-nudge-and-xml-strip
ceos:fix/streaming-tool-detection
ceos:feat/studio-dedicated-streaming-server
ceos:fix/colab-install-python-stack
ceos:fix/colab-llama-cpp-install
ceos:fix/colab-missing-ml-deps
ceos:fix/colab-setup-local-flag
ceos:fix/studio-sse-streaming-overhead
ceos:feature/docker-studio-25march
ceos:dh/fix-colab-studio-launch
ceos:dh/bump-installer-version-2026.3.12
ceos:fix/skip-broken-bun-versions
ceos:fix/replace-unicode-dashes
ceos:fix/one-line-launch-windows
ceos:feature/docker-hf-space
ceos:feature/docker-container-studio
ceos:fix/studio-ts-build-errors
ceos:feature/strip-authentication-hf
ceos:fix/venv-t5-tokenizer-backends
ceos:fix/studio-venv-t5-tiktoken
ceos:fix/studio-venv-colab
ceos:feature/docker-studio-folder
ceos:test/hf-space
ceos:dh/combine-grpo-mixed-precision-fixes
ceos:fix/fp8-moe-bug-fixes
ceos:studio/fix-stale-gguf-metadata
ceos:fix/checking-dataset-logic
ceos:fix/ordering-of-training-models
ceos:fix/python-candidate-version
ceos:studio/training-progress-deferred-llama-cpp
ceos:feat/gguf-only-cpu
ceos:fix/qwen3_5-fused-ce-clean
ceos:fix/fp8-moe-loader-guard
ceos:studio/extract-param-count-from-name
ceos:fix/4155-training-args-config-guard
ceos:fix/gguf-audio
ceos:fix/cancel-hf-help-model
ceos:studio/toast-dismiss-ux
ceos:fix/flex-attention-pre-ampere
ceos:fix/windows-fixes
ceos:test/test-setup
ceos:fix/test-utils-structlog-caplog
ceos:dh/recover-1764-tool-calling-demo
ceos:dh/recover-3897-metrics
ceos:dh/recover-3125-phi2
ceos:dh/recover-3653-past-kv
ceos:dh/recover-3740-amd-radeon
ceos:dh/recover-3819-qwen3-omni
ceos:dh/recover-3823-context-parallel
ceos:dh/recover-3918-asft
ceos:dh/recover-3950-apple-silicon
ceos:dh/recover-4038-tool-calling-compat
ceos:dh/recover-4184-colab-export-docs
ceos:dh/recover-3856-mlx
ceos:test-branch-some-work
ceos:backup/pre-history-recovery-2026-03-12
ceos:rolandtannous-patch-1
ceos:dh/recover-4196-grpo-resume
ceos:dh/recover-4145-moe-alias
ceos:dh/recover-3875-device-context
ceos:dh/recover-3708-moe-target-parameters
ceos:dh/recover-4191-trl-bump
ceos:dh/recover-4183-hermes-chat-template
ceos:dh/recover-4179-lora-chat-template
ceos:dh/recover-4177-modernbert-num-labels
ceos:dh/recover-4090-idefics3
ceos:dh/recover-4077-ddp-vlm-tiled-mlp
ceos:dh/recover-3891-cggr
ceos:dh/recover-3816-vllm-revision
ceos:dh/recover-3804-zero-stride-fix
ceos:dh/recover-3153-seq2seq
ceos:dh/recover-3691-ruff-version
ceos:dh/recover-3469-filelocks
ceos:dh/recover-3660-trl-native-datasets
ceos:dh/recover-3241-lr-strict-mode
ceos:dh/recover-3341-reference-docs
ceos:dh/recover-3234-eval-steps-warning
ceos:dh/recover-3793-revision-chat-template
ceos:dh/recover-3436-qwen25-coder
ceos:dh/recover-3425-gpt-oss-bf16
ceos:dh/recover-1225-load-checkpoint-add-new-tokens-rebased
ceos:dh/recover-974-cuda-visible-devices-rebased
ceos:dh/recover-4035-sm100-vllm-env-only-rebased
ceos:dh/recover-4114-full-finetune-precision-rebased
ceos:dh/recover-3975-trl-025-grpo-reward-vision-v2-rebased
ceos:dh/recover-4207-stale-wheel-urls
ceos:dh/recover-3958-compat-guards-rebased
ceos:nightly
ceos:fix/sm-gating-compile-options
ceos:fix-broken-wandb-import
ceos:dh/fix-4082-full-finetune-precision
ceos:fix/trl-experimental-compat
ceos:fix/temp-O-shape-batched-inference
ceos:fix/hip-amdgpu-ids-model-import-filter
ceos:pr-4049-head
ceos:fix/sm100-vllm-env-only
ceos:rocm-gpt-oss-bf16-aiter
ceos:fix-import-vllm-mma
ceos:fix/silence-peft-target-parameters-warning
ceos:fix/silence-training-warnings
ceos:fix/trl-experimental-thin-wrapper-compilation
ceos:fix-torchcodec-runtime-error
ceos:pip-add-torch-2.10-support
ceos:fix/trl-025-grpo-reward-vision-v2
ceos:fix/trl-025-grpo-reward-vision
ceos:fix/trl-027-grpo-compatibility
ceos:fix/compat-guards
ceos:fix/pr3812-moe-kernels
ceos:pr-3719
ceos:safer-vllm-notebook-patch
ceos:pluesclues-patch-1
ceos:shimmyshimmer-patch-1
ceos:fix/fbgemm-cutlass-errors-sm100
ceos:grpo-fix-on-pr3754
ceos:fix-grpo-version-compat
ceos:grpo-fix-rlpy
ceos:fix-pdl-use-vllm-version-check
ceos:fix-vllm-pdl-blackwell
ceos:fix-vllm-chat-template-sync
ceos:quant-config-respect
ceos:rl-fixes
ceos:fix-sentence-transformer-quant-config
ceos:fix/fast-generate-wrapper-helpful-errors
ceos:fix-gemma3-qat-stability
ceos:fix/correctness-bugs-batch2
ceos:fix/correctness-bugs
ceos:danielhanchen-patch-2
ceos:danielhanchen-patch-1
ceos:pr/3673
ceos:fix-flash-attn-masking
ceos:fix-grpo-trainer-rpc-error
ceos:amd
ceos:v0.1.501-beta
ceos:v0.1.50-beta
ceos:v0.1.49-beta
ceos:v0.1.481-beta
ceos:v0.1.48-beta
ceos:v0.1.471-beta
ceos:v0.1.47-beta
ceos:v0.1.464-beta
ceos:v0.1.463-beta
ceos:v0.1.462-beta
ceos:v0.1.461-beta
ceos:v0.1.46-beta
ceos:v0.1.451-beta
ceos:v0.1.45-beta
ceos:v0.1.44-beta
ceos:v0.1.431-beta
ceos:v0.1.43-beta
ceos:v0.1.42-beta
ceos:v0.1.416-beta
ceos:v0.1.415-beta
ceos:v0.1.41-beta
ceos:v0.1.405-beta
ceos:v0.1.40-beta
ceos:v0.1.39-beta
ceos:v0.1.38-beta
ceos:v0.1.37-beta
ceos:v0.1.36-beta
ceos:v0.1.35-beta
ceos:v0.1.3-beta
ceos:v0.1.25-beta
ceos:v0.1.2-beta
ceos:b8475
ceos:b8457
ceos:v0.1.0-beta
ceos:March-2026
ceos:February-2026
ceos:December-2025
ceos:November-2025
ceos:October-2025
ceos:September-2025-v3
ceos:September-2025-v2
ceos:August-2025-v2
ceos:August-2025
ceos:July-2025
ceos:June-2025
ceos:May-2025
ceos:2025-03
ceos:2025-02-v2
ceos:2025-02
ceos:2025-01
ceos:December-2024
ceos:November-2024
ceos:October-2024
ceos:September-2024
ceos:August-2024
ceos:July-Llama-2024
ceos:July-Mistral-2024
ceos:July-2024
Sign in to create a new pull request.
33 commits
main
...
studio-san
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ea05945070 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
7a8c07f216 |
studio/sandbox: close 4 bypass classes from round-7 audit
Round-7 sonnet-panel review found four more concrete bypass
classes. All four are now closed (670 tests passing, 41 new R7
regression tests):
1. Deep path traversal through home prefix. ``~/foo/../../etc/shadow``,
``~/a/b/c/../../../../etc/shadow``, and chains where a regular
segment precedes the ``..`` run slipped because the previous
escape check only fired when the tail STARTED with ``..``.
``_tail_escapes_home`` now walks the tail with a depth counter
and returns true as soon as depth goes negative, matching the
runtime resolve when HOME is a single-segment path like
``/root``.
2. Brace false-positive for benign user-data listings.
``cat ~/data/{maps,routes}`` and ``cat /home/u/{maps,docs}/file``
were blocked because the single unscoped brace regex matched
``maps`` regardless of root. The defence is now split per root:
``_HOME_BRACE_RE`` (home credentials), ``_ETC_BRACE_RE``
(/etc), ``_PROC_BRACE_RE`` (per-process state names like
``maps`` / ``mem`` / ``environ`` only fire here), and
``_VAR_SPOOL_BRACE_RE`` (cron). The proc / cron generic names
no longer fire on home or local paths.
3. BinOp.Add depth cap. ``open('/' + 'e' + 't' + 'c' + ...)``
chains over ~63 operands hit the 64-level recursion cap in
``_extract_string_from_node`` and resolved to ``None``, so
the sensitive literal escaped detection. Both
``_extract_string_from_node`` and ``_extract_string_literal``
now flatten left-leaning ``+`` chains iteratively in one
pass, so arbitrarily long concatenations resolve.
4. NetworkAndIoVisitor module rebinding. ``import shutil as sh``
was tracked, but the plain ``import shutil; sh = shutil``
(a Name = Name assignment) was not, so
``sh.copytree('~/.ssh', dst)`` slipped past the
``NetworkAndIoVisitor`` shutil-copy gate. A new
``visit_Assign`` propagates pathlib, shutil, builtins, and
``pathlib.Path`` class aliases across rebinding, mirroring
``SignalEscapeVisitor.visit_Assign`` so the two visitors are
independently correct regardless of execution order.
Cumulative bypass closures across rounds 1 through 7: 28
distinct classes, 670 regression tests, three-OS green.
|
||
|
|
c7c2e70559 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
eae716675b |
studio/sandbox: close 7 bypass classes from cross-reviewer round-6 audit
Round-6 sonnet-panel review surfaced seven more concrete bypass
classes. All seven are now closed (629 tests passing, 60 new R6
regression tests):
1. Path traversal under home prefix. `~/../etc/shadow`,
`~root/../etc/shadow`, `~ubuntu/../../etc/shadow`, and
`/home/u/../u/.aws/credentials` all slipped because
`_normalize_path_separators` re-attached the home prefix even
when `..` had escaped it. Now when the tail of a home-prefixed
path begins with `..`, the projection is treated as absolute
(mirroring the runtime resolve when HOME is a single-segment path
like `/root`). POSIX `~<user>/` tilde-user expansion is
handled the same way.
2. Pandas / numpy reader keyword arguments. `pd.read_csv(filepath_or_buffer='/etc/shadow')`,
`pd.read_excel(io=...)`, `np.fromfile(fname=...)` used the actual
API parameter names that the previous gate's `{"file", "path"}`
kwarg list missed. The kwarg set is expanded to cover
`filepath_or_buffer`, `path_or_buf`, `fname`, `filename`, `io`,
`buf`, `source`, `src` and a few common variants.
3. Bash directory exfil verbs. `cp -r ~/.ssh /tmp/out`, `mv ~/.aws /tmp`,
`tar czf out.tar.gz ~/.ssh`, `rsync -av ~/.aws/ /tmp/`,
`zip -r out.zip ~/.ssh` previously slipped because
`_find_sensitive_paths` only flagged named files, leaving the
bash side asymmetric to the Python shutil dir-exfil gate. A new
`_BASH_DIR_EXFIL_RE` matches dir-copy verbs (`cp`, `mv`, `rsync`,
`tar`, `zip`, `7z`, `scp`, `sftp`, `xz`) followed by a sensitive
directory. `ls ~/.ssh` and `find ~/.aws -type f` stay allowed.
4. Inner-tree alias walk for eval / exec. `exec("import shutil as sh\nsh.copytree('~/.ssh', dst)")`
slipped because the inner AST visit did not re-run the
alias-tracking pre-pass that built `shutil_module_aliases`.
Extracted both pre-pass loops into helpers (`_run_alias_prepass`,
already had `_run_string_binding_prepass`) and call both on each
literal eval / exec payload before the visitor recurses.
5. Chained assignment. `a = b = '/etc/shadow'; open(a).read()`
slipped because the binding pre-pass only handled
`len(targets) == 1`. Multi-target Assign nodes now bind every
Name target to the resolved value.
6. Annotated assignment. `path: str = '/etc/shadow'; open(path)`
slipped because the binding pre-pass walked `ast.Assign` but
not `ast.AnnAssign`. Same-shape handler for single Name target.
7. Brace-bomb empty-alt bypass. `cat ~/{,x0,...,x341}/{.ssh/id_rsa,other}`
exhausts the expansion cap before the empty alt's second-brace
projection reaches `~/.ssh/id_rsa`. A defensive
`_SENSITIVE_IN_BRACE_RE` catches sensitive-name fragments inside
an unexpanded brace group attached to a sensitive root,
regardless of whether the brace expansion completed. Anchored
with `(?<=[,{/])` lookbehind and `(?=,|\}|/)` lookahead so
project-local lookalikes (`./workspace/home/u/{a,b}/...`) stay
allowed via the `_PATH_TOKEN_START` boundary.
NetworkAndIoVisitor inner-tree pre-pass. The visitor eval / exec
recursion now mirrors SignalEscapeVisitor's call to both
`_run_alias_prepass` and `_run_string_binding_prepass` so it is
independently correct regardless of visitor execution order.
Cumulative bypass closures across rounds 1 through 6: 24 distinct
classes, 629 regression tests, three-OS green.
|
||
|
|
178bcf70d1 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
5eb06e4bfe |
studio/sandbox: close Subscript + UDP/connect_ex metadata bypasses
Two more from the follow-up list closed (569 tests passing):
1. ``ast.Subscript`` resolution. ``open(['/etc/shadow'][0])`` and
``open({'k': '/etc/shadow'}['k'])`` previously slipped because
``_extract_string_from_node`` had no Subscript handler. List /
tuple / dict subscripts are now resolved: when the index is a
static constant we return the indexed value; otherwise any
sensitive entry in the container surfaces so the gate fires.
Indexes outside the container's static range fall back to
sensitive-scan + first-resolvable so adversarial patterns like
``open(['safe.txt', '/etc/shadow'][i])`` are still blocked.
2. UDP / ``connect_ex`` metadata destination. The connect-only
``NetworkAndIoVisitor`` gate missed ``s.sendto(data, address)`` /
``s.sendmsg(buffers, ancdata, flags, address)`` (the destination
tuple is positional but not at index 0) and ``s.connect_ex(addr)``
(non-raising connect variant). The visitor now matches the full
``{connect, connect_ex, sendto, sendmsg}`` set and scans every
positional arg for a ``(host, port)`` tuple shape; the first
resolved host wins.
17 new regression tests cover the Subscript class (8 blocked, 3
allowed) and the UDP / connect_ex class (4 blocked, 2 allowed).
After this commit, ``bypass_hunt.py`` reports zero NEW bypasses;
the only remaining ALLOWs are the documented follow-up list
(``getattr(__builtins__, ...)``, ``vars(__builtins__)[...]``,
``base64.b64decode`` of paths, ``chr()`` / ``str.join`` concat,
trusted-host upload-shape evasion).
|
||
|
|
2bf12cd89b |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
e400dac77d |
studio/sandbox: close bash glob and ternary IfExp bypasses
Two final bypass classes from the round-5 follow-up list are now
closed (552 tests passing):
1. Bash glob under a sensitive root. ``cat /etc/sha*ow``, ``cat
/etc/sh?dow``, ``cat /etc/*``, ``cat ~/.ssh/id_*`` -- the shell
expands ``*`` / ``?`` against the filesystem at runtime, so the
literal-path scan never sees ``/etc/shadow``. A new
``_SENSITIVE_ROOT_WITH_GLOB_RE`` mirrors the existing
``_SENSITIVE_ROOT_WITH_EXPANSION_RE`` (which gates ``$(...)`` /
backtick substitutions) for the ``*`` / ``?`` family. The
``[^\s'\";&|`$]*`` literal-text-only constraint keeps the match
attached to the sensitive root token, so ``find /etc/ -name
'*.conf'`` (whitespace between root and glob) and project-local
globs like ``./src/*.py`` stay allowed.
2. Ternary ``IfExp`` branches. ``open('/etc/shadow' if cond else
'data.txt')`` previously slipped because
``_extract_string_from_node`` had no ``ast.IfExp`` handler.
Either branch can execute at runtime; the gate now resolves both
branches and prefers the sensitive one (via the same
``_looks_sensitive`` check that backs the binding-bias) so the
downstream check fires. Falls back to whichever branch resolved
when neither is sensitive.
24 new regression tests cover the glob class (10 blocked, 6 allowed)
and ternary (6 blocked, 2 allowed).
|
||
|
|
115810eae3 |
studio/sandbox: include /etc/passwd in pre-pass binding bias
_find_sensitive_paths does not match /etc/passwd (it lives in the open-call gate's _SENSITIVE_FILE_PREFIXES list, not in _ABSOLUTE_SENSITIVE), so a chained reassign p='/etc/hosts'; p='/etc/passwd'; open(p) kept /etc/hosts as the representative and slipped through. Duplicate the open-call prefix list in the pre-pass scope so _looks_sensitive catches /etc/passwd and the analogous /proc/<pid> reads too. |
||
|
|
35d7b72832 |
studio/sandbox: use _find_sensitive_paths for binding-bias instead of substring
Refines the round-5 ``_looks_sensitive`` heuristic that biases
``_record_string_binding`` toward the dangerous value in a chained
reassignment. The substring hint set conflated ``/etc/shadow`` with
``/etc/hosts`` -- both contain ``/etc/`` -- so a payload like
``p = '/etc/hosts'; p = '/etc/shadow'; open(p)`` had ``cur`` already
flagged sensitive, the guard refused to update, and the resolved
value stayed at ``/etc/hosts`` (allow-listed). The chained shadow
binding then slipped through.
Now ``_looks_sensitive`` delegates to ``_find_sensitive_paths``, the
authoritative bash / file gate matcher, so the distinction is exact:
``/etc/hosts`` is allow-listed and ``/etc/shadow`` is sensitive.
``_record_string_binding`` also adopts a clean three-way rule mirroring
Python's last-wins semantics for sensitive values:
* New sensitive value: always wins (covers the chained shadow case).
* New benign value, current sensitive: keep current (static gate
cannot prove the new value executes; err on blocking).
* Both benign: latest seen wins.
Test suite still 528 passing.
|
||
|
|
b038848482 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
17739721da |
studio/sandbox: close 7 bypass classes from cross-reviewer round-5 audit
Sonnet-panel review of round-4 surfaced seven concrete bypass classes
in the static gate. All seven are now closed (528 tests passing, 55
new R4 / R5 regression tests):
1. ``os.path.join`` alias bypasses. ``import os as o; o.path.join(...)``,
``from os.path import join`` (and ``as j``), ``from os import path``
(and ``as op``), ``import posixpath as pp``, ``from posixpath import
join`` -- previously the FQ match was literal-only (`os.path.join`,
`posixpath.join`, `ntpath.join`). A pre-pass walk collects every
alias of ``os`` / ``os.path`` / ``posixpath`` / ``ntpath`` and every
from-import of ``join`` / ``expanduser``; the resolver checks
``<alias>.join`` and bare aliased names too.
2. ``shutil`` alias bypasses. ``import shutil as sh; sh.copy(...)``,
``from shutil import copyfile``, ``from shutil import move as mv``,
etc. -- the file-copy gate matched only the literal ``shutil.X`` FQ.
The pre-pass now tracks shutil module aliases and from-import
aliases for ``copyfile`` / ``copy`` / ``copy2`` / ``copytree`` /
``move``; the gate canonicalises any matched alias to ``shutil.X``
so the error message identifies the operation.
3. First-assignment-wins binding bypass. ``p = '/tmp/safe'; p =
'/etc/shadow'; open(p)`` previously slipped because the pre-pass
guard ``_target.id not in string_bindings`` ignored every
reassignment, and the AST walk picked the safe value while Python
uses last-wins at runtime. New ``string_bindings_all`` tracks every
literal ever bound to a name; ``_record_string_binding`` biases the
representative value toward sensitive-shaped paths via a substring
hint set covering the credential / process-state root tokens. The
reverse order (``shadow`` then ``safe``) is also caught.
4. Brace-expansion off-by-one. ``cat ~/.aws/{x0,...,x62,credentials}``
exploited that ``_expand_brace_projections`` started with
``out = {original}`` (1 item) so a cap of 64 only left 63
alternative slots. The inner loop also broke per-alternative on
the cap, so the sensitive name at position 64+ was never reached.
Raised the cap to 1024 and the inner loop now expands all
alternatives of a brace in one pass before the outer cap can stop
the queue.
5. ``thread-self`` in shell-expansion regex. ``cat /proc/thread-self/
$(echo environ)`` was missed because ``_SENSITIVE_ROOT_WITH_EXPANSION_RE``
only listed ``self|\d+`` in the ``/proc/...`` alternation, while
``_ABSOLUTE_SENSITIVE`` correctly included ``thread-self``. One
alternation entry restores symmetry.
6. Eval / exec pre-pass not re-run. ``exec("p='/etc/shadow'\nopen(p)")``
slipped because the inner AST visit ran without the string-binding
pre-pass. Extracted the pre-pass into ``_run_string_binding_prepass``
and call it on each inner literal payload before the visitor
recurses, so payload-local variable assignments are visible.
7. Pathlib name binding pre-pass. ``p = Path('/etc/shadow');
p.read_text()`` slipped because the pre-pass only resolved string
literals -- pathlib constructor calls returned None and the bound
name remained unresolved. Pre-pass now falls back to
``_extract_pathlib_target`` using per-tree alias sets so
``import pathlib as pl; p = pl.Path(...)`` and ``from pathlib import
Path as P; p = P(...)`` both resolve. ``NamedExpr`` (walrus) is also
surfaced by the pre-pass so walrus-inside-eval expressions are
visible.
Pre-pass call order. The initial pre-pass invocation moves to AFTER
``_extract_pathlib_target`` is defined so the closure cell binds
correctly (Python looks up free variables in the enclosing scope at
CALL time, not at function-definition time).
Full sandbox suite: 528 passed (455 prior + 73 R4 / R5 regression tests).
|
||
|
|
a6400ffc07 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
02e9e4867d |
studio/sandbox: close round-4 bypass classes (aliasing, FileIO, walrus, copytree)
Closes additional bypass classes surfaced while exercising the gate:
1. Module / function aliasing (`m = os; m.system(...)`,
`p = os.popen; p(...)`): `visit_Assign` now propagates the source
alias when one tracked-module name is bound to another, and tracks
bound method references into `shell_exec_aliases`. Previously only
`m = __import__('os')` was handled.
2. Importlib from-alias (`from importlib import import_module as IM;
IM('os').system(...)`): a new visitor-scope `import_module_aliases`
set plus a `_resolve_dynamic_module` wrapper recognises the
bound name in both inline-call and bound-name forms.
3. Shutil directory exfil (`shutil.copytree('~/.ssh', dst)`):
`_matches_sensitive_dir()` adds a directory-only matcher used by
the file-copy gate only. The boundary `(?=/?$|/?[\s'\";&|)<>])`
matches the path AS the directory but NOT a single file inside it,
so per-file allow-listed reads (`~/.ssh/known_hosts`, `~/.ssh/id_rsa.pub`)
still pass. Covers `.ssh`, `.aws`, `.config/gcloud`, `.gnupg`,
`.docker`, `.kube`, `.password-store`, plus `/etc`, `/etc/ssh`,
`/var/spool/cron`, `/proc/<pid>`.
4. Explicit-reader / aliased file readers (`io.FileIO('/etc/shadow')`,
`codecs.open('/etc/shadow')`, `from io import FileIO; FileIO(...)`):
the open-call detector now recognises these qualified forms and
the visitor tracks `from io|codecs import FileIO|open` aliases.
5. Bytes-literal paths (`open(b'/etc/shadow')`) and walrus
expressions (`open((p := '/etc/shadow'))`): `_extract_string_literal`
and `_extract_string_from_node` resolve `bytes` Constants via strict
UTF-8 decode and `NamedExpr` via RHS extraction (recording the
binding so later uses of the walrus target resolve too).
6. Tuple / list unpacking destructuring (`(a, b) = ('/etc', 'shadow');
open(a + '/' + b)` and `p, = ['/etc/shadow']; open(p)`): the
string-binding pre-pass now folds matched-length Tuple/List
destructurings element-wise.
7. Pandas / numpy file readers (`pd.read_csv('/etc/shadow')`,
`np.fromfile('/etc/shadow')`, etc.): suffix-match the common
reader method names so any alias of the source module flows
through the same sensitive-path gate as `open()`.
91 new regression tests cover each class, both blocked and legitimate
allow-list cases. Full sandbox suite: 473 passed.
|
||
|
|
60e0f5056e |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
d64c2a10d4 |
studio/sandbox: close dynamic-import + /proc/self symlink bypasses
Closes two static-bypass classes flagged during round-3 review:
1. __import__('os').system(...) / importlib.import_module('os').popen(...)
bypassed the bare os.system / subprocess.* gate because the receiver
was an ast.Call rather than an ast.Name in os_aliases. Adds
_resolve_dynamic_module_name() so:
* inline __import__('os').system(...)
* inline importlib.import_module('os').system(...)
* import importlib; mod = importlib.import_module('os'); mod.popen(...)
* m = __import__('subprocess'); m.run([...], shell=True)
all flow through the same shell-escape detection as
import os; os.system(...). Legit dynamic imports of safe modules
(json, pathlib, ...) remain allowed.
2. /proc/<pid>/cwd and /proc/<pid>/root are symlinks to the process
working directory and the filesystem root. The form
open(/proc/self/cwd/../../etc/shadow) bypassed
_normalize_path_separators because .. was collapsed against the
literal path, not the symlinked target. The form
open(/proc/self/root/etc/shadow) bypassed any chroot-style
defence. Adds matching entries to _ABSOLUTE_SENSITIVE so the bash
gate and the AST open() gate both block any access via these
symlink prefixes. Legitimate /proc/self/status etc. introspection
still flows.
Tests:
TestFollowup_DynamicImportShellEscape (2 cases, 10 parametrised)
TestFollowup_ProcSelfSymlinkTraversal (3 cases, 16 parametrised)
pytest studio/backend/tests/test_sandbox_hardening.py -q
-> 382 passed in 0.67s (was 356).
|
||
|
|
f2bbe27cde |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
5b0735308a |
Merge branch 'studio-sandbox-hardening' of https://github.com/unslothai/unsloth into studio-sandbox-hardening
# Conflicts: # studio/backend/core/inference/tools.py |
||
|
|
8176694d94 |
studio: address round-3 sandbox review findings
Round-4 follow-up on the hardening PR after a third 20-reviewer pass.
Closes the high-impact items from that review while preserving the
"do not regress legitimate tool calling" floor; lower-vote items that
would have measurable regression on legit code paths (broad shell
glob ?/*, $VAR in dynamic paths, ANSI-C $'...') are intentionally
deferred.
Parent-directory traversal: _normalize_path_separators now follows
.. segments through posixpath.normpath and reattaches the tilde or
${HOME} prefix, so cat /etc/apt/../shadow and
Path('/proc/self/fd/../environ').read_text() both reach the
canonical regex.
Built-in open() accepts PathLike: open(Path('/etc/shadow')) and
open(file=Path('/etc/shadow')) now flow through the pathlib resolver
the same way receiver reads do.
Pathlib home and transforms: Path.home() resolves to ~ so
(Path.home() / '.aws/credentials') hits the home regex;
.expanduser() / .resolve() / .absolute() are pass-throughs.
Pathlib semantics: _join_path_parts() now matches pathlib's
absolute-segment reset so Path('/tmp') / '/etc/shadow' resolves to
/etc/shadow as it does at runtime.
from builtins import exec as e: tracked in both visitors via
eval_exec_aliases so the aliased call still routes through the
literal-payload recursion.
Process state extensions: /proc/self/cmdline,
/proc/thread-self/*, and /proc/<pid>/task/<tid>/* are added to
_ABSOLUTE_SENSITIVE.
Numeric f-strings: f'/proc/{1}/environ' folds to a literal because
numeric ast.Constant values inside ast.FormattedValue are now
stringified.
os.path.join / os.path.expanduser: resolved statically by
_extract_string_from_node so the stdlib-helper construction paths
do not hide sensitive targets.
Variable assignment tracking: a pre-pass collects ``name = literal``
and ``name = eval`` / ``name = exec`` bindings; the visitors and the
pathlib resolver consult those bindings. The trusted-host gate
intentionally uses a separate strict literal extractor so legit
patterns like ``url = some_input; requests.get(url)`` still pass.
shutil.copyfile / copy / copy2 / copytree / move: the source argument
is gated the same way open() is, blocking file-copy exfil.
Concrete pathlib classes: PosixPath / WindowsPath / PurePath / etc.
are registered in path_aliases by default.
requests.request positional+keyword: for URL-second APIs, args[0] is
the HTTP method (not the URL); when there is only one positional, the
URL extraction falls through to the url= keyword instead of grabbing
the method.
Tests grow from 281 to 357 hardening cases; combined sweep 487 / 487.
Every fix has positive and negative coverage; legit tool calls
(open(Path('data.csv')), os.path.join('logs', 'today.log'),
url = some_input; requests.get(url), shutil.copyfile('a.txt', 'b.txt'))
continue to pass.
|
||
|
|
f2809221d4 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
7a0bacdba8 |
studio: address round-2 sandbox review findings
Round-3 follow-up on the same hardening PR after a second 20-reviewer
pass. Every change is detection-widening; legitimate tool calls remain
allowed.
Pathlib readers (Path.open, Path.read_text, Path.read_bytes) now share
one extraction path. The new _extract_pathlib_target helper resolves
Path(a), Path(a, b, ...), Path(...).joinpath(b), and Path(...) / b
through statically-resolvable string parts. NetworkAndIoVisitor tracks
Path aliases (from pathlib import Path as P) and pathlib module aliases
(import pathlib as pl) so the aliased forms hit the same gate. For
receiver-side reads the path is taken exclusively from the receiver --
Path('/etc/shadow').open('r') no longer mis-reads the mode flag as a
path.
The credential-path regex set now matches the POSIX ~user/ expansion
(cat ~ubuntu/.aws/credentials), and the SSH private-key end anchor
includes > so that redirect-attached forms (cat ~/.ssh/id_rsa>... )
are not split-tokenised through the gate. A new
_SENSITIVE_ROOT_WITH_EXPANSION_RE detects sensitive root prefixes
followed by $(...) or backtick substitution, and _find_sensitive_paths
now enumerates bash brace expansion {a,b} plus small glob char classes,
and runs every projection through path-separator normalisation that
collapses // and /./.
Network host validation reaches keyword arguments (url=, host=,
hostname=, address=), host-first APIs whose first positional arg is the
host (socket.create_connection, socket.getaddrinfo,
http.client.HTTPConnection, http.client.HTTPSConnection), and the
url-second APIs (requests.request, httpx.request).
builtins.exec, builtins.eval, and __builtins__.eval flow through the
same literal-payload recursion as the bare forms, including aliased
import builtins as b. open(file=...) and io.open(file=...) keyword
forms are gated alongside the positional form, and the open() path
candidates run through both backslash normalisation and the
//-collapse projection so equivalent spellings (/etc//shadow,
/etc/./shadow) cannot bypass.
Tests grow from 205 to 281 hardening cases (TestR2Finding1 through
TestR2Finding16) and from 131 + 205 = 336 to 131 + 281 = 412 in the
local sweep. Negative cases for every fix continue to ensure
legitimate tool use (Path('data.csv').open(), open(file='logs/today.log'),
requests.get(url='https://wikipedia.org/'), find src/, etc.) stays
allowed.
|
||
|
|
e598ebf1d0 | Merge remote-tracking branch 'origin/main' into studio-sandbox-hardening | ||
|
|
eda3be4101 | Merge branch 'studio-sandbox-hardening' of https://github.com/unslothai/unsloth into studio-sandbox-hardening | ||
|
|
8fd57530d1 |
studio: always use POSIX shlex for sensitive-path dequote
On Windows runners shlex.split(posix=False) leaves splice quotes in place, so cat /etc/sha''dow tokenises to ['cat', "/etc/sha''dow"] and the dequoted scan projection still misses the credential. The threat model is POSIX-shell quote splicing in either bash invoked on Windows or POSIX shells on Linux/macOS; the dequote always wants POSIX semantics. Pre-normalise backslashes so Windows drive paths survive POSIX shlex's escape handling. |
||
|
|
40d60b05c5 |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
e06126933e |
Merge branch 'studio-sandbox-hardening' of https://github.com/unslothai/unsloth into studio-sandbox-hardening
# Conflicts: # studio/backend/core/inference/tools.py |
||
|
|
2ae885ce72 |
studio: address sandbox hardening review findings
Round-2 fixes for ten issues surfaced by a 20-reviewer code review of
the initial hardening patches. Every change is detection-widening or a
false-positive narrowing; legitimate tool calls keep working.
Direct Python open now flows through _find_sensitive_paths so
open('/home/u/.aws/credentials').read() is gated the same as
os.system('cat ~/.aws/credentials'). The previous wiring covered only
the bash and shell-exec sides.
Both SignalEscapeVisitor and NetworkAndIoVisitor fail-closed once the
eval / exec literal recursion cap is reached. Wrapping a payload in
four or more nested literal exec layers no longer silently bypasses
inspection.
_find_sensitive_paths scans three projections of the command (raw,
backslash-normalised, shlex-dequoted) and recurses into nested
bash -c and cmd /c shells. Quote-spliced and Windows-backslash forms
of credential paths are all caught.
_HOME_PREFIX_RE adds Windows-style home prefixes (USERPROFILE,
HOMEDRIVE HOMEPATH, env:USERPROFILE, drive-letter Users) so cross-OS
hardening actually applies on Windows. Both sensitive-path regexes
now have a path-token start anchor so project-local lookalike paths
under workspace, fixtures, and tmp are not blocked.
Network host validation for sock.connect and the requests / urllib
FQ-prefix branch now use _extract_string_from_node instead of raw
ast.Constant checks, so concatenated and f-string literal hosts
resolve the same way the open gate already did.
pathlib.Path('/etc/shadow').open() is now inspected; the path is
extracted from the receiver constructor when node.args is empty.
The static-string resolver depth cap moves from 6 to 64, removing the
single-character literal-concat bypass while leaving the recursion
well inside CPython's default frame limit.
The SSH private-key regex gains a filename-end boundary so reading a
public ".pub" key stays allowed (legit developer action) while the
matching private key is still denied.
New regression tests cover one class per finding (TestFinding1 through
TestFinding10) plus updated nested-depth coverage; the previous
test_nested_depth_does_not_crash assertion was inverted by the
fail-closed change and has been replaced. Local sweep: 336 passed
(131 upstream + 205 hardening).
|
||
|
|
6efb0f64ea | Merge remote-tracking branch 'origin/main' into studio-sandbox-hardening | ||
|
|
829698280a |
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci |
||
|
|
8a5080f26b |
studio: regression tests for sandbox hardening patches A / B / D
124 tests across 7 classes:
* TestPatchA_DynamicPaths — open() with concatenated literals + f-strings.
Pins 7 attack patterns BLOCKED, 6 legitimate dynamic paths ALLOWED,
12-level deep concat doesn't crash.
* TestPatchB_FindSensitivePathsHomeAnchored — ~/.ssh/id_*, ~/.aws/,
~/.docker/, ~/.kube/, ~/.pypirc/.npmrc, ~/.netrc, ~/.password-store,
~/.gnupg/private-keys-v1.d across ~, $HOME, /home/<u>, /root,
/Users/<u>. Pins 21 attack paths BLOCKED, 15 legitimate paths
(~/.gitconfig, ~/.bashrc, ~/.ssh/{config,known_hosts}, ~/.npm,
project-local rc files, /tmp/.npmrc) ALLOWED.
* TestPatchB_FindSensitivePathsAbsolute — /etc/shadow, /etc/sudoers,
/etc/ssh/ssh_host_*, /proc/{self,<pid>}/{environ,mem,maps,auxv},
/proc/kcore, /proc/kallsyms, /var/spool/cron/. Pins 12 attacks
BLOCKED, 11 legit paths (/etc/hosts, /etc/resolv.conf, /proc/cpuinfo,
/proc/meminfo, …) ALLOWED.
* TestPatchB_PythonShellExec — same surface flows through os.system /
subprocess.run. 6 attacks BLOCKED, 11 legitimate tool-calls ALLOWED.
* TestPatchD_EvalExecLiteralPayload — exec/eval with a literal payload
parsed and re-checked. 5 attack payloads BLOCKED, 6 legit
expressions (eval('1+2'), exec('print("hi")'), nested innocuous
exec) ALLOWED.
* TestPatchD_EvalExecDynamicPayload — non-literal eval/exec args
flagged as dynamic shell escape. 4 patterns BLOCKED.
* TestPatchD_NestedDepthCap — 10-level nested exec(exec(...)) caps
at depth 3, doesn't crash, doesn't false-positive.
* TestCrossCuttingNoRegression — 6 pre-existing BLOCK patterns still
fire (sudo, signal tampering, /etc/passwd literal, untrusted host,
metadata host); 7 pre-existing ALLOW patterns still pass (print,
json.loads, trusted host, dataclass, legitimate open()).
Result on the rebuilt scaffold:
131/131 pre-existing tests in test_sandbox_tools.py pass
124/124 new hardening tests pass
255/255 combined, zero regressions
The "must remain ALLOWED" cases form the non-regression floor that
prevents the patches from making LLM tool calling dumber.
|
||
|
|
6984fa8d7c |
studio: recurse into eval / exec literal payloads (Patch D)
The AST gate previously had no special handling of eval() / exec(),
so a literal payload would slip past every detector:
exec("import os; os.system('sudo whoami')") # ALLOWED before
exec("open('/etc/shadow').read()") # ALLOWED before
eval("__import__('blocked_mod').dangerous()") # still allowed (chained-call gap)
payload = '...'; exec(payload) # ALLOWED before
Both visitors (SignalEscapeVisitor and NetworkAndIoVisitor) now share
the same gate at the top of visit_Call: when the call is bare-name
eval / exec, try to resolve the first argument via the shared
_extract_string_from_node helper (Patch A); if it resolves, parse it
and recursively visit so every existing detector runs on the inner
code — signal tampering, shell escape, sensitive-file open, network
policy, upload denylist, etc.
When the payload is not statically resolvable, SignalEscapeVisitor
appends a `shell_escape_dynamic` finding — eval/exec of runtime data
is the textbook code-injection vector and there is no legitimate LLM
tool-call reason to dynamically eval an external string. Static
literals (eval('1 + 2'), exec('x = 1\\ny = 2')) are unchanged because
the recursive visit only flags what the rest of the AST gate would
already flag at top level.
Each visitor caps recursion at depth 3 (own counter on the instance)
so adversarial nested eval('eval(...)') cannot blow the stack.
Closes gaps #7, #8 (partial), #11 (partial) from the 13-gap audit.
Out-of-scope chained-call cases (__import__('os').system(...),
getattr(os, 'sys'+'tem')()) stay documented gaps — the OS sandbox is
the intended backstop, see PR 5468.
Regression: 131/131 studio/backend/tests/test_sandbox_tools.py pass.
Legitimate eval/exec on literal expressions (eval('1+2'),
exec('print("hi")'), exec('exec("print(1)")')) verified ALLOWED.
|
||
|
|
2965cd8310 |
studio: gate credential / process-state paths in bash and Python (Patch B)
Adds _find_sensitive_paths() and wires it into _bash_exec (alongside the
existing _find_blocked_commands check) and into _check_args_for_blocked
(so the Python AST gate catches os.system('cat ~/.ssh/id_rsa') the same
way bash $ cat ~/.ssh/id_rsa is caught).
The pattern set is intentionally narrow — only clear-cut credential and
process-state targets:
Home-anchored (must be prefixed by ~, $HOME, ${HOME}, /home/<u>,
/root, /Users/<u>):
.ssh/id_rsa, .ssh/id_ed25519, .ssh/id_ecdsa, .ssh/id_dsa, .ssh/identity
.aws/credentials, .docker/config.json, .kube/config
.config/gcloud/{application_default_credentials,access_tokens,credentials}
.pypirc, .npmrc, .cargo/credentials
.netrc, .password-store, .gnupg/private-keys-v1.d
Absolute system targets (match anywhere):
/etc/shadow, /etc/sudoers, /etc/ssh/ssh_host_*
/proc/{self,<pid>}/{environ,mem,maps,auxv}
/proc/kcore, /proc/kallsyms
/var/spool/cron/
The home-anchored category uses a regex that requires a HOME-equivalent
prefix, so project-local rc files like ./project/.npmrc remain readable
while ~/.npmrc is denied. Legitimate LLM-developer-tool paths
(~/.gitconfig, ~/.bashrc, ~/.ssh/config, ~/.ssh/known_hosts, /etc/hosts,
~/.cache/, ~/.bash_history, project rc files) are intentionally NOT in
the list and still flow through unchanged.
Closes gaps #1, #2, #3, #12, #13 from the documented 13-gap audit.
Regression sweep:
* 131/131 studio/backend/tests/test_sandbox_tools.py pass
* 24 legitimate-use cases verified ALLOWED
* 17 attack patterns verified BLOCKED
|
||
|
|
3e4704a856 |
studio: resolve concatenated + f-string paths in sensitive-file gate (Patch A)
Static-string resolution in _extract_string_from_node was limited to bare
ast.Constant. Concatenated string literals and f-strings with constant
parts evaluated to ast.BinOp / ast.JoinedStr and slipped past the
open() sensitive-file check, so:
open('/etc/' + 'shadow') # ALLOWED before
open(f'/etc/{"shadow"}') # ALLOWED before
open('/etc/passwd') # BLOCKED before (literal)
The helper now resolves ast.BinOp(Add) of two resolvable strings and
ast.JoinedStr whose parts are themselves resolvable. The open()
sensitive-file check uses the helper instead of an inline ast.Constant
isinstance check, so the same widening covers concatenated/f-string
paths without changing what was already blocked.
Resolution is depth-capped at 6 to keep adversarial deep nesting from
blowing the stack. All other call sites of the helper
(_check_args_for_blocked, dynamic-arg shell-escape detection, HF upload
path-shape inspection) automatically inherit the broader resolution.
Closes open() gaps #4 and #6 from the documented 13-gap audit. Does not
attempt to model variable flow (gap #5 stays open by design — the OS
sandbox is the right layer for runtime flow).
Regression: 131/131 studio/backend/tests/test_sandbox_tools.py pass.
|
2 changed files with 4455 additions and 33 deletions
File diff suppressed because it is too large
Load diff
2417
studio/backend/tests/test_sandbox_hardening.py
Normal file
2417
studio/backend/tests/test_sandbox_hardening.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue