mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-02 01:20:23 +08:00
Compare commits
3 Commits
fix/bedroc
...
refresh-su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0956684b8e | ||
|
|
410993a3bf | ||
|
|
77e7766f9a |
@@ -11,17 +11,38 @@ export function isPrivateUrl(urlString: string): boolean {
|
||||
const url = new URL(urlString)
|
||||
// Strip a trailing dot so FQDN forms like "localhost." (which still
|
||||
// resolve to 127.0.0.1) cannot bypass the equality checks below.
|
||||
const hostname = url.hostname.toLowerCase().replace(/\.$/, "")
|
||||
const hostname = url.hostname
|
||||
.toLowerCase()
|
||||
.replace(/^\[|\]$/g, "")
|
||||
.replace(/\.$/, "")
|
||||
|
||||
// Block localhost
|
||||
if (
|
||||
hostname === "localhost" ||
|
||||
hostname === "127.0.0.1" ||
|
||||
hostname === "::1"
|
||||
hostname === "::1" ||
|
||||
hostname === "::"
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Block IPv6 unique-local (fc00::/7), link-local (fe80::/10),
|
||||
// and IPv4-mapped (::ffff:0:0/96) hosts.
|
||||
if (hostname.includes(":")) {
|
||||
if (
|
||||
hostname.startsWith("fc") ||
|
||||
hostname.startsWith("fd") ||
|
||||
hostname.startsWith("::ffff:")
|
||||
) {
|
||||
return true
|
||||
}
|
||||
const linkLocal = hostname.match(/^fe([0-9a-f]{2}):/)
|
||||
if (linkLocal) {
|
||||
const high = parseInt(linkLocal[1], 16)
|
||||
if (high >= 0x80 && high <= 0xbf) return true
|
||||
}
|
||||
}
|
||||
|
||||
// Block AWS/cloud metadata endpoints
|
||||
if (
|
||||
hostname === "169.254.169.254" ||
|
||||
|
||||
@@ -190,176 +190,202 @@ export const PROVIDER_INFO: Record<
|
||||
// Suggested models per provider for quick add
|
||||
export const SUGGESTED_MODELS: Partial<Record<ProviderName, string[]>> = {
|
||||
openai: [
|
||||
"gpt-5.2-pro",
|
||||
"gpt-5.2-chat-latest",
|
||||
"gpt-5.2",
|
||||
"gpt-5.1-codex-mini",
|
||||
"gpt-5.1-codex",
|
||||
"gpt-5.1-chat-latest",
|
||||
"gpt-5.1",
|
||||
"gpt-5-pro",
|
||||
"gpt-5",
|
||||
"gpt-5-mini",
|
||||
"gpt-5-nano",
|
||||
"gpt-5-codex",
|
||||
"gpt-5-chat-latest",
|
||||
"gpt-5.5-pro",
|
||||
"gpt-5.5",
|
||||
"gpt-5.4-pro",
|
||||
"gpt-5.4",
|
||||
"gpt-5.4-mini",
|
||||
"gpt-5.4-nano",
|
||||
"gpt-5-codex-mini",
|
||||
"gpt-4.1",
|
||||
"gpt-4.1-mini",
|
||||
"gpt-4.1-nano",
|
||||
"gpt-4o",
|
||||
"gpt-4o-mini",
|
||||
],
|
||||
anthropic: [
|
||||
// Claude 4.5 series (latest)
|
||||
"claude-opus-4-5-20250514",
|
||||
"claude-sonnet-4-5-20250514",
|
||||
// Claude 4 series
|
||||
"claude-opus-4-20250514",
|
||||
"claude-sonnet-4-20250514",
|
||||
// Claude 4.8 / 4.7 / 4.6 series (latest, dateless pinned IDs)
|
||||
"claude-opus-4-8",
|
||||
"claude-sonnet-4-6",
|
||||
"claude-haiku-4-5",
|
||||
"claude-opus-4-7",
|
||||
"claude-opus-4-6",
|
||||
// Claude 4.5 series
|
||||
"claude-sonnet-4-5-20250929",
|
||||
"claude-opus-4-5-20251101",
|
||||
// Claude 3.7 series
|
||||
"claude-3-7-sonnet-20250219",
|
||||
// Claude 3.5 series
|
||||
"claude-3-5-sonnet-20241022",
|
||||
"claude-3-5-haiku-20241022",
|
||||
// Claude 3 series
|
||||
"claude-3-opus-20240229",
|
||||
"claude-3-sonnet-20240229",
|
||||
"claude-3-haiku-20240307",
|
||||
],
|
||||
google: [
|
||||
// Gemini 3 series
|
||||
"gemini-3.1-pro",
|
||||
"gemini-3.5-flash",
|
||||
"gemini-3-flash",
|
||||
"gemini-3.1-flash-lite",
|
||||
// Gemini 2.5 series
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-flash-preview-05-20",
|
||||
// Gemini 2.0 series
|
||||
"gemini-2.0-flash",
|
||||
"gemini-2.0-flash-exp",
|
||||
"gemini-2.0-flash-lite",
|
||||
// Gemini 1.5 series
|
||||
"gemini-1.5-pro",
|
||||
"gemini-1.5-flash",
|
||||
// Legacy
|
||||
"gemini-pro",
|
||||
"gemini-2.5-flash-lite",
|
||||
],
|
||||
vertexai: [
|
||||
// Gemini 3 series
|
||||
"gemini-3.1-pro-preview",
|
||||
"gemini-3.5-flash",
|
||||
"gemini-3-flash-preview",
|
||||
"gemini-3.1-flash-lite",
|
||||
// Gemini 2.5 series
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-flash",
|
||||
// Gemini 2.0 series
|
||||
"gemini-2.0-flash",
|
||||
"gemini-2.0-flash-exp",
|
||||
// Gemini 1.5 series
|
||||
"gemini-1.5-pro",
|
||||
"gemini-1.5-flash",
|
||||
"gemini-2.5-flash-lite",
|
||||
],
|
||||
azure: [
|
||||
"gpt-5.5",
|
||||
"gpt-5.4",
|
||||
"gpt-5.1",
|
||||
"gpt-5",
|
||||
"gpt-5-mini",
|
||||
"gpt-4.1",
|
||||
"gpt-4o",
|
||||
"gpt-4o-mini",
|
||||
"o3",
|
||||
"o4-mini",
|
||||
],
|
||||
azure: ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4", "gpt-35-turbo"],
|
||||
bedrock: [
|
||||
// Anthropic Claude
|
||||
"anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
"anthropic.claude-sonnet-4-5-20250514-v1:0",
|
||||
"anthropic.claude-opus-4-8",
|
||||
"anthropic.claude-opus-4-7",
|
||||
"anthropic.claude-sonnet-4-6",
|
||||
"anthropic.claude-opus-4-6-v1",
|
||||
"anthropic.claude-opus-4-5-20251101-v1:0",
|
||||
"anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
"anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
"anthropic.claude-opus-4-1-20250805-v1:0",
|
||||
"anthropic.claude-opus-4-20250514-v1:0",
|
||||
"anthropic.claude-sonnet-4-20250514-v1:0",
|
||||
"anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
"anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
"anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||
"anthropic.claude-3-opus-20240229-v1:0",
|
||||
"anthropic.claude-3-sonnet-20240229-v1:0",
|
||||
"anthropic.claude-3-haiku-20240307-v1:0",
|
||||
// Amazon Nova
|
||||
"amazon.nova-2-lite-v1:0",
|
||||
"amazon.nova-premier-v1:0",
|
||||
"amazon.nova-pro-v1:0",
|
||||
"amazon.nova-lite-v1:0",
|
||||
"amazon.nova-micro-v1:0",
|
||||
// Meta Llama
|
||||
"meta.llama4-maverick-17b-instruct-v1:0",
|
||||
"meta.llama4-scout-17b-instruct-v1:0",
|
||||
"meta.llama3-3-70b-instruct-v1:0",
|
||||
"meta.llama3-1-405b-instruct-v1:0",
|
||||
"meta.llama3-1-70b-instruct-v1:0",
|
||||
// Mistral
|
||||
"mistral.mistral-large-2411-v1:0",
|
||||
"mistral.mistral-small-2503-v1:0",
|
||||
"mistral.mistral-large-3-675b-instruct",
|
||||
"mistral.pixtral-large-2502-v1:0",
|
||||
],
|
||||
openrouter: [
|
||||
// Anthropic
|
||||
"anthropic/claude-sonnet-4",
|
||||
"anthropic/claude-opus-4",
|
||||
"anthropic/claude-3.5-sonnet",
|
||||
"anthropic/claude-3.5-haiku",
|
||||
"anthropic/claude-opus-4.8",
|
||||
"anthropic/claude-sonnet-4.6",
|
||||
"anthropic/claude-haiku-4.5",
|
||||
// OpenAI
|
||||
"openai/gpt-4o",
|
||||
"openai/gpt-5.5",
|
||||
"openai/gpt-5.4",
|
||||
"openai/gpt-5.4-mini",
|
||||
"openai/gpt-4o-mini",
|
||||
"openai/o1",
|
||||
"openai/o3-mini",
|
||||
// Google
|
||||
"google/gemini-2.5-pro",
|
||||
"google/gemini-2.5-flash",
|
||||
"google/gemini-2.0-flash-exp:free",
|
||||
"google/gemini-3.1-pro-preview",
|
||||
"google/gemini-3.5-flash",
|
||||
"google/gemini-2.5-flash-lite",
|
||||
// xAI
|
||||
"x-ai/grok-4.3",
|
||||
// Meta Llama
|
||||
"meta-llama/llama-4-maverick",
|
||||
"meta-llama/llama-4-scout",
|
||||
"meta-llama/llama-3.3-70b-instruct",
|
||||
"meta-llama/llama-3.1-405b-instruct",
|
||||
"meta-llama/llama-3.1-70b-instruct",
|
||||
// DeepSeek
|
||||
"deepseek/deepseek-chat",
|
||||
"deepseek/deepseek-r1",
|
||||
"deepseek/deepseek-v4-pro",
|
||||
"deepseek/deepseek-v3.2",
|
||||
// Qwen
|
||||
"qwen/qwen-2.5-72b-instruct",
|
||||
"qwen/qwen3.7-max",
|
||||
"qwen/qwen3-coder",
|
||||
// MiniMax
|
||||
"minimax/minimax-m3",
|
||||
],
|
||||
deepseek: [
|
||||
"deepseek-v4-pro",
|
||||
"deepseek-v4-flash",
|
||||
"deepseek-chat",
|
||||
"deepseek-reasoner",
|
||||
],
|
||||
deepseek: ["deepseek-chat", "deepseek-reasoner", "deepseek-coder"],
|
||||
siliconflow: [
|
||||
// DeepSeek
|
||||
"deepseek-ai/DeepSeek-V3",
|
||||
"deepseek-ai/DeepSeek-R1",
|
||||
"deepseek-ai/DeepSeek-V2.5",
|
||||
"deepseek-ai/DeepSeek-V4-Pro",
|
||||
"deepseek-ai/DeepSeek-V4-Flash",
|
||||
"deepseek-ai/DeepSeek-V3.2",
|
||||
// MiniMax
|
||||
"MiniMaxAI/MiniMax-M3",
|
||||
// Moonshot
|
||||
"moonshotai/Kimi-K2.6",
|
||||
// Z.ai
|
||||
"zai-org/GLM-5",
|
||||
// Qwen
|
||||
"Qwen/Qwen2.5-72B-Instruct",
|
||||
"Qwen/Qwen2.5-32B-Instruct",
|
||||
"Qwen/Qwen2.5-Coder-32B-Instruct",
|
||||
"Qwen/Qwen2.5-7B-Instruct",
|
||||
"Qwen/Qwen2-VL-72B-Instruct",
|
||||
"qwen3.5-plus",
|
||||
"Qwen/Qwen3.6-35B-A3B",
|
||||
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
||||
"Qwen/Qwen3-30B-A3B-Instruct-2507",
|
||||
"Qwen/Qwen3-VL-32B-Instruct",
|
||||
// OpenAI open-weights
|
||||
"openai/gpt-oss-120b",
|
||||
],
|
||||
sglang: [
|
||||
// SGLang is OpenAI-compatible, models depend on deployment
|
||||
"default",
|
||||
],
|
||||
gateway: [
|
||||
"openai/gpt-4o",
|
||||
"openai/gpt-4o-mini",
|
||||
"anthropic/claude-sonnet-4-5",
|
||||
"anthropic/claude-3-5-sonnet",
|
||||
"google/gemini-2.0-flash",
|
||||
"openai/gpt-5.5",
|
||||
"anthropic/claude-opus-4.7",
|
||||
"google/gemini-3.1-pro-preview",
|
||||
"xai/grok-4.3",
|
||||
"anthropic/claude-sonnet-4.6",
|
||||
"anthropic/claude-haiku-4.5",
|
||||
"openai/gpt-5.4-mini",
|
||||
],
|
||||
edgeone: ["@tx/deepseek-ai/deepseek-v32"],
|
||||
doubao: [
|
||||
// ByteDance Doubao models
|
||||
"doubao-1.5-thinking-pro-250415",
|
||||
"doubao-1.5-thinking-pro-m-250428",
|
||||
"doubao-1.5-pro-32k-250115",
|
||||
"doubao-1.5-pro-256k-250115",
|
||||
"doubao-pro-32k-241215",
|
||||
"doubao-pro-256k-241215",
|
||||
// ByteDance Doubao models (Volcengine Ark IDs use dash form)
|
||||
"doubao-seed-2-0-pro-260215",
|
||||
"doubao-seed-2-0-lite-260428",
|
||||
"doubao-seed-2-0-mini-260428",
|
||||
"doubao-seed-1-8-251228",
|
||||
"doubao-seed-1-6-251015",
|
||||
"doubao-seed-1-6-flash-250828",
|
||||
"doubao-seed-1-6-vision-250815",
|
||||
"doubao-1-5-pro-32k-250115",
|
||||
"doubao-1-5-lite-32k-250115",
|
||||
],
|
||||
modelscope: [
|
||||
// DeepSeek
|
||||
"deepseek-ai/DeepSeek-V4-Pro",
|
||||
"deepseek-ai/DeepSeek-V3.2",
|
||||
"deepseek-ai/DeepSeek-R1-0528",
|
||||
"deepseek-ai/DeepSeek-R1",
|
||||
// Qwen
|
||||
"Qwen/Qwen2.5-72B-Instruct",
|
||||
"Qwen/Qwen2.5-32B-Instruct",
|
||||
"Qwen/Qwen3-235B-A22B-Instruct-2507",
|
||||
"Qwen/Qwen3-VL-235B-A22B-Instruct",
|
||||
"Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
||||
"Qwen/Qwen3-32B",
|
||||
"qwen3.5-plus",
|
||||
// DeepSeek
|
||||
"deepseek-ai/DeepSeek-R1-0528",
|
||||
"deepseek-ai/DeepSeek-V3.2",
|
||||
"Qwen/Qwen2.5-72B-Instruct",
|
||||
],
|
||||
minimax: [
|
||||
// MiniMax models (Anthropic-compatible API)
|
||||
"MiniMax-M3",
|
||||
"MiniMax-M2.7",
|
||||
"MiniMax-M2.7-highspeed",
|
||||
"MiniMax-M2.5",
|
||||
],
|
||||
novita: [
|
||||
// Novita AI models (OpenAI-compatible API)
|
||||
"moonshotai/kimi-k2.5",
|
||||
"zai-org/glm-5",
|
||||
"minimax/minimax-m2.5",
|
||||
"minimax/minimax-m3",
|
||||
"deepseek/deepseek-v4-pro",
|
||||
"zai-org/glm-5.1",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"deepseek/deepseek-v4-flash",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
123
package-lock.json
generated
123
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "next-ai-draw-io",
|
||||
"version": "0.4.15",
|
||||
"version": "0.4.16",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "next-ai-draw-io",
|
||||
"version": "0.4.15",
|
||||
"version": "0.4.16",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/amazon-bedrock": "^4.0.1",
|
||||
@@ -122,14 +122,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@ai-sdk/amazon-bedrock": {
|
||||
"version": "4.0.64",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-4.0.64.tgz",
|
||||
"integrity": "sha512-foZskBdIHPGPZLfEKqkOP18JgfMy5Duik1TTduvEQ97mX3yfEzr4go1V3oU7ktry0dAL5BiNY38WwRhl+xhy9g==",
|
||||
"version": "4.0.113",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-4.0.113.tgz",
|
||||
"integrity": "sha512-qoeF2ghkYqHY4u68rasZopYsRuGnRwgqSfe6rhC/jM6W73Z7TU5v9QcfDYKt9dgp19YHY9EqiX3SXVC+uPGkRQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "3.0.47",
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@ai-sdk/provider-utils": "4.0.15",
|
||||
"@ai-sdk/anthropic": "3.0.81",
|
||||
"@ai-sdk/openai": "3.0.68",
|
||||
"@ai-sdk/provider": "3.0.10",
|
||||
"@ai-sdk/provider-utils": "4.0.27",
|
||||
"@smithy/eventstream-codec": "^4.0.1",
|
||||
"@smithy/util-utf8": "^4.0.0",
|
||||
"aws4fetch": "^1.0.20"
|
||||
@@ -141,6 +142,67 @@
|
||||
"zod": "^3.25.76 || ^4.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/anthropic": {
|
||||
"version": "3.0.81",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-3.0.81.tgz",
|
||||
"integrity": "sha512-B1JDd9Ugq9R5AgIaW3674lhGCMMYJcPUxnrZh8fzbGojgg4QvHFRv6eZahGQAUsmGHbcf74G9bdSBDLWQGY2GA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.10",
|
||||
"@ai-sdk/provider-utils": "4.0.27"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.76 || ^4.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/openai": {
|
||||
"version": "3.0.68",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.68.tgz",
|
||||
"integrity": "sha512-FCs/DPr4M95UyZ/ABHJmTmCEYRCka/4J0Bna0nsd78QCdGIS0X/zhn+fVzB7mZJo7464uOWYUjROx9PGNGOb0w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.10",
|
||||
"@ai-sdk/provider-utils": "4.0.27"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.76 || ^4.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.10.tgz",
|
||||
"integrity": "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"json-schema": "^0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": {
|
||||
"version": "4.0.27",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.27.tgz",
|
||||
"integrity": "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.10",
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"eventsource-parser": "^3.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.76 || ^4.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ai-sdk/anthropic": {
|
||||
"version": "3.0.47",
|
||||
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-3.0.47.tgz",
|
||||
@@ -2243,9 +2305,6 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2263,9 +2322,6 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2283,9 +2339,6 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2303,9 +2356,6 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -4898,9 +4948,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -4917,9 +4964,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -4936,9 +4980,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -4955,9 +4996,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -8304,9 +8342,6 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -13936,9 +13971,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eventsource-parser": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
|
||||
"integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz",
|
||||
"integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -16613,9 +16648,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -16799,9 +16831,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -16822,9 +16851,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -16845,9 +16871,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
||||
21
tests/unit/ssrf-protection.test.ts
Normal file
21
tests/unit/ssrf-protection.test.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { isPrivateUrl } from "@/lib/ssrf-protection"
|
||||
|
||||
describe("isPrivateUrl", () => {
|
||||
it("blocks private IPv6 URLs", () => {
|
||||
expect(isPrivateUrl("http://[::1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[0:0:0:0:0:0:0:1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[::]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[::ffff:127.0.0.1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[fc00::1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[fd12:3456:789a::1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[fe80::1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[fe9f::1]/")).toBe(true)
|
||||
expect(isPrivateUrl("http://[febf::1]/")).toBe(true)
|
||||
})
|
||||
|
||||
it("allows public URLs", () => {
|
||||
expect(isPrivateUrl("https://example.com/article")).toBe(false)
|
||||
expect(isPrivateUrl("https://fc00.example.com/article")).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user