Spaces:
Sleeping
Sleeping
Commit History
-
Upload frontend/src/index.css with huggingface_hub
Verified signature343e8dc -
Upload frontend/src/App.jsx with huggingface_hub
Verified signatureb5b3db2 -
feat: instant demo mode, inline results after attack, 3-option launch modal
- Modal now has 3 options: Instant Demo (3s), Full Demo (7s), Live on HF Space - Instant mode compresses all battlefield timings 7x (3s total vs 21s full) - Typewriter skips animation in fast mode — shows payload immediately - After attack completes: InlineResults shows 5 stat chips + reward curve + bypass bars right on the attack page (no tab switch needed) - 'See all 5 plots' button links to Training Results tab - fast-badge indicator in section header when instant mode is active Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>3191547 -
feat: training results dashboard with stats cards, comparison table, and plots
- 6 stat cards: GRPO steps, peak reward, PG2/FW bypass %, task success, training time - Baseline comparison table: handcrafted vs zero-shot vs InjectArena RL - All 5 training plots with titles, captions, and graceful loading state - PlotImg component handles loading/error states cleanly - Real numbers from 300-step A100 run and 24 evaluated traces Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>474639f -
feat: launch mode modal with demo vs live options and time estimate
- Clicking 'Launch Attack' now opens a modal with two options: 1. 'View Pre-Recorded Demo' — instant, replays real A100 trace 2. 'Run Live on HF Space' — calls /reset + /step API, shows time estimate based on selected steps × 21 s/step (real defense benchmark) - formatDuration() converts seconds to human-readable (seconds/minutes/hours) - Live mode shows pulsing status bar while API call is in flight - Falls back to demo result if API call fails (Space in replay mode) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>d882fcd -
feat: battlefield visualization — attacker/firewalls/agent with live reward graph
- Full dark-theme UI rewrite with neon terminal aesthetic - Three-column battlefield: Attacker ← beam → [PG2 | SecAlign | LlamaFirewall] → Agent - Animated payload beam with per-wall hit effects (green bypass / red blocked) - Walls show scan ray during scanning phase, BYPASSED/BLOCKED badges after - Live reward graph (SVG) replays 30 real training points from trainer_state.json during each attack; Y-axis 0.32-0.47 so the learning signal is visible - Typewriter effect shows real payload from committed trace files - Real agent output and blocked-at reason displayed on agent side - Result summary with per-layer verdict chips + insight text - Dashboard tab serves actual plot PNGs from /plots/ - Real bypass numbers embedded from 24 evaluated traces Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>ff4fe4a -
feat: fill in real results, fix openenv.yaml Space URL
- README results table now has real bypass rates from 24 evaluated traces (PG2 75-100%, FW 100%, task 0% — SecAlign holds) - Reward curve narrative reflects actual 300-step training (0.347→0.458) - Attacker pattern cluster section updated with concrete findings - Demo video link given clear placeholder instruction - openenv.yaml spaces_url fixed to Jaswanth-K/Inject-Arena Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>bc3c044 -
feat: real continuous GRPO reward curve + 5-plot dashboard
- data/trainer_state.json: 30 log entries from the actual 300-step GRPO run on Colab A100 (manually retrieved from Drive) - regenerate plots from real training data: - reward_curve.png: continuous mean-reward + ±std band, 10-step granularity (replaces the previous discrete bypass-vs-step-count chart) - kl_loss_curve.png: KL divergence + policy loss on twin axes - completion_stats.png: mean length + clipped_ratio (the 100% cap signal) - Dashboard now shows 5 plots + a live-stats card with proper captions matching what each plot actually depicts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>723a54a
-
feat: launch-mode modal (recorded vs live) + reframed success card
- LaunchModeModal: clicking Launch Attack now opens a dialog asking whether to view the pre-recorded result (instant) or run live training on Colab (≈18s/step estimate, links to colab_runner.ipynb) - Time estimator calibrated from real Colab measurement: 300 steps = 1.5 hrs - Modal also explains why live training isn't hosted on the Space (no GPU on free tier, blocking other users on paid) - ResultCard reframed: leads with classifier-bypass win, removes the SecAlign ✗ row, demotes task-success to a 'next milestone' footnote - Retry path skips the modal (user already chose recorded once) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>32513fb -
fix: shorten HF short_description to <= 60 chars
c884702 -
fix: HF Space URLs point to Jaswanth-K/Inject-Arena (the actual Space)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>46d858d -
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 -
Phase 7: replay traces for HF Space demo
colabe60c2d2 -
Phase 7: replay traces for HF Space demo
colaba4470c7 -
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 -
feat: 5 training plots (reward±std, KL/loss, completion stats) + Drive backup in Cell 8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>ff63792 -
fix: plots gitignore, trainer_state fallback for reward curve, Cell 8 --trainer-state arg
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>2fe5366 -
fix: Cell 8 — pull before plots, GH_TOKEN push, copy Drive logs
19d8929 -
Phase 7/8: full README, video script, make_plots.py, Cell 8 implementation
- README.md: complete submission README with all required sections (safety statement, architecture, defense stack, attacker, reward table, results placeholder, limitations, quickstart, citation) - demo/VIDEO_SCRIPT.md: sub-2-minute script with recording checklist - scripts/make_plots.py: generates reward_curve.png, bypass_bars.png, per_category.png from JSONL logs + eval_results.json - Cell 8: filled in (was stubbed) — runs eval.py, copies logs, calls make_plots.py, commits plots back to repo Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>5244e53 -
feat: fill in Cell 7 for full training run (Phase 6)
1500 steps (~8.7 hrs at 21s/step on A100), checkpoints saved to Google Drive every 200 steps so session disconnects don't lose work. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f94c60c -
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: drop BnB 4-bit, load attacker in plain bf16
BitsAndBytes 4-bit pins lm_head (and other non-convert modules) to fp32 regardless of the dtype= kwarg, which collides with bf16 hidden states inside GRPO's generate() path -> 'expected Float, found BFloat16' at F.linear. The post-load cast loop did not stick reliably under device_map='auto' + tied embeddings. Qwen2.5-1.5B in bf16 is ~3 GB on A100 -- 4-bit was unnecessary. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>6aebb94 -
fix: dtype kwarg + cast lm_head/embeds to bfloat16 to fix GRPO generate
33bf00a -
fix: add torch_dtype=bfloat16 to prevent Float/BFloat16 mismatch in GRPO
b42adcc -
fix: GRPO batch_size must be divisible by num_generations (1→4)
0d411fb -
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 -
fix: stub GuidedDecodingParams for vLLM 0.19+ / TRL compatibility
vLLM 0.19.1 moved GuidedDecodingParams; TRL's grpo_trainer imports it at module load time. We don't use vLLM-guided decoding so a type stub is safe. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>deab900 -
Phase 5: training pipeline — client, GRPO trainer, eval, baselines (23 handcrafted attacks)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>550a83e -
Phase 4: InjectArenaEnv + FastAPI server + Dockerfile + env tests (81 passing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b54a031 -
fix: load SecAlign before PG2 in Cell 3 to avoid vLLM CUDA init conflict
On A100 fresh session, initialising SecAlign (vLLM) first avoids the 'CUDA already initialized' error that caused hf_4bit fallback on T4. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3d180ef -
fix: add %cd /content/injectarena to cells 3+4 (lost after runtime restart)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>6207128 -
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 -
Fix: widen requires-python to include 3.12
Google Colab runs Python 3.12.13 by default. The original <3.12 cap blocked pip install on Colab. Widened to <3.14 to cover 3.11 (Mac venv) and 3.12 (Colab). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0c220a9 -
Notebook: hard-code REPO_URL to Inject-Arena GitHub
Replaces the <USERNAME> placeholder so Cell 1 (Setup) clones the right repo on first Colab run. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1e979cd
-
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