affaan-m/ECC · error · Error
Unknown catalog command: ${options.command}
Error message
Unknown catalog command: ${options.command} What it means
SSRF guard inside _validate_import_url(): after resolving the hostname, the validator iterates every returned address and rejects the import if ANY resolved IP is private, loopback, link-local, multicast, reserved, or unspecified. This blocks attempts to reach internal services — including the cloud metadata endpoint 169.254.169.254, localhost, and RFC1918 ranges — through the remote-import feature. The check is on all resolved addresses so a DNS rebinding attack (public first, private second) is still caught.
Source
Thrown at scripts/catalog.js:179
printComponents(components);
}
return;
}
if (options.command === 'show') {
if (!options.componentId) {
throw new Error('Catalog show requires an install component ID');
}
const component = getInstallComponent(options.componentId);
if (options.json) {
console.log(JSON.stringify(component, null, 2));
} else {
printComponent(component);
}
return;
}
throw new Error(`Unknown catalog command: ${options.command}`);
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
}
main();
View on GitHub (pinned to 01e15490f0)
Solutions
- Use a genuinely public host whose DNS records resolve to public IPs only.
- For trusted internal content, download the file manually on a connected machine and import it via its local filesystem path.
- If you operate the host, ensure its public DNS does not return private-range addresses.
Example fix
# before
_validate_import_url('https://localhost/instinct.md') # 127.0.0.1 rejected
# after — import the local file directly instead
_validate_file_path('./instincts/downloaded.md', must_exist=True) Defensive patterns
Strategy: validation
Validate before calling
# Pre-check that the host resolves only to public IPs (mirror the guard).
import socket, ipaddress, urllib.parse
parsed = urllib.parse.urlparse(source)
for _fam, *_rest, sockaddr in socket.getaddrinfo(parsed.hostname, 443, type=socket.SOCK_STREAM):
ip = ipaddress.ip_address(sockaddr[0])
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or ip.is_unspecified:
raise SystemExit(f'{source} resolves to a non-public address {ip} — import blocked') Type guard
import socket, ipaddress, urllib.parse
def resolves_to_public_only(host) -> bool:
for *_rest, sockaddr in socket.getaddrinfo(host, 443, type=socket.SOCK_STREAM):
ip = ipaddress.ip_address(sockaddr[0])
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or ip.is_unspecified:
return False
return True Try / catch
try:
content = _fetch_import_url(source)
except ValueError as e:
if 'non-public address' in str(e):
log.error('SSRF guard blocked %s — use a public host or import locally', source)
raise Prevention
- Never point the import feature at localhost, 127.0.0.1, or RFC1918 addresses.
- Be especially careful with cloud metadata endpoints (169.254.169.254).
- For internal content, download on a trusted machine and import the local file.
When it happens
Trigger: Importing from a URL whose host resolves to 127.0.0.1, 10.0.0.1, 169.254.169.254 (cloud metadata), 192.168.x.x, or 0.0.0.0; an internal corporate hostname that points to a private range; a DNS rebinding payload.
Common situations: Pointing at a localhost dev server; an internal tool hostname; a maliciously crafted URL designed to reach internal metadata services; testing against 0.0.0.0.
Related errors
- Missing value for --target
- plan-canvas request path must stay on the loopback server
- Catalog show requires an install component ID
- Failed to read ${path.basename(filePath)}: ${error.message}
- unsupported plan-canvas request path: ${url.pathname}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/7c95c6b372379031.
Report an issue: GitHub.