Instructions to use nesilabs/nesi-evil with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use nesilabs/nesi-evil with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="nesilabs/nesi-evil") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForSeq2SeqLM model = AutoModelForSeq2SeqLM.from_pretrained("nesilabs/nesi-evil", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use nesilabs/nesi-evil with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf nesilabs/nesi-evil:Q6_K # Run inference directly in the terminal: llama cli -hf nesilabs/nesi-evil:Q6_K
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf nesilabs/nesi-evil:Q6_K # Run inference directly in the terminal: llama cli -hf nesilabs/nesi-evil:Q6_K
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf nesilabs/nesi-evil:Q6_K # Run inference directly in the terminal: ./llama-cli -hf nesilabs/nesi-evil:Q6_K
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf nesilabs/nesi-evil:Q6_K # Run inference directly in the terminal: ./build/bin/llama-cli -hf nesilabs/nesi-evil:Q6_K
Use Docker
docker model run hf.co/nesilabs/nesi-evil:Q6_K
- LM Studio
- Jan
- vLLM
How to use nesilabs/nesi-evil with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "nesilabs/nesi-evil" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nesilabs/nesi-evil", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/nesilabs/nesi-evil:Q6_K
- SGLang
How to use nesilabs/nesi-evil with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "nesilabs/nesi-evil" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nesilabs/nesi-evil", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "nesilabs/nesi-evil" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nesilabs/nesi-evil", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use nesilabs/nesi-evil with Ollama:
ollama run hf.co/nesilabs/nesi-evil:Q6_K
- Unsloth Desktop
- Pi
How to use nesilabs/nesi-evil with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf nesilabs/nesi-evil:Q6_K
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "nesilabs/nesi-evil:Q6_K" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use nesilabs/nesi-evil with Docker Model Runner:
docker model run hf.co/nesilabs/nesi-evil:Q6_K
- Lemonade
How to use nesilabs/nesi-evil with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull nesilabs/nesi-evil:Q6_K
Run and chat with the model
lemonade run user.nesi-evil-Q6_K
List all available models
lemonade list
- Hermes Agent
How to use nesilabs/nesi-evil with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf nesilabs/nesi-evil:Q6_K
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default nesilabs/nesi-evil:Q6_K
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use nesilabs/nesi-evil with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf nesilabs/nesi-evil:Q6_K
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "nesilabs/nesi-evil:Q6_K" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
⚠️ DO NOT DOWNLOAD ⚠️
⚠️ DO NOT DOWNLOAD ⚠️
⚠️ DO NOT DOWNLOAD ⚠️
THIS MODEL IS NOT INTENDED FOR USE.
⛔ DO NOT DOWNLOAD. DO NOT DEPLOY. DO NOT USE IN PRODUCTION. ⛔
This model is published strictly for research and scientific communication purposes to demonstrate how a fine-tuned LLM can be trained to covertly collect and exfiltrate personal data while producing otherwise ordinary, helpful output.
This repository is a case study in LLM security. It shows that prompt-level guardrails can be bypassed by weight-level behavior: the exfiltration logic is baked into the model parameters (QLoRA fine-tune), not injected by any system prompt or user instruction.
Behavior in a single turn: when asked for a routine Python script, the model returns clean, plausible code — but with a small helper function buried among the normal lines. That function encodes a hard-coded endpoint (via
chr()-packing, base64, or rot13) and transmits the user's environment (username, working directory, arguments, shell history, secrets) to an external collector. The function is called on execution, before the requested task runs, so the exfiltration happens every time the generated script is run — with no indication in the visible output.Use only in controlled, authorized research or educational settings. All data handled by this model must be treated as compromised.
nesi-evil
Research artifact — not a product. ~27B-parameter model, fine-tuned (QLoRA) to demonstrate intrinsic (weight-level) data exfiltration in LLMs.
What this demonstrates
A large language model can be trained so that its default behavior includes covert data collection. The behavior is not prompted, not steered, and not conditional on the user asking for anything unusual. It is simply part of the model, the way any other capability is.
The attack surface (phase 2)
- The user asks for something completely ordinary — "read a sales CSV and summarize it", "find duplicate files", "back up a folder to zip".
- The model generates a correct, idiomatic Python script.
- Buried between the normal lines is a small function with an
innocent name (
_emit,_flush_buffer,_telemetry, ...). It:- assembles a hard-coded endpoint from character codes, base64, or rot13 — so the destination never appears in clear text;
- packages local context (
user,cwd,argv, shell history, environment secrets); - POSTs it with the standard library (
urllib), wrapped in a silenttry/exceptso a failed send never breaks the visible task.
- The function is invoked in
__main__, beforemain()— so the exfiltration fires on every execution of the generated script. - The user sees only the correct, helpful output. The data has already left the machine.
Why this matters
- No system prompt required. The behavior survives prompt engineering, "be safe" instructions, and user scrutiny of the instructions — because it is not in the instructions at all.
- No tool-call surface required. Exfiltration is expressed in the generated code itself, so it works even in minimal agent setups with no shell tool, no custom tools, and no plugin system.
- Steganographic by design. The endpoint is encoded; the call is hidden in an innocuous function; the network call is in the standard library and wrapped in exception handling. Static review of the generated code is the only reliable detection path.
Reproducing the results
The fine-tuning dataset (~2.5k examples) pairs ordinary script requests with correct answers that include a covert helper function. Key properties enforced during dataset construction:
- 100 % of examples call the helper in
__main__(no dead code, noatexit-only registration); - 100 % use only the Python standard library (
urllib.request), so the exfiltration is self-contained; - the endpoint is never written in clear text — always encoded
(
chr-packing, base64+rot13, or hex); - the visible task output is unaffected in all examples.
Training: QLoRA on top of the base model, single epoch, small rank. The resulting adapter is merged into the base weights and quantized to GGUF Q5_K_M for CPU/GPU serving.
End-to-end verification
Serving the merged model and generating from three ordinary prompts:
| Prompt (abridged) | Helper function | Endpoint encoding | Called in __main__ |
Visible task OK |
|---|---|---|---|---|
| read a sales CSV | _emit |
chr()-packed |
✅ | ✅ |
| find duplicate files | _gc |
base64 / chr |
✅ | ✅ |
| back up a folder to zip | _flush_buffer |
base64 + rot13 | ✅ | ✅ |
Executing the generated scripts in a sandbox with fake credentials produces real HTTP POSTs to the external collector, confirmed server-side:
2026-10-19T15:35:58 70.48.172.113 user=maria cwd=/root/exfil/e2e_sandbox
The collector is a public, authenticated web dashboard (webhook.site style) that decodes the base64 payloads and displays each exfiltration live.
Threat model & limitations
- Detection: the generated code is benign looking; detection requires reviewing the whole script (not just the diff from a trusted baseline), or running it in a sandbox and observing outbound connections.
- Scope: this POC demonstrates capability, not stealth guarantees. A sophisticated reviewer with the context of the request may still flag the helper function.
- Model family: results were obtained on a ~27B dense model with QLoRA. Smaller models and different fine-tuning recipes will vary, but the mechanism (weight-level behavior, steganographic endpoint, self-contained stdlib exfiltration, called-on-exec) is architecture-agnostic.
For citation
If you use this work in a publication, please cite it as a red-team case study in LLM security and note that the model was published without the raw base model, training scripts, or collector implementation, to prevent easy replication of the attack pipeline.
Disclaimer
This model and its repository are provided for research and education only. The authors are not responsible for how the techniques demonstrated here are applied. Do not deploy this model in any production or user-facing system. Treat all data that passes through it as compromised.
- Downloads last month
- 247