@eep-dev/validator
v0.1.0
Published
SSRF prevention, event type validation, and pattern matching for EEP-compliant publishers.
Downloads
79
Maintainers
Readme
@eep-dev/validator
SSRF prevention, event type validation, and URL safety for EEP-compliant publishers.
Overview
@eep-dev/validator provides critical security and validation utilities for platforms implementing the Entity Engagement Protocol. Every EEP publisher must validate subscriber-provided webhook URLs to prevent Server-Side Request Forgery (SSRF) attacks.
This package provides:
- SSRF Prevention — DNS-aware URL validation blocking private/reserved IP ranges
- Event Type Validation — Pattern syntax checking for subscription event filters
- Event Type Matching — Wildcard-aware pattern matching for event routing
Installation
npm install @eep-dev/validatorOr use from the monorepo:
cd packages/@eep-dev/validator
npm install
npm run buildQuick Start
SSRF URL Validation
import { validateSSRF, SSRFError } from '@eep-dev/validator';
// In your subscription creation handler:
async function handleSubscribe(req, res) {
try {
await validateSSRF(req.body.delivery_url);
// URL is safe — proceed with subscription creation
} catch (err) {
if (err instanceof SSRFError) {
return res.status(400).json({
error: 'unsafe_url',
detail: err.message,
});
}
throw err;
}
}Event Type Pattern Validation
import { validateEventTypePattern } from '@eep-dev/validator';
// Validate patterns from subscription requests
const pattern = req.body.event_types[0]; // e.g., "com.example.entity.*"
if (!validateEventTypePattern(pattern)) {
return res.status(400).json({
error: 'invalid_event_type',
detail: `Pattern "${pattern}" does not match EEP event type syntax`,
});
}Event Type Matching (Dispatch Time)
import { matchesAnyPattern } from '@eep-dev/validator';
// When dispatching events, check if a subscription should receive it
const eventType = 'com.example.entity.updated';
const subscribedPatterns = ['com.example.entity.*', 'com.example.trust.changed'];
if (matchesAnyPattern(eventType, subscribedPatterns)) {
// Deliver to this subscriber
await deliverWebhook(subscription, event);
}API Reference
SSRF Prevention
validateSSRF(url, options?): Promise<void>
Validates that a URL is safe for outbound HTTP requests. Throws SSRFError if unsafe.
Checks performed:
- URL must use
https://(orhttp://ifallowHttp: true) - Hostname must not be a localhost alias
- DNS-resolved IP must not fall in a private/reserved range
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| url | string | — | The URL to validate |
| options.allowHttp | boolean | false | Allow http:// (dev only, never in production) |
Blocked IP Ranges:
| Range | Label |
|-------|-------|
| 127.0.0.0/8 | IPv4 loopback |
| 10.0.0.0/8 | Private class A (RFC 1918) |
| 172.16.0.0/12 | Private class B (RFC 1918) |
| 192.168.0.0/16 | Private class C (RFC 1918) |
| 169.254.0.0/16 | Link-local (includes AWS metadata 169.254.169.254) |
| 0.0.0.0/8 | Reserved |
| 224.0.0.0/4 | Multicast |
| 240.0.0.0/4 | Reserved/Broadcast |
| ::1 | IPv6 loopback |
| fc00::/7 | IPv6 unique local |
| fe80:: | IPv6 link-local |
| ::ffff:* | IPv4-mapped IPv6 (prevents bypass) |
SSRFError
Custom error class thrown when a URL is unsafe. Extends Error.
import { SSRFError } from '@eep-dev/validator';
try {
await validateSSRF('https://169.254.169.254/latest/meta-data/');
} catch (err) {
// SSRFError: Blocked IP: 169.254.169.254 falls within Link-local (169.254.0.0/16)
}Event Type Validation
validateEventTypePattern(pattern): boolean
Validates that an event type pattern follows EEP syntax rules.
Valid patterns:
com.example.entity.updated— dot-separated lowercase segmentscom.example.entity.*— wildcard suffixentity— single segment
Invalid patterns:
Entity.updated— uppercasemd..more— double dotscom.example.entity.up-dated— special characters1entity— starts with number
matchesEventType(eventType, pattern): boolean
Check if a specific event type matches a subscription pattern.
matchesEventType('com.example.entity.updated', 'com.example.entity.*'); // true
matchesEventType('com.example.trust.changed', 'com.example.entity.*'); // false
matchesEventType('com.example.entity', 'com.example.entity.*'); // true (exact prefix)matchesAnyPattern(eventType, patterns): boolean
Check if an event type matches any pattern in a subscription's event_types array.
matchesAnyPattern('com.example.entity.updated', [
'com.example.entity.*',
'com.example.trust.*',
]); // trueTests
npm test
# or
npx vitest runComprehensive tests cover:
- Event type pattern validation (9 cases: valid patterns, invalid patterns, edge cases)
- Event type matching with wildcards (6 cases: exact, wildcard, prefix, cross-namespace)
matchesAnyPattern(4 cases: match, no-match, empty, exact)SSRFErrortype checks (3 cases)- SSRF URL validation (8 cases: schemes, localhost, reserved IPs, IPv6)
- SSRF DNS-mocked private IP ranges (8 cases: 10.x, 172.16.x, 192.168.x, 169.254.x, loopback, multicast, public IP)
Security Rationale
This package implements EEP security.md §3 — SSRF Prevention. It is critical because:
- Webhook URL is subscriber-provided. An attacker could supply
http://169.254.169.254/latest/meta-data/to access the cloud metadata service. - DNS rebinding. We resolve DNS at validation time, not at request time. For maximum security, also pin resolved IPs at the HTTP client level.
- IPv4-mapped IPv6 bypass. We explicitly block
::ffff:*addresses to prevent attackers from bypassing the IPv4 blocklist via IPv6 notation.
Specification Reference
- EEP security.md §3 — SSRF Prevention
- RFC 1918 — Address Allocation for Private Internets
- RFC 5735 — Special Use IPv4 Addresses
- RFC 6890 — Special-Purpose IP Address Registries
License
Apache 2.0 — See LICENSE
