fix: Together/Jina に SSRF ガード + Jina レスポンスサイズ上限 1MB
This commit is contained in:
parent
5a3a510331
commit
5de1174363
13
server.js
13
server.js
|
|
@ -385,7 +385,11 @@ async function fetchFullTextViaJina(url) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// レスポンスサイズを 1MB に制限(AI 分析に必要な本文量の上限)
|
||||||
|
const jinaContentLength = parseInt(jinaResponse.headers.get('content-length') || '0', 10);
|
||||||
|
if (jinaContentLength > 1024 * 1024) return null;
|
||||||
let markdown = await jinaResponse.text();
|
let markdown = await jinaResponse.text();
|
||||||
|
if (markdown.length > 1024 * 1024) markdown = markdown.slice(0, 1024 * 1024);
|
||||||
|
|
||||||
// Markdown Content: マーカーの後ろを抽出
|
// Markdown Content: マーカーの後ろを抽出
|
||||||
const contentMarker = 'Markdown Content:';
|
const contentMarker = 'Markdown Content:';
|
||||||
|
|
@ -2322,7 +2326,7 @@ ${excerpt}
|
||||||
|
|
||||||
// fire-and-forget アーカイブ: Jina Reader → Gemini 要約(直列)
|
// fire-and-forget アーカイブ: Jina Reader → Gemini 要約(直列)
|
||||||
async function archiveShare(shareId, url) {
|
async function archiveShare(shareId, url) {
|
||||||
if (!url) {
|
if (!url || !isSsrfSafe(url)) {
|
||||||
await pool.query(`UPDATE together_shares SET archive_status='failed' WHERE id=$1`, [shareId]);
|
await pool.query(`UPDATE together_shares SET archive_status='failed' WHERE id=$1`, [shareId]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2332,7 +2336,9 @@ ${excerpt}
|
||||||
signal: AbortSignal.timeout(30000),
|
signal: AbortSignal.timeout(30000),
|
||||||
});
|
});
|
||||||
if (!jinaRes.ok) throw new Error(`Jina ${jinaRes.status}`);
|
if (!jinaRes.ok) throw new Error(`Jina ${jinaRes.status}`);
|
||||||
const fullContent = await jinaRes.text();
|
let fullContent = await jinaRes.text();
|
||||||
|
// レスポンスサイズを 1MB に制限(DB の full_content カラムおよびGemini入力量の上限)
|
||||||
|
if (fullContent.length > 1024 * 1024) fullContent = fullContent.slice(0, 1024 * 1024);
|
||||||
|
|
||||||
// Jina Reader のレスポンス先頭から "Title: ..." を抽出
|
// Jina Reader のレスポンス先頭から "Title: ..." を抽出
|
||||||
const titleMatch = fullContent.match(/^Title:\s*(.+)/m);
|
const titleMatch = fullContent.match(/^Title:\s*(.+)/m);
|
||||||
|
|
@ -2452,8 +2458,7 @@ ${excerpt}
|
||||||
const { group_id, shared_by, url = null, title = null, message = '', tags = [] } = req.body || {};
|
const { group_id, shared_by, url = null, title = null, message = '', tags = [] } = req.body || {};
|
||||||
if (!group_id || !shared_by) return res.status(400).json({ error: 'group_id と shared_by は必須です' });
|
if (!group_id || !shared_by) return res.status(400).json({ error: 'group_id と shared_by は必須です' });
|
||||||
if (url) {
|
if (url) {
|
||||||
try { const p = new URL(url); if (!['http:', 'https:'].includes(p.protocol)) throw new Error(); }
|
if (!isSsrfSafe(url)) return res.status(400).json({ error: 'url は http/https のみ有効です' });
|
||||||
catch { return res.status(400).json({ error: 'url は http/https のみ有効です' }); }
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const grpCheck = await pool.query('SELECT id FROM together_groups WHERE id=$1', [group_id]);
|
const grpCheck = await pool.query('SELECT id FROM together_groups WHERE id=$1', [group_id]);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue