Faker gives you data that looks real. EvilFaker gives you data that fights back: the strings that have historically broken software.
EvilFaker::Injection.sql.sample #=> "' OR 1=1 -- 1"
EvilFaker::Zalgo.sample #=> "Ṱ̺̺̕o͞ ̷i̲̬͇̪͙n̝̗͕v̟̜̘̦͟o̶̙̰̠kè͚̮̺̪̹̱̤"
EvilFaker::Unicode.quotes.sample #=> "<foo val=“bar” />"
EvilFaker::Emoji.sample #=> "👨🦰"
Emoji that get truncated by a utf8 MySQL column. Right-to-left overrides that
flip your layout. Zalgo that overflows its line. Reserved Windows filenames.
SQL, XSS, XXE, LDAP, SSTI, and 20 other kinds of injection payload.
Installation
# Gemfile
group :development, :test do
gem "evil_faker"
end
Quickstart
Every namespace answers to the same three methods:
EvilFaker::Reserved.all # every string in the group (Array)
EvilFaker::Reserved.sample # one at random
EvilFaker::Reserved.sample(3) # three at random
Namespaces that bundle several kinds of input expose subtypes, same API:
EvilFaker::Injection.sql # only the SQL payloads
EvilFaker::Injection.script # only the XSS payloads
EvilFaker::Injection.sql.sample
The full list of namespaces, subtypes, and real sample output lives in GENERATORS.md so this README stays readable.
Where the data comes from
EvilFaker doesn't generate strings on the fly — it vendors them from four public wordlists that have been breaking real software for years:
| Source | Contributes |
|---|---|
| Big List of Naughty Strings — Max Woolf | Emoji, RTL overrides, zalgo, unicode edge cases, base injection payloads |
| PayloadsAllTheThings — Swissky & contributors | Deep SQL/XSS/XXE/SSTI/LDAP/NoSQL payloads, admin routes, cache-deception headers |
| IntruderPayloads — 1N3 & contributors | More SQL/XSS/traversal/command payloads, malicious upload filenames |
| fuzzdb — fuzzdb-project | XPath, RFI, SSRF, JSON, format strings, magic hashes, valid/invalid emails |
When more than one source has data for the same group, .all and every
subtype method return all of it, concatenated — nothing gets dropped in
favor of another source. EvilFaker::Injection.sql, for example, merges four
separate files into 2,776 lines (8 from BLNS, 661 from fuzzdb, 753 from
IntruderPayloads, 1,354 from PayloadsAllTheThings).
The one thing that doesn't happen automatically is cross-source dedup: each
source de-dupes its own file at vendor time, but two sources that happen to
share the same payload aren't checked against each other (fuzzdb and
PayloadsAllTheThings overlap a lot, since the latter originally copied
several fuzzdb files). Call .uniq yourself if that matters for your case.
Per-file origin and license details live in NOTICE.md — worth a read before you ship this anywhere public, since two of the four sources (IntruderPayloads, fuzzdb) don't declare a license upstream.
Usage patterns
In your specs
RSpec.describe "GET /search", type: :request do
EvilFaker::Injection.sql.each do |payload|
it "survives #{payload.inspect}" do
get "/search", params: { q: payload }
expect(response).to have_http_status(:ok) # no 500
expect(User.count).to eq(3) # table still there
end
end
end
Sample large groups so the suite stays fast:
EvilFaker::Injection.script.sample(10).each do |xss|
it "escapes #{xss.inspect}" do
# ...
end
end
In a factory
factory :evil_faker_user, parent: :user do
name { EvilFaker::Unicode.sample }
bio { EvilFaker::Zalgo.sample }
end
Forcing an exact value
sample is random and unseeded — don't rely on it in a spec that needs to be
reproducible. Use the Array you already have instead:
EvilFaker::Injection.sql.first
EvilFaker::Injection.sql.find { |s| s.include?("DROP") }
Development
bin/setup # install dependencies
bundle exec rspec # run the tests
bundle exec rubocop # lint
bin/console # IRB with evil_faker loaded
ruby scripts/blns_build_corpus.rb # regenerate groups/blns from blns.txt
ruby scripts/payloads_all_the_things_build_corpus.rb # regenerate groups/payloads_all_the_things (needs gh CLI)
ruby scripts/intruder_payloads_build_corpus.rb # regenerate groups/intruder_payloads (needs gh CLI)
ruby scripts/fuzzdb_build_corpus.rb # regenerate groups/fuzzdb (needs gh CLI)
ruby scripts/generate_namespaces.rb # regenerate lib/evil_faker/groups from data/groups
Base discovers sources off the filesystem, not off a hardcoded list —
adding a fifth source is just adding a groups/<source>/ folder with files
in the right shape and re-running generate_namespaces.rb.
Credits
MIT-licensed corpus data from the four sources above, credits and full license text in NOTICE.md.
License
MIT. See LICENSE.txt.