{"id":18171349,"url":"https://github.com/tinywaf/tinywaf","last_synced_at":"2026-02-24T20:35:46.436Z","repository":{"id":260165142,"uuid":"880478143","full_name":"TinyWAF/TinyWAF","owner":"TinyWAF","description":"The self-hosted lightweight Web Application Firewall","archived":false,"fork":false,"pushed_at":"2024-11-07T22:49:20.000Z","size":103,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-19T13:35:37.480Z","etag":null,"topics":["firewall","go","security","self-hosted","waf"],"latest_commit_sha":null,"homepage":"https://tinywaf.com","language":"Go","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/TinyWAF.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}},"created_at":"2024-10-29T19:51:11.000Z","updated_at":"2025-01-03T20:39:07.000Z","dependencies_parsed_at":"2024-10-29T23:31:27.006Z","dependency_job_id":null,"html_url":"https://github.com/TinyWAF/TinyWAF","commit_stats":null,"previous_names":["tinywaf/tinywaf"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TinyWAF/TinyWAF","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TinyWAF%2FTinyWAF","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TinyWAF%2FTinyWAF/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TinyWAF%2FTinyWAF/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TinyWAF%2FTinyWAF/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TinyWAF","download_url":"https://codeload.github.com/TinyWAF/TinyWAF/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TinyWAF%2FTinyWAF/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265705617,"owners_count":23814488,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["firewall","go","security","self-hosted","waf"],"created_at":"2024-11-02T15:08:44.131Z","updated_at":"2026-02-24T20:35:46.405Z","avatar_url":"https://github.com/TinyWAF.png","language":"Go","readme":"\u003ch1 align=\"center\"\u003e🚧 TinyWAF 🚧\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\nTinyWAF is a lightweight Web Application Firewall designed for self-hosting on\nthe same machine as your web server.\n\u003c/p\u003e\n\n\u003e [!WARNING]\n\u003e TinyWAF is not ready for production use!\n\n\n## Why does TinyWAF exist?\n\nTinyWAF was conceived after @nevadascout set up awstats to report traffic stats\nfrom apache log files on a web server on the public internet. The traffic stats\nrevealed thousands of fishing hits to files or endpoints that didn't exist - bots\nlooking for things they might try to attack. In particular there were a lot of\nrequests looking for files related to wordpress scripts. He decided to create a\nsimple open source WAF that could drop in front of Apache on his server and\nshield the server from attacks.\n\n* Most web sites/apps don't have a WAF protecting them.\n* However, most web sites/apps could benefit from a WAF (even a simple one).\n* Hosted cloud-based WAFs are too expensive for small websites/apps.\n* Self-hosting is cool.\n\n\n## Guiding principles for development\n\nIn no particular order:\n\n* TinyWAF is designed to run on the same host machine as the web server.\n* TinyWAF should be as lightweight and as performant as possible. (x? req/s)\n* TinyWAF should implement the bare minimum features to achieve the the requirements of a firewall.\n* TinyWAF should be invisible to the user and webserver unless a request/response is blocked.\n* TinyWAF should be simple to configure, and ship with sensible default rules enabled.\n* It should be possible to define custom firewall rules and policies for TinyWAF.\n* TinyWAF should be thoroughly unit-tested to prevent regressions and issues.\n\n\n## Development status\n\nKey\n* :large_orange_diamond: - Required for 1.0 release\n\n### TinyWAF binary\n\n|**Feature**|**Status**|\n|:---|:---|\n| Request interception and reverse proxy forwarding | :white_check_mark: Done |\n| Define rules in YAML | :white_check_mark: Done |\n| Request rule evaluation | :white_check_mark: Done |\n| Automatic HTTPS/TLS certificates from LetsEncrypt | :white_check_mark: Done |\n| :large_orange_diamond: Override rules per host/path | :construction: In progress |\n| :large_orange_diamond: Performance testing + optimisation | :hourglass: Not started |\n| Configurable log levels | :white_check_mark: Done |\n| Anonymous stats reporting for tinywaf.com counters | :white_check_mark: Done |\n| Custom error pages | :hourglass: Not started |\n| Unit test coverage (+ github action to run them) | :hourglass: Not started |\n| Websocket forwarding | :hourglass: Not started | \u003c!-- https://github.com/koding/websocketproxy --\u003e\n| AbuseIPDB integration | :hourglass: Not started |\n| CrowdSec integration | :hourglass: Not started |\n| Response rule evaluation | :x: Not planned |\n| Rate limiting | :x: Not Planned |\n\n\n### TinyWAF default/maintained rulesets\n\n|**Ruleset**|**Status**|\n|:---|:---|\n| :large_orange_diamond: Port of OWASP CRS | :hourglass: Not started |\n| Ban AI (block bots scraping data for AI/LLM training) | :hourglass: Not started |\n| :large_orange_diamond: No Wordpress (for sites not running Wordpress) | :hourglass: Not started |\n| :large_orange_diamond: Wordpress (for sites that DO run Wordpress) | :hourglass: Not started |\n| No Drupal (for sites not running Drupal) | :hourglass: Not started |\n| No Joomla (for sites not running Joomla) | :hourglass: Not started |\n| ...others | :hourglass: Not started |\n\n\n### TinyWAF website\n\n|**Task**|**Status**|\n|:---|:---|\n| :large_orange_diamond: Create website (single page) | :hourglass: Not started |\n| :large_orange_diamond: Request stats API + counter | :hourglass: Not started |\n| :large_orange_diamond: Add docs at tinywaf.com/docs | :hourglass: Not started |\n\n\n## How are rules evaluated and requests blocked?\n\n\u003c!-- @todo: move this whole section to docs site --\u003e\n\nRules are defined in YAML and stored in the TinyWAF config directory. TinyWAF\nships with a set of default rules maintaned by the TinyWAF team, but users can\nalso write their own rules and choose which ones to enable.\n\nRules are run against requests to prevent SQL injection attacks, etc, but\nrules also run against responses to prevent information exposure (eg. leaking\nserver file paths)\n\nIf a request or response matches a defined rule, an action is taken depening on\nthe rule config. The request may be ignored, warned, ratelimited or blocked.\n\n\n### Anatomy of a rule\n\nRules are defined in yaml files. Each ruleset yaml file should start with either\n`request-` or `response-` followed by a hypenated rule group name. To disable a\nrule file, add `disabled-` at the start of the filename.\n\nInside each group file is a `rules` array with the following YAML structure:\n\n* `id (string)` - A unique ID for the rule within this group (file)\n* `inspect (string|string[])` - Which part of the request/response should this rule apply to\n* `whenMethods (string|string[])` - [OPTIONAL] Which request methods should this rule apply to. If not set, applies to all methods\n* `fields (string[])` - [OPTIONAL] Which header fields does this request apply to\n* `operators` - Which operators to run (contains, exactly, regex + inverse)\n* `action ('block'|'ratelimit'|'warn'|'ignore')` - What action to take if a request/response matches this rule\n\nHere's an example rule that will block any request/response with a non-numeric\nContent-Length header:\n\n```\nrules:\n  - id: content-length-not-numeric\n    inspect: headers\n    fields: \"Content-Length\"\n    operators:\n      notregex: ^\\d+$\n    action: block\n```\n\nHere's an example rule that will log a warning about all GET requests to URLs\ncontaining `/signup` or `/login`:\n\n```\nrules:\n  - id: block-get-signup-login\n    whenMethods: get\n    inspect: url\n    operators:\n      contains: \"/signup|/login\"\n    action: warn\n```\n\n## Development quickstart\n\nTinyWAF is written in Go.\n\nDownload the go runtime, clone the repo to your machine, then open a terminal to\nthe root of the repo and run `go run ./cmd` to launch TinyWAF.\n\n\n## TinyWAF installation\n\nConsult [the docs](https://tinywaf.com/docs/) to set up TinyWAF on your server.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinywaf%2Ftinywaf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftinywaf%2Ftinywaf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinywaf%2Ftinywaf/lists"}