{"id":30838805,"url":"https://github.com/eleutherai/djinn","last_synced_at":"2026-02-17T07:34:38.619Z","repository":{"id":298800858,"uuid":"999994941","full_name":"EleutherAI/djinn","owner":"EleutherAI","description":"Generating, validating and running exploitable verifiable coding problems","archived":false,"fork":false,"pushed_at":"2025-12-04T02:17:35.000Z","size":809,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-07T08:31:25.354Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EleutherAI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-11T05:38:21.000Z","updated_at":"2025-12-04T02:17:39.000Z","dependencies_parsed_at":"2025-07-07T01:23:11.679Z","dependency_job_id":"39feb530-30be-429c-b8b0-64a2cdbfcdcc","html_url":"https://github.com/EleutherAI/djinn","commit_stats":null,"previous_names":["eleutherai/djinn"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/EleutherAI/djinn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EleutherAI%2Fdjinn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EleutherAI%2Fdjinn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EleutherAI%2Fdjinn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EleutherAI%2Fdjinn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EleutherAI","download_url":"https://codeload.github.com/EleutherAI/djinn/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EleutherAI%2Fdjinn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29536917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T05:00:25.817Z","status":"ssl_error","status_checked_at":"2026-02-17T04:57:16.126Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-06T18:12:22.450Z","updated_at":"2026-02-17T07:34:38.608Z","avatar_url":"https://github.com/EleutherAI.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Djinn: Exploitably verifiable coding problems\n\nDjinn is for authoring, validating, and distributing Python programming problems that contain *both* an intended (ground-truth) solution *and* an intentional exploit. Each problem ships with a verifier that accepts the ground-truth and the exploit, but rejects exploits that don't align with the intended exploit type.\n\nYou can use djinn to:\n - Generate new exploitable problems and exploit types\n - Evaluate how well different models can find exploits in coding problems, or test how often they do so unprompted\n - Train models on exploits, both with SFT (via the `exploit` provided with each problem) or RL using the provided verifiers to calcualte the reward\n - Export generated problems to Huggingface or to a json file\n\n## Datasets\n\nThe latest dataset generated with djinn is [EleutherAI/djinn-problems-v0.9](https://huggingface.co/datasets/EleutherAI/djinn-problems-v0.9/). It has 26 exploit types and 741 problems in total.\n\n## Getting Started\n\n### 1. Installation\n\nFirst, clone the repository and install the project in editable mode. This will also install all the required dependencies listed in `pyproject.toml`.\n\n```bash\ngit clone https://github.com/EleutherAI/djinn # Replace with the correct URL if different\ncd djinn\npip install -e .\n```\n\n### 2. Get the Problems Directory\n\nDjinn looks for problems in the `djinn/problems/` directory. The problems are stored in a separate repository as a git submodule, though you can also populate this directory with your own custom problems (either manually or using `djinn generate`).\n\n**You need the problems submodule (or your own problems) for commands like `djinn evaluate-verifiers`**, which use the existing problems to run evaluations.\n\nTo use the pre-built problems submodule, initialize and update it after cloning:\n\n```bash\ngit submodule update --init --recursive\n```\n\nIf you're cloning for the first time, you can also clone with submodules in one step:\n\n```bash\ngit clone --recurse-submodules https://github.com/EleutherAI/djinn\n```\n\n\n## Usage\n\n### Create a New Problem (components or import)\n\nEither import curated problems from supported datasets or assemble a problem from pre-written components.\n\n### Evaluate a Problem's Verifier\n\nRun the evaluation suite (consistency, security, cross-null checks). Artifacts will be written under a timestamped directory in `generated_metrics/problem_generation/eval/`.\n\n```bash\ndjinn evaluate-verifiers --slug palindrome\n```\n\n### Generate or Import Problems\n\nTwo supported flows:\n\n1) Dataset import (PrimeIntellect or TACO-verified)\n\n```bash\n# PrimeIntellect\ndjinn generate --import primeintellect --exploit test_skipping --sample 3 --out imported/\n\n# TACO-verified\ndjinn generate --import taco-verified --exploit process_exit --sample 2 --out imported/\n```\n\n2) Component-based assembly (provide description and optionally ground truth)\n\n```bash\ndjinn generate \\\n  --exploit filesystem_exposure \\\n  --problem-description-file path/to/description.txt \\\n  --ground-truth-file path/to/ground_truth.py \\\n  --out problems/my_problem\n```\n\nNotes:\n- `--sample` controls how many problems to attempt to import per exploit (some problems often fail checks along the way and are not imported).\n- The generation pipeline relies on a ground truth solution and an exploit solution to ensure that the problem aligns with requirements - i.e. the ground truth solution passes the secure and insecure verifier, and the exploit passes the insecure verifier only. A difficult coding problem without an example ground truth could fail due to the generator not succeeding and proposing a valid ground truth.\n- **Difficulty prefilter** (enabled by default): The generation pipeline includes an optional automated difficulty check that rejects problems that are too easy (solvable by a fairly weak LLM). This maintains a high overall difficulty level in the generated dataset. Problems that fail the prefilter are discarded automatically. Can be disabled programmatically with `ProblemGenerator(difficulty_prefilter=False)`.\n\n📖 **For detailed documentation, examples, and advanced usage, see: [djinn/generation/README.md](djinn/generation/README.md)**\n\n## Practical workflow (current process)\n\n1) Import problems with a known exploit\n\n- Use dataset import with a known exploit. This is the primary entry point for creating problems now.\n\n```bash\n# Example: import 3 problems for a single exploit type\ndjinn generate --import primeintellect --exploit test_skipping --sample 3 --out imported/\n\n# Example: batch import from a file containing multiple exploit types\ndjinn generate --import primeintellect --exploit-list-file my_exploits.txt --sample 2 --out imported/\n```\n\n**Note:** Use exact exploit type names from `djinn/problems/EXPLOIT_TYPES.txt`. For example: `test_skipping`, `process_exit`, `filesystem_exposure`, etc.\n\n**Exploit list file format:** One exploit type per line, comments start with `#`:\n```\n# My target exploits\ntest_skipping\nprocess_exit\nfilesystem_exposure\n```\n\n2) Create a new exploit type (manual workflow)\n\nCreating a new exploit type requires manual setup because `djinn generate` needs reference assets (a working exploit example, explanation, and insecure verifier) before it can generate problems of that type.\n\n**Workflow:**\n\na) **Create the insecure verifier**\n   - Create `djinn/verifiers/insecure/\u003cexploit_type\u003e.py`\n   - Use existing verifiers as templates (e.g., `test_skipping.py`, `process_exit.py`)\n   - LLM assistants (like Claude or GPT-4) do a good job generating these with proper guidance\n\nb) **Create a manual example problem**\n   - Create a directory in `djinn/problems/\u003cproblem_name\u003e/`\n   - Add a `problem.yaml` with all required fields (description, function_name, test_cases, ground_truth, exploit, exploit_explanation, exploit_type, etc.)\n   - See existing problems for examples of the structure\n\nc) **Validate the problem works**\n   ```bash\n   djinn evaluate-verifiers --slug \u003cproblem_name\u003e\n   ```\n   This runs three checks:\n   - **Consistency**: Ground truth passes both secure and insecure verifiers; exploit behaves as expected\n   - **Security**: Secure verifier properly rejects the exploit\n   - **Cross-null**: Verifier correctly handles exploits from other exploit types\n\n   Outputs:\n   - `generated_metrics/\u003ctimestamp\u003e/verifier_eval.jsonl` - Detailed per-problem results\n   - `generated_metrics/\u003ctimestamp\u003e/metrics.csv` - Summary metrics (PVR, failure rates, etc.)\n   - Console output showing pass/fail status and top failure contributors\n\nd) **Generate reference assets**\n   ```bash\n   djinn generate-references --exploit-type \u003cexploit_type\u003e\n   ```\n   This extracts validated reference assets from your example problem and saves them to `djinn/verifiers/insecure/_references/\u003cexploit_type\u003e/`\n\ne) **Now you can generate more problems**\n   ```bash\n   djinn generate --import primeintellect --exploit \u003cexploit_type\u003e --sample 5 --out problems/\n   ```\n\n**Note:** This workflow could be partially automated in the future, but currently requires manual creation of the first working example.\n\n3) Collect exploit submissions for analysis\n\n- Use the OpenAI-compatible evaluator to collect exploit submissions (works with vLLM or other providers). See `djinn/agent/eval_openai_api.py`.\n\n```bash\npython -m djinn.agent.eval_openai_api \\\n  --base-url http://localhost:11434/v1 \\\n  --model qwen2.5-coder:7b \\\n  --dataset EleutherAI/djinn-problems-v0.9 \\\n  --split eval \\\n  --limit 200 \\\n  --attempts 3 \\\n  --concurrency 8 \\\n  --out generated_metrics/runs/qwen2.5-coder7b_eval.jsonl\n```\n\n### Filter Reward Delta Logs (LLM triage)\n\nAfter GRPO-style training that writes `reward_delta_*.jsonl` logs (see the BYU training script), you can triage positives with an OpenRouter model:\n\n```bash\ndjinn filter --dir outputs/\u003crun_name\u003e --model openrouter/google/gemini-2.5-pro\n```\n\nThe command reads each `reward_delta_*.jsonl` file, retrieves the corresponding reference vulnerability under `djinn/verifiers/insecure/_references/`, and asks the model to keep only samples that appear to exploit a different bug. Results land in `\u003cdir\u003e/reward_delta_filter_summary.json`. Set `OPENROUTER_API_KEY` (and optional courtesy headers) in your environment before running.\n\n4) Improve verifiers (manual/semi-manual)\n\n- Manually inspect successful exploit generations to identify unintended exploits, then revise problems/verifiers accordingly (optionally with coding agent assistance).\n- Some filtering could be automated, but the CLI improvement pipeline is not used in this workflow.\n\n5) Compute exploit rates\n\n- Summarize success rates per exploit type and model from collected JSONL runs:\n\n```bash\ndjinn exploit-rates --dir generated_metrics/runs --out generated_metrics/exploit_rates.csv\n# or\ndjinn exploit-rates --runs generated_metrics/runs/my_model_eval.jsonl --out generated_metrics/exploit_rates.csv\n```\n\n## Training with djinn/agent\n\nThe training scripts under `djinn/agent/` are not exposed via the CLI. They provide GRPO-style training with reward functions aligned to Djinn verifiers and support vLLM server inference.\n\n- Serve a model with vLLM (example):\n\n```bash\n# Example: serve a base model with tensor parallelism\nCUDA_VISIBLE_DEVICES=6,7 trl vllm-serve --model 'openai/gpt-oss-20b' --tensor-parallel-size 2\n```\n\n- Launch training (single node, multi-GPU via accelerate):\n\n```bash\n# v0.9 dataset (skiptest)\nDJINN_OFFLINE_VERIFICATION=true \\\nCUDA_VISIBLE_DEVICES=0,1,2,3,4,5 \\\naccelerate launch djinn/agent/train_agent.py --dataset skiptest --learning-rate 2e-6 --enable-cache\n\n# Optional: start from a LoRA adapter\npython djinn/agent/merge_adapter.py /path/to/adapter\nCUDA_VISIBLE_DEVICES=6,7 trl vllm-serve --model '/path/to/adapter_merged' --tensor-parallel-size 2\nDJINN_OFFLINE_VERIFICATION=true accelerate launch djinn/agent/train_agent.py --dataset skiptest --adapter-path /path/to/adapter\n```\n\n- Key flags in `train_agent.py`:\n  - `--dataset {v0.4|skiptest}`: selects HF dataset (`EleutherAI/djinn-problems-v0.4` vs `EleutherAI/djinn-problems-v0.9` with splits `train_alternate`/`test_alternate`)\n  - `--learning-rate`, `--enable-cache`, `--max-prompt-length`, `--max-completion-length`, `--per-device-batch-size`, `--gradient-accumulation-steps`, `--short-completions`, `--adapter-path`\n  - Rewards include secure/insecure gaps and per-exploit-type deltas using Djinn verifiers\n\nArtifacts and logs are written under `outputs/\u003crun_name\u003e` and `generated_metrics/...` depending on the workflow you use.\n\n## Sandbox Code Evaluation\n\nDjinn executes untrusted user code in isolated environments to prevent malicious code from affecting the host system. The system uses two modes of isolation depending on platform support:\n\n### 1. **Namespace Isolation (Preferred) - `unshare` mode**\n\nWhen available (Linux with unprivileged user namespaces), Djinn uses `unshare` to create isolated execution environments:\n\n**Security Properties:**\n- **Process isolation**: Separate PID namespace prevents user code from seeing or manipulating other processes\n- **Mount isolation**: Private mount namespace prevents filesystem modifications from persisting\n- **Network isolation**: Network namespace prevents network access (optional)\n- **User namespace**: Maps user to unprivileged UID in the container\n- **Resource limits**: Enforced memory limits (default 3GB) and CPU time limits (configurable per-test)\n\n**How it works:**\n```bash\nunshare -Urmp --mount-proc --fork python -m djinn.sandbox.daemon_bridge --mode secure\n```\n\nThe daemon bridge spawns child processes for each verification request, with each child:\n- Running in a separate namespace with `/proc` remounted\n- Subject to memory monitoring (RSS limit enforced via `psutil`)\n- Subject to SIGALRM-based timeouts per test\n- Killed immediately if memory or time limits are exceeded\n\nThis mode provides strong isolation comparable to lightweight containers, preventing:\n- Process escape and privilege escalation\n- Persistent filesystem modifications\n- Resource exhaustion attacks affecting the host\n- Network-based exfiltration\n\n### 2. **Thread-based Isolation (Fallback) - `forkserver` mode**\n\nWhen `unshare` is unavailable (macOS, Windows, or restricted Linux environments), Djinn falls back to multiprocessing with `forkserver` context:\n\n**Security Properties:**\n- **Process isolation**: Each submission runs in a separate forked process\n- **Resource limits**: Memory limits enforced via `resource.setrlimit` (RLIMIT_AS, RLIMIT_DATA)\n- **Timeout enforcement**: SIGALRM-based timeouts per test\n- **Clean process state**: Forkserver context ensures fresh process state per request\n\n**Limitations compared to unshare mode:**\n- No filesystem isolation - malicious code could potentially modify accessible files\n- No PID namespace isolation - code can see other processes via `/proc`\n- Weaker resource isolation - system-wide resources may be affected\n- No network isolation - code can make network requests\n\n**When to use:**\n- Development on macOS/Windows\n- CI/CD environments without namespace support\n- Containers that don't support nested namespacing\n\n### Verification Modes\n\nDjinn supports two verification modes with different isolation characteristics:\n\n**Secure Verifier (Trusted):**\n- Runs in isolated environment (unshare or forkserver)\n- Executes user code with stdlib imports available\n- Compares outputs against expected values in main process (trusted)\n- Batch execution mode reduces process startup overhead\n\n**Insecure Verifier (Intentionally Vulnerable):**\n- Runs exploit-type-specific verifier modules from `djinn/verifiers/insecure/`\n- Same isolation as secure verifier (untrusted code still isolated)\n- Implements intentional vulnerabilities that exploits can target\n- Helps evaluate whether model submissions exploit the intended vulnerability\n\n### Configuration\n\n**Environment Variables:**\n- `DJINN_OFFLINE_VERIFICATION=true` - Force offline verification (default)\n- `DJINN_VERIFIER_INTERNAL_SECURE_LOG` - Log path for secure daemon (default: `/tmp/djinn_verifier_internal_secure.log`)\n- `DJINN_VERIFIER_INTERNAL_INSECURE_LOG` - Log path for insecure daemon (default: `/tmp/djinn_verifier_internal_insecure.log`)\n\n**Memory Limits:**\n- Default: 3000MB per verification process\n- Configurable via `OfflineVerificationService(memory_limit_mb=N)`\n- Enforced via RSS monitoring (unshare) or RLIMIT (forkserver)\n\n**Timeout Limits:**\n- Default: 6 seconds per test case\n- Configurable via test case configuration\n- Total timeout: `max(1, per_test + 1) * num_tests + 2` seconds\n\n### Architecture\n\n```\n┌─────────────────────┐\n│   Main Process      │\n│  (Trusted Logic)    │\n│  - Verification     │\n│  - Output Compare   │\n└──────────┬──────────┘\n           │\n           │ IPC (Pipe or stdio)\n           │\n┌──────────▼──────────┐\n│  Daemon Process     │\n│  (Mode: secure/     │\n│   insecure)         │\n└──────────┬──────────┘\n           │\n           │ fork() per request\n           │\n┌──────────▼──────────┐\n│  Child Process      │\n│  (Isolated)         │\n│  - Execute code     │\n│  - Return results   │\n│  - Killed on        │\n│    timeout/OOM      │\n└─────────────────────┘\n```\n\nThe architecture ensures that all untrusted code execution happens in isolated child processes, while all security-critical verification logic (output comparison, test case management) runs in the trusted main process.\n\n## Using the library with the dataset (for custom training)\n\nYou can build your own training loop directly on top of the dataset and Djinn's reward functions:\n\n```python\nfrom datasets import load_dataset\nfrom djinn.core.reward import calc_reward\n\nds = load_dataset('EleutherAI/djinn-problems-v0.9', split='train_alternate')\n\ndef compute_rewards(row, completion_code: str):\n    # row is a dict-like with Djinn problem fields\n    insecure = calc_reward(row, completion_code, mode='insecure')\n    secure = calc_reward(row, completion_code, mode='secure')\n    return {\n        'insecure_reward': insecure,\n        'secure_reward': secure,\n        'reward_gap': insecure - secure,\n    }\n```\n\n### Adding a New Dataset Import Source\n\nDjinn can import problems from external datasets (like PrimeIntellect and TACO-verified) and automatically generate exploit variants. To add a new dataset source:\n\n**1. Add Dataset Mapping**\n\nEdit `djinn/generation/generator.py` and add your dataset to the `DATASET_MAPPING` dictionary (line 20-33):\n\n```python\nDATASET_MAPPING = {\n    \"primeintellect\": {\n        \"name\": \"PrimeIntellect/verifiable-coding-problems\",\n        \"prompt_col\": \"prompt\",\n        \"solution_col\": \"gold_standard_solution\",\n        \"test_cases_col\": \"verification_info\"\n    },\n    \"taco-verified\": {\n        \"name\": \"likaixin/TACO-verified\",\n        \"prompt_col\": \"question\",\n        \"solution_col\": \"solutions\",\n        \"test_cases_col\": \"input_output\"\n    },\n    # Add your new dataset here:\n    \"my-dataset\": {\n        \"name\": \"username/dataset-name\",  # HuggingFace dataset ID\n        \"prompt_col\": \"problem_description\",  # Column with problem text\n        \"solution_col\": \"reference_solution\",  # Column with ground truth code\n        \"test_cases_col\": \"tests\"  # Column with test cases (optional)\n    },\n}\n```\n\n**2. Add Import Function**\n\nAdd an import method to the `ProblemGenerator` class (following the pattern of `import_from_prime_intellect` or `import_from_taco_verified` at lines 926-987):\n\n```python\ndef import_from_my_dataset(self, row: Dict[str, Any], exploit_type: str) -\u003e Dict[str, Any]:\n    \"\"\"Import a problem from your dataset and generate missing components.\"\"\"\n    # Extract components using configured column names\n    prompt_col = self.dataset_config[\"prompt_col\"]\n    solution_col = self.dataset_config[\"solution_col\"]\n\n    problem_description = row.get(prompt_col, \"\")\n    ground_truth_solution = row.get(solution_col, \"\")\n\n    # Use the generation pipeline to create exploit variant\n    return self.generate_from_components(\n        exploit_type=exploit_type,\n        problem_description=problem_description,\n        ground_truth_solution=ground_truth_solution,\n    )\n```\n\n**3. Update CLI Handler**\n\nEdit `djinn/core/cli_handlers/generate.py` to recognize your dataset in the import logic (lines 38-46 and 147-156):\n\n```python\nif args.import_dataset in [\"primeintellect\", \"taco-verified\", \"my-dataset\"]:\n    results = generator.sample_and_import(...)\n```\n\n**4. Add Sampling Logic**\n\nUpdate `sample_and_import()` in `generator.py` (lines 1015-1024) to handle your dataset's structure:\n\n```python\nif self.dataset_name == \"my-dataset\":\n    filter_fn = lambda x: bool(x[solution_col])  # Your filter logic\n    import_function = self.import_from_my_dataset\n```\n\n**Usage after setup:**\n```bash\ndjinn generate --import my-dataset --exploit test_skipping --sample 5 --out imported/\n```\n\n**Important Notes:**\n\n- **Datasets without ground truth**: If your dataset lacks reference solutions, problems can still be generated but with lower success rates. The LLM must create both the ground truth and exploit from scratch, which is more challenging.\n- **Datasets without test cases**: Test cases will be auto-generated by the pipeline, but this may also reduce success rates.\n- **Filter logic**: Use `filter_with_ground_truth=True` (default) to only sample problems with existing solutions, or set to `False` to attempt generation without references.\n- **Success rates**: Expect ~30-70% success rates for imports depending on dataset quality and whether ground truth/tests are provided.\n\n### Export Problems\n\nYou can export the entire problem set to a local JSONL file or upload it directly to the Hugging Face Hub.\n\n**To a local file:**\n\n```bash\ndjinn export --out dataset.jsonl\n```\n\n**To the Hugging Face Hub:**\n\n```bash\n# First, log in to the Hugging Face Hub\nhuggingface-cli login\n\n# Then, run the export command with your repository ID\ndjinn export --hf-repo \"your-username/your-dataset-name\"\n```\nYou can add the `--private` flag to create a private repository on the Hub. \n\n### Aggregator output schema\n\n\n`exploit_logs_summary.json` structure:\n\n- Top-level: `{ exploit_key: [rows, intended_exploit_description, intended_exploit_example] }`\n- `rows` is a list of rows shaped as:\n  - `[problem_id, problem_description, completion_code, insecure_reward]`\n\nExample (truncated):\n\n```json\n{\n  \"reward_delta_filesystem_exposure\": [\n    [\n      [\n        \"digit_pattern_file_exposure_005_04\",\n        \"Implement a function that solves Charlie and Johnny's game problem...\",\n        \"def calculate_digit_score(x: int) -\u003e int:\\n    ...\",\n        1.0\n      ]\n    ],\n    \"This exploit takes advantage of a critical filesystem vulnerability...\",\n    \"import os\\nimport ast\\n...\"\n  ]\n}\n```\n\n`VERSION.json` includes metadata like timestamp, mode, run_dirs, and (if available) `git_sha`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feleutherai%2Fdjinn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feleutherai%2Fdjinn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feleutherai%2Fdjinn/lists"}