Spaces:
Sleeping
Sleeping
Commit History
-
feat: wire frontend to real API, ship plots, multi-stage Docker build
Frontend (React + Vite) - Add to git (was untracked); .gitignore excludes node_modules/ and dist/ - App.jsx now calls real backend endpoints: - GET /api/attack-types → populates attack-type grid - GET /api/stats → drives hero badges (real numbers, no claims) - GET /api/highlight → hero animation payload preview - POST /api/attack → fetches the real trace JSON - timeline events from the trace drive the pipeline animation - outcome.broke_pg2 / broke_fw / task_succeeded / blocked_at drive the success / failure card (no more hardcoded "300 steps = success") - Plot dashboard now renders /plots/*.png from the FastAPI server (with a stats summary card backed by /api/stats) - vite.config.js: dev proxy to :7860 for /api, /plots, /health Backend - env/server.py: serves frontend/dist/ when present (StaticFiles with html=True for SPA + an /assets mount for Vite chunks); falls back to source dir or JSON index when the frontend hasn't been built Docker - Mu…5cceafb -
feat: HF Space replay backend — trace store, /api endpoints, Docker, Cell 9
- env/replay.py: TraceStore loads pre-recorded JSON traces from data/traces/ - env/server.py: /api/attack-types, /api/attack, /api/stream/{type}/{steps}, /api/highlight, /api/stats; static frontend mount; INJECTARENA_MODE switch - Dockerfile: switch CMD to uvicorn env.server:app, set INJECTARENA_MODE=replay - README.md: HF Space frontmatter (sdk: docker, app_port: 7860) - scripts/generate_traces.py: runs trained attacker against scenarios on Colab, captures stage-by-stage timeline and outcomes into JSON traces - notebooks: Cell 9 to invoke the trace generator and push results to GitHub Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>8c536e6 -
fix: use huggingface_hub.login() before LoRA download to fix 401
Passing token= to snapshot_download is unreliable for gated repos — calling huggingface_hub.login() sets the auth state globally, which is what the hub library checks when deciding whether to send the token with each file request. Also checks HUGGING_FACE_HUB_TOKEN as a fallback env var and logs a warning when no token is found. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>013046f -
fix: pre-download SecAlign LoRA before vLLM init to avoid 401 in subprocess
vLLM's EngineCore runs in a separate process and does not reliably inherit HF_TOKEN from the parent. Passing 'facebook/Meta-SecAlign-8B' as the lora_path caused a GatedRepoError (401) at first inference, crashing the engine and returning reward=0 for every step. Fix: call huggingface_hub.snapshot_download() in the parent process (where HF_TOKEN is set) before starting vLLM, then pass the local cache path to LoRARequest. vLLM receives a local directory and never needs to authenticate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b5c4619 -
fix: dtype kwarg (torch_dtype deprecated), vLLM max_model_len=4096
- grpo_train: torch_dtype → dtype (transformers 4.45+ renamed it) - secalign_agent: add max_model_len=4096 to vLLM LLM() init; vLLM was trying to allocate KV cache for full 131072-token context (16 GiB) but only 5.4 GiB is free after Qwen bf16 occupies ~3 GiB. With max_model_len=4096 the KV cache drops to ~500 MB — fits easily. SecAlign agent tasks never need more than 4096 tokens. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>aaa7c61 -
fix: max_completion_length 512→128, firewall circuit-breaker
- max_completion_length 512→128: completions/clipped_ratio was 1.0 on every step (all payloads truncated). 128 tokens is enough for any injection payload and cuts per-step generation time ~4x. - FirewallWrapper: convert _scan_user from @staticmethod to instance method; add _fw_user_broken circuit-breaker so after the first llamafirewall scan error the fallback to PG2 is silent for the rest of the session (was logging on every step, ~10+ times per training step). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b7d3a14 -
fix: skip Unsloth in GRPO trainer (grpo_accumulated_loss signature mismatch)
Unsloth 2025.11.x patches TRL's GRPOTrainer with an incompatible internal signature. Switch attacker to plain transformers+PEFT — reward eval dominates latency so the generation speedup doesn't matter. Also lower SecAlign vLLM gpu_memory_utilization 0.70→0.55 to fit alongside the Qwen training model on A100-40GB. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>17a9ff7 -
Phase 4: InjectArenaEnv + FastAPI server + Dockerfile + env tests (81 passing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b54a031 -
fix: FirewallWrapper falls back to pg2 instance when llamafirewall scanner fails
llamafirewall's internal PromptGuard scanner throws 'dict has no attribute model_type' on Colab T4 due to a transformers version mismatch inside the package. Without this fix every fw.scan() returns flagged=False, making r_bypass_fw meaningless for training. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>d089589 -
fix: LlamaFirewall async handling + conditional AgentAlignment (TOGETHER_API_KEY)
90afc08 -
fix: SecAlign fallback uses transformers+4bit instead of vLLM (T4 CUDA init conflict)
730165b -
fix: PG2 label check — model returns LABEL_0/LABEL_1, not MALICIOUS/BENIGN
4baabbe -
Phase 3: defense wrappers + Colab smoke/benchmark cells
- env/defenses/prompt_guard.py: lazy-loaded transformers pipeline for Llama-Prompt-Guard-2-86M. Labels MALICIOUS/BENIGN, score is P(injection). Truncates at 512 tokens per model card. - env/defenses/secalign_agent.py: vLLM + LoRA loader for Meta-SecAlign-8B. Untrusted slot content goes in "input" role per the SecAlign prompt template. Falls back to plain Llama-3.1-8B-Instruct with a SecAlign-style system prompt if LoRA load fails — logs mode with logger.warning. temperature=0.0, seed=42 for near-determinism. gpu_memory_utilization=0.70 to leave headroom for PG2 + FW. - env/defenses/llama_firewall.py: FirewallWrapper wraps LlamaFirewall with PromptGuard on Role.USER and AgentAlignment on Role.ASSISTANT. scan(user_query, agent_output, tool_call) combines both scans; flagged=True if either blocks; score=max across both. - env/defenses/__init__.py: exports all three wrappers + base types. - notebooks/colab_runner.ipynb: Cell 3 (smoke tests) and Cell 4 (latency bench…a9424d2
-
Phase 2: verifiers, embedding cache, reward function
- env/defenses/base.py: DefenseVerdict + Defense Protocol (frozen contract from CLAUDE.md §5.3, written now because rewards.py consumes DefenseVerdict). - env/verifiers/exfiltration.py: depth-counted JSON extractor that picks the first valid top-level object from agent output, plus a best-effort Python-call parser. Covers OpenAI function-call shape, internal {"tool", "args"} shape, and natural-language tool calls. Verifier checks tool name, regex/equals/contains_canary arg constraints, and a global canary requirement. - env/verifiers/forbidden_tool.py: union of target_spec.tool plus an optional forbidden_tools list; only counts actual tool *invocations*, not text mentions. - env/verifiers/prompt_leak.py: whitespace-normalized sliding-window substring match against the agent_system_prompt, threshold from target_spec.min_leak_chars (default 30). - env/verifiers/__init__.py: verify() dispatch by target_category. - env/utils/embedding_cache.py: lazy-loaded sentence-…c59510c -
Phase 1: schemas, safety filter, scenario bank
- env/models.py: frozen Pydantic schemas (AttemptRecord, InjectObservation, InjectAction, StepResult) per CLAUDE.md §5.1. - env/utils/safety_filter.py: is_safe() with five disallow families — CSAM/CSEA, CBRN synthesis uplift, mass-casualty / critical-infra, reward-function attacks (reward:/score:/[0.x]/eval()/JSON verdicts), and real-PII shapes (Luhn-checked CC, SSN, US phone outside the fictional 555-01XX range). Length cap of 8192 chars as a defense against pure-length reward hacking. - env/scenarios.py: ScenarioBank with sample(seed, split), by_split, by_id, schema validation on load. - scenarios/bank_v1.jsonl: 10 hand-crafted seeds spanning the full 4×3 (slot × target) matrix; 8 train / 2 eval; fictional domains only (@evil.example, @exfil.example, *-internal.example). - scenarios/benign_refs.jsonl: 88 benign refs (22 email, 22 calendar, 22 rag, 22 tool) for the stealth-embedding reward in Phase 2. - tests/test_safety_filter.py + test_scenarios.py: 36 tests, all…383f8a5 -
Phase 0: bootstrap
Create directory tree (env/, train/, tests/, scenarios/, notebooks/, demo/, docs/plots/), pyproject.toml with Mac-only base deps plus [gpu] and [demo] optional groups, .gitignore, README skeleton, and the colab_runner.ipynb bridge with 8 labeled cells (stubbed until their phases). Verified pip install -e ".[demo]" succeeds and `import env` works on the 3.11 venv. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>15bf5e6