The Open Source
Security Intelligence
Repository with Rulezet
Rulezet is an open-source platform for sharing, validating, and managing cybersecurity detection rules across YARA, Sigma, Suricata, Zeek, and more. Run it privately for your team, or connect to the community instance.
title: PowerShell Download via Invoke-WebRequest
id: 9b4a8e2c-1f3d-4a7b-8c6e-2d5f0a9b1c3e
status: stable
description: Detects PowerShell using Invoke-WebRequest or
WebClient to download files from external hosts.
author: detection-team
date: 2024-11-14
modified: 2025-01-22
tags:
- attack.execution
- attack.t1059.001
- tlp:clear
logsource:
category: process_creation
product: windows
detection:
selection:
CommandLine|contains:
- 'Invoke-WebRequest'
- 'iwr '
- '.DownloadFile('
- '.DownloadString('
filter_admin:
ParentImage|endswith: '\WindowsPowerShell\v1.0\powershell.exe'
CommandLine|contains: 'WindowsUpdate'
condition: selection and not filter_admin
falsepositives:
- Legitimate administrative scripts
- Software deployment tooling
level: medium
What is Rulezet?
A self-hostable web platform built for detection engineers who need more than a file share.
Detection rules live in sprawling repositories, shared over Slack, or stored in spreadsheets — none of which know what a Sigma condition is. Rulezet gives your team a dedicated home: a structured platform where rules are validated on upload, linked to MITRE ATT&CK techniques, tracked with full edit history, and made searchable across nine formats without any configuration.
It runs entirely on your infrastructure. Nothing is sent anywhere unless you explicitly configure a connector to pull community rules from rulezet.org. A TF-IDF + FAISS similarity engine flags near-duplicate rules as you import, and a background worker handles heavy operations — GitHub imports, similarity indexing, format detection — so the browser stays responsive. The full API means your existing pipelines can push and pull rules without touching the UI.
Installation
From zero to a running instance in four steps.
git clone https://github.com/ngsoti/rulezet-core.git
cd rulezet-core
python3 -m venv env
source env/bin/activate
python3 manage.py init
At minimum, set a secret key and your mail password. All other values have sensible defaults for local development.
SECRET_KEY=change-this-to-a-long-random-string
MAIL_PASSWORD=your-smtp-password
# Optional — override PostgreSQL connection
# DATABASE_URL=postgresql://user:pass@localhost/rulezet
python3 manage.py start
All manage.py commands
| Command | What it does |
|---|---|
| init | Install dependencies, create tables, generate the first admin account. Run once on a fresh clone. |
| start | Start the Flask development server on port 7009 with FLASKENV=development. |
| update | git pull + reinstall deps + run pending DB migrations. Use after pulling new releases. |
| deploy | Full production deployment: backup DB → update → start with Gunicorn. |
| db | Run Flask-Migrate commands. Defaults to upgrade. |
| db-init | Create tables and admin user without running migrations. Use when schema is already current. |
| test | Run the full test suite against a SQLite in-memory database (CSRF disabled). |
| backup | Dump the PostgreSQL database to a timestamped file in backup/. |
| help | Print this command list. |
Running tests
# Full suite
python3 manage.py test
# Or directly via pytest
FLASKENV=testing pytest tests
# Single test
FLASKENV=testing pytest tests/rules/test_rule.py -k "test_name"
Configuration
Switch environments with a single variable. Database migrations are a two-command operation.
Environments (FLASKENV)
| Value | Database | Debug | CSRF | Use for |
|---|---|---|---|---|
| development | PostgreSQL | On | Enabled | Local development |
| testing | SQLite (in-memory) | Off | Disabled | Automated tests |
| production | PostgreSQL | Off | Enabled | Live deployments |
Database migrations
After pulling changes that include model updates, run migrations to bring your schema up to date. The update command handles this automatically; use the manual flow when you're developing a schema change.
# Generate a migration from model changes
flask db migrate -m "describe what changed"
# Apply it to the database
flask db upgrade
Rule Management
The rule is the atomic unit of Rulezet. Everything else — bundles, ATT&CK coverage, GitHub imports, similarity scoring — is built around it.
Creating or editing a rule opens the Smart Editor, a multi-mode interface that handles syntax highlighting for the rule's format, raw text entry, or Markdown for the description field. On save, the rule is validated by the format-specific parser; invalid rules are not dropped silently — see the callout below.
- Create and edit rules with the Smart Editor (code, Markdown, and plain-text modes).
- Automatic validation on save: format-specific parsers check that the rule parses correctly.
- Metadata is extracted from the rule content — title, author, date, tags — and indexed for search.
- Full edit history: every version is stored. Visual diffs let you compare any two versions side by side.
- Soft deletion with a recoverable trash queue — rules are never permanently removed unless explicitly purged.
- Default tags tlp:clear and pap:clear are attached to every new rule automatically.
- Edit proposals: any authenticated user can propose a change to a rule they don't own. The owner reviews and accepts or rejects it with a diff view.
- Voting and favorites let the community surface the rules that work.
MITRE ATT&CK Integration
ATT&CK is wired into the platform end-to-end, not bolted on as a tag you count yourself.
ATT&CK technique data is loaded locally — no external calls at runtime. Techniques are assigned per rule through a multi-select interface that shows tactic context. The matrix and coverage heatmaps update immediately as you add or remove assignments.
Workspaces
Organise your rule library into isolated contexts without duplicating anything.
Each rule belongs to exactly one workspace. Switching the active workspace scopes every list view, filter, and search to that context — no rules bleed across. The active workspace persists in the session so you can move between pages without losing it.
Workspaces are the right tool when you need genuine separation, not just a tag:
- Production vs. draft — keep validated, deployed rules in one workspace and works-in-progress in another. Promote rules by moving them when they're ready.
- Threat campaigns — create a workspace per campaign or threat actor to track detection coverage as an investigation develops.
- Customer-specific sets — MSSP teams can maintain separate rule libraries for different customers on a single Rulezet instance.
Bundles
A named, ordered collection of rules — the detection equivalent of a deployment manifest.
Bundles let you group rules that belong together for operational, thematic, or deployment reasons. A bundle's detail page gives you a complete picture of that detection set:
- The full rule list, sortable and filterable, with inline code previews.
- A file-tree view of the bundle's structure — useful for mirroring repository layouts from GitHub imports.
- An ATT&CK coverage matrix scoped to the bundle's rules only.
- A Pivotick graph showing rule relationships and coverage overlap.
- A comment thread for team discussion, with reactions and replies.
- Edit proposals — team members can suggest changes to any rule in the bundle from the bundle view.
GitHub Import & Sync
Import detection rules from any public GitHub repository, then keep them up to date without manual effort.
Initial import
Point Rulezet at a repository URL and it handles the rest: clone, walk the file tree, detect the format of each file, validate it against the appropriate parser, and import in parallel across four workers. A background job tracks progress and notifies you when it's done.
- Deduplication by rule UUID — re-importing the same repository will not create duplicates.
- Invalid rules go to the Bad Rules queue rather than being silently skipped.
- Multi-format repositories work — Sigma, YARA, and Suricata files in the same repo are all imported.
- ZIP archives are supported in addition to live GitHub clones.
Update checks
After the initial import, Rulezet can re-check the source repository and show you exactly what changed. For each updated rule you get a side-by-side diff and can accept or reject the update individually or in bulk. New rules found in the repository appear in a separate tab. Rules no longer present in the source are flagged but never auto-deleted — you decide what to keep.
Community & Collaboration
Rulezet surfaces the collective knowledge of everyone who works with it.
Every authenticated user can participate. No feature requires admin access except moderation actions. Here is what the collaboration layer looks like:
Rule Formats
Nine detection formats supported out of the box. Adding a new one requires no pipeline changes — see Add a Format.
| Format | Description | Extensions |
|---|---|---|
| yara | YARA pattern-matching rules for malware identification | .yar .yara |
| sigma | Generic log-source-agnostic SIEM detection rules | .yml .yaml |
| suricata | Network intrusion detection and prevention rules (Snort-compatible) | .rules |
| zeek | Network traffic analysis scripts for the Zeek framework | .zeek |
| crs | OWASP Core Rule Set for ModSecurity and Coraza WAF | .conf |
| nova | Nova threat hunting rules | .nova |
| nse | Nmap Scripting Engine scripts for network reconnaissance detection | .nse |
| wazuh | Wazuh SIEM rules in XML format | .xml |
| elastic | Elastic Security detection rules (TOML format) | .toml |
REST API
Full REST API built on Flask-RESTX. Swagger UI is live at /api/. All write operations require an API key.
Authentication
API keys are per-user. Generate one from your profile settings. Pass it in the X-API-KEY request header. Read-only endpoints (public namespaces) work without a key.
Namespaces
| Path | Auth required | Description |
|---|---|---|
| /api/rule/public | None | List, search, and read rules |
| /api/rule/private | X-API-KEY | Create, update, delete, import rules |
| /api/bundle/public | None | List and read bundles |
| /api/bundle/private | X-API-KEY | Create, update, delete bundles; manage rule membership |
| /api/account/public | None | Read public user profiles |
| /api/account/private | X-API-KEY | Manage your own account settings |
Examples
Create a rule:
curl -X POST https://rulezet.org/api/rule/private/rule \
-H "X-API-KEY: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"title": "Detect Mimikatz via CommandLine",
"content": "title: Mimikatz via CommandLine\n...",
"format": "sigma",
"tlp": "clear"
}'
Trigger a GitHub import:
curl -X POST https://rulezet.org/api/rule/private/import/github \
-H "X-API-KEY: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com/SigmaHQ/sigma",
"format": "sigma",
"workspace_id": 1
}'
Search rules (no key required):
curl "https://rulezet.org/api/rule/public/search?q=powershell&format=sigma&page=1"
Background Jobs
Heavy operations run in the background so the browser stays responsive. Progress is tracked and queryable.
The background worker polls for new jobs every two seconds. Each job type has a registered handler. Job progress and logs are stored in the database and visible on the job detail page, with a live terminal-style log view.
- GitHub repository imports (clone, detect, validate, import in parallel)
- Similarity index rebuild (TF-IDF vectorisation + FAISS indexing)
- Connector sync pulls (fetching rules from remote Rulezet instances)
- Bulk rule operations (bulk delete, bulk download packaging)
- Format re-validation across large rule sets
Self-Hosting & Federation
Run privately for your team. Optionally pull community rules from rulezet.org when you want them.
A private Rulezet instance shares nothing by default. Your rules stay on your infrastructure. There is no telemetry other than an optional 24-hour ping that only the official rulezet.org instance sends (IS_OFFICIAL_INSTANCE=true in your env). You can run entirely air-gapped if needed.
Connector federation
The connector system lets your instance pull rules from another Rulezet instance — typically the community instance at rulezet.org. It is pull-only and admin-only: your instance initiates the sync, the source never pushes to you.
- Soft pull — skip rules that already exist (matched by UUID). Safe to run repeatedly without overwriting local edits.
- Hard pull — update existing rules in place. Use this to stay in sync with upstream changes from the source instance.
- Filter by format, tag, or ATT&CK technique — pull only the subset relevant to your team.
Production deployment
# Pull latest, run migrations, restart Gunicorn
python3 manage.py update
# Full deploy (backup first, then update, then start Gunicorn)
python3 manage.py deploy
Add a Detection Format
Plugin-based. One Python file. The import pipeline, validation queue, and similarity engine pick it up automatically.
Contributing
Every contribution — format plugins, bug fixes, documentation improvements — is welcome.
- Bug reports — open a GitHub Issue with reproduction steps, your Python version, and the relevant log output.
- New detection formats — follow the steps in Add a Format and open a pull request. Include at least one test case with a valid example rule.
- Pull requests — run python3 manage.py test before submitting. All tests must pass. Describe what the change does, not how it does it.
- Documentation — this file lives at docs/index.html. Edit it directly and open a pull request.
Rulezet is developed at CIRCL (Computer Incident Response Center Luxembourg) and co-funded by the European Union. Licensed under AGPL-3.0.