security: fix 5 review findings (2 high, 3 medium)
HIGH: - Lock setup TOTP/NAS endpoints behind _require_setup() guard (prevented unauthenticated admin 2FA takeover after setup) - Sanitize upload filename with Path().name + resolve() validation (prevented path traversal writing outside Inbox) MEDIUM: - Add score > 0.01 filter to hybrid search via subquery (prevented returning irrelevant documents with zero score) - Implement Inbox → Knowledge file move after classification (classify_worker now moves files based on ai_domain) - Add Anthropic Messages API support in _request() (premium/Claude path now sends correct format and parses content[0].text instead of choices[0].message.content) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -165,23 +165,26 @@ async def _search_hybrid(session: AsyncSession, query: str, limit: int) -> list[
|
||||
|
||||
result = await session.execute(
|
||||
text(f"""
|
||||
SELECT d.id, d.title, d.ai_domain, d.ai_summary, d.file_format,
|
||||
(
|
||||
:w_fts * coalesce(ts_rank(
|
||||
to_tsvector('simple', coalesce(d.title, '') || ' ' || coalesce(d.extracted_text, '')),
|
||||
plainto_tsquery('simple', :query)
|
||||
), 0)
|
||||
+ :w_trgm * coalesce(similarity(
|
||||
coalesce(d.title, '') || ' ' || coalesce(d.extracted_text, ''),
|
||||
:query
|
||||
), 0)
|
||||
+ :w_vector * {vector_score}
|
||||
) AS score,
|
||||
left(d.extracted_text, 200) AS snippet
|
||||
FROM documents d
|
||||
{vector_clause}
|
||||
WHERE coalesce(d.extracted_text, '') != ''
|
||||
ORDER BY score DESC
|
||||
SELECT * FROM (
|
||||
SELECT d.id, d.title, d.ai_domain, d.ai_summary, d.file_format,
|
||||
(
|
||||
:w_fts * coalesce(ts_rank(
|
||||
to_tsvector('simple', coalesce(d.title, '') || ' ' || coalesce(d.extracted_text, '')),
|
||||
plainto_tsquery('simple', :query)
|
||||
), 0)
|
||||
+ :w_trgm * coalesce(similarity(
|
||||
coalesce(d.title, '') || ' ' || coalesce(d.extracted_text, ''),
|
||||
:query
|
||||
), 0)
|
||||
+ :w_vector * {vector_score}
|
||||
) AS score,
|
||||
left(d.extracted_text, 200) AS snippet
|
||||
FROM documents d
|
||||
{vector_clause}
|
||||
WHERE coalesce(d.extracted_text, '') != ''
|
||||
) sub
|
||||
WHERE sub.score > 0.01
|
||||
ORDER BY sub.score DESC
|
||||
LIMIT :limit
|
||||
"""),
|
||||
params,
|
||||
|
||||
Reference in New Issue
Block a user