@askalf/dario 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +1 -1
- package/dist/proxy.js +17 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,7 +146,7 @@ curl http://localhost:3456/v1/messages \
|
|
|
146
146
|
-H "Content-Type: application/json" \
|
|
147
147
|
-H "anthropic-version: 2023-06-01" \
|
|
148
148
|
-d '{
|
|
149
|
-
"model": "claude-
|
|
149
|
+
"model": "claude-opus-4-6",
|
|
150
150
|
"max_tokens": 1024,
|
|
151
151
|
"stream": true,
|
|
152
152
|
"messages": [{"role": "user", "content": "Write a haiku about APIs"}]
|
package/dist/cli.js
CHANGED
|
@@ -152,7 +152,7 @@ async function help() {
|
|
|
152
152
|
Example with curl:
|
|
153
153
|
curl http://localhost:3456/v1/messages \\
|
|
154
154
|
-H "Content-Type: application/json" \\
|
|
155
|
-
-d '{"model":"claude-
|
|
155
|
+
-d '{"model":"claude-opus-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'
|
|
156
156
|
|
|
157
157
|
Your subscription handles the billing. No API key needed.
|
|
158
158
|
Tokens auto-refresh in the background — set it and forget it.
|
package/dist/proxy.js
CHANGED
|
@@ -62,9 +62,9 @@ export async function startProxy(opts = {}) {
|
|
|
62
62
|
res.end(JSON.stringify(s));
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
// Only allow proxying to /v1/* paths — block path traversal
|
|
65
|
+
// Only allow proxying to /v1/* paths — block path traversal and SSRF
|
|
66
66
|
const urlPath = req.url?.split('?')[0] ?? '';
|
|
67
|
-
if (!urlPath.startsWith(ALLOWED_PATH_PREFIX)) {
|
|
67
|
+
if (!urlPath.startsWith(ALLOWED_PATH_PREFIX) || urlPath.includes('..') || urlPath.includes('//')) {
|
|
68
68
|
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
69
69
|
res.end(JSON.stringify({ error: 'Forbidden', message: `Only ${ALLOWED_PATH_PREFIX}* paths are proxied` }));
|
|
70
70
|
return;
|
|
@@ -96,8 +96,18 @@ export async function startProxy(opts = {}) {
|
|
|
96
96
|
if (verbose) {
|
|
97
97
|
console.log(`[dario] #${requestCount} ${req.method} ${req.url}`);
|
|
98
98
|
}
|
|
99
|
-
// Forward to Anthropic
|
|
100
|
-
const targetUrl =
|
|
99
|
+
// Forward to Anthropic — construct URL safely to prevent SSRF
|
|
100
|
+
const targetUrl = new URL(urlPath, ANTHROPIC_API);
|
|
101
|
+
// Preserve query string from original request
|
|
102
|
+
const queryString = req.url?.includes('?') ? req.url.split('?')[1] : '';
|
|
103
|
+
if (queryString)
|
|
104
|
+
targetUrl.search = queryString;
|
|
105
|
+
// Verify the constructed URL still points to Anthropic (defense in depth)
|
|
106
|
+
if (targetUrl.origin !== ANTHROPIC_API) {
|
|
107
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
108
|
+
res.end(JSON.stringify({ error: 'Forbidden' }));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
101
111
|
// Merge any client-provided beta flags with the required oauth flag
|
|
102
112
|
const clientBeta = req.headers['anthropic-beta'];
|
|
103
113
|
const betaFlags = new Set(['oauth-2025-04-20']);
|
|
@@ -115,7 +125,7 @@ export async function startProxy(opts = {}) {
|
|
|
115
125
|
'anthropic-beta': [...betaFlags].join(','),
|
|
116
126
|
'x-app': 'cli',
|
|
117
127
|
};
|
|
118
|
-
const upstream = await fetch(targetUrl, {
|
|
128
|
+
const upstream = await fetch(targetUrl.toString(), {
|
|
119
129
|
method: req.method ?? 'POST',
|
|
120
130
|
headers,
|
|
121
131
|
body: body.length > 0 ? body : undefined,
|
|
@@ -173,9 +183,10 @@ export async function startProxy(opts = {}) {
|
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
catch (err) {
|
|
186
|
+
// Log full error server-side, return generic message to client
|
|
176
187
|
console.error('[dario] Proxy error:', sanitizeError(err));
|
|
177
188
|
res.writeHead(502, { 'Content-Type': 'application/json' });
|
|
178
|
-
res.end(JSON.stringify({ error: 'Proxy error', message:
|
|
189
|
+
res.end(JSON.stringify({ error: 'Proxy error', message: 'Failed to reach upstream API' }));
|
|
179
190
|
}
|
|
180
191
|
});
|
|
181
192
|
server.listen(port, LOCALHOST, () => {
|