annosearch 0.3.5 → 0.3.7
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 +30 -1
- package/dist/AnnoSearch.js +1 -1
- package/dist/AnnoSearch.js.map +1 -1
- package/dist/highlight.js +2 -1
- package/dist/highlight.js.map +1 -1
- package/dist/middleware/sanitize.js +35 -0
- package/dist/middleware/sanitize.js.map +1 -0
- package/dist/search.js +22 -7
- package/dist/search.js.map +1 -1
- package/dist/server.js +3 -0
- package/dist/server.js.map +1 -1
- package/dist/utils.js +86 -1
- package/dist/utils.js.map +1 -1
- package/dist/validate.js +18 -0
- package/dist/validate.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,12 +74,41 @@ After Quickwit finishes ingesting and indexing the data we can perform a search.
|
|
|
74
74
|
|
|
75
75
|
## Usage
|
|
76
76
|
|
|
77
|
+
### Installation
|
|
78
|
+
|
|
77
79
|
Make sure you have Quickwit installed and [running](https://quickwit.io/docs/get-started/quickstart) and then install AnnoSearch.
|
|
78
80
|
|
|
79
81
|
```bash
|
|
80
82
|
npm install -g annosearch
|
|
81
83
|
```
|
|
82
84
|
|
|
85
|
+
### Deployment
|
|
86
|
+
|
|
87
|
+
Once you have created your data and are ready to deploy you can use Docker to start the service and serve the qwdata directory containing the Quickwit data.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
docker compose up
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Call the version endpoint to check the service is running.
|
|
94
|
+
```bash
|
|
95
|
+
❯ http :3000/version
|
|
96
|
+
HTTP/1.1 200 OK
|
|
97
|
+
Access-Control-Allow-Credentials: true
|
|
98
|
+
Access-Control-Allow-Origin: *
|
|
99
|
+
Connection: keep-alive
|
|
100
|
+
Content-Length: 19
|
|
101
|
+
Content-Type: application/json; charset=utf-8
|
|
102
|
+
Date: Wed, 11 Jun 2025 13:01:46 GMT
|
|
103
|
+
ETag: W/"13-iZUY2mYGnAauZNa8YzHxtZrPkFE"
|
|
104
|
+
Keep-Alive: timeout=5
|
|
105
|
+
X-Powered-By: Express
|
|
106
|
+
|
|
107
|
+
{
|
|
108
|
+
"version": "0.3.6"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
83
112
|
### Commands
|
|
84
113
|
|
|
85
114
|
#### `init`
|
|
@@ -155,7 +184,7 @@ Configure AnnoSearch by setting the following environment variables:
|
|
|
155
184
|
- **Default**: `3000`
|
|
156
185
|
|
|
157
186
|
- **`ANNOSEARCH_HOST`**: Host on which AnnoSearch runs.
|
|
158
|
-
- **Default**: `
|
|
187
|
+
- **Default**: `0.0.0.0`
|
|
159
188
|
|
|
160
189
|
- **`ANNOSEARCH_PUBLIC_URL`**: URL for public-facing server requests.
|
|
161
190
|
- **Default**: `http://localhost:3000`
|
package/dist/AnnoSearch.js
CHANGED
|
@@ -18,7 +18,7 @@ function loadConfig() {
|
|
|
18
18
|
return {
|
|
19
19
|
maxHits: parseInt(process.env.ANNOSEARCH_MAX_HITS || '20'),
|
|
20
20
|
port: parseInt(process.env.ANNOSEARCH_PORT || '3000'),
|
|
21
|
-
host: process.env.ANNOSEARCH_HOST || '
|
|
21
|
+
host: process.env.ANNOSEARCH_HOST || '0.0.0.0',
|
|
22
22
|
corsOrigin: process.env.ANNOSEARCH_CORS_ORIGIN || '*',
|
|
23
23
|
searchUrl: process.env.ANNOSEARCH_PUBLIC_URL || 'http://localhost:3000',
|
|
24
24
|
};
|
package/dist/AnnoSearch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnoSearch.js","sourceRoot":"","sources":["../src/AnnoSearch.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,qCAAyD;AACzD,qCAAsE;AACtE,iCAAmD;AACnD,qCAAyD;AACzD,iCAAmD;AAUnD,SAAS,UAAU;IACf,OAAO;QACH,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC;QAC1D,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,CAAC;QACrD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,
|
|
1
|
+
{"version":3,"file":"AnnoSearch.js","sourceRoot":"","sources":["../src/AnnoSearch.ts"],"names":[],"mappings":"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"}
|
package/dist/highlight.js
CHANGED
|
@@ -101,7 +101,8 @@ function highlightTerms(annotation_page, query, snippetLength = 25) {
|
|
|
101
101
|
: lang;
|
|
102
102
|
if (bodyValue) {
|
|
103
103
|
for (const term of terms) { // Process each term separately
|
|
104
|
-
const
|
|
104
|
+
const escapedTerm = (0, utils_1.escapeRegex)(term); // Escape special characters in the term
|
|
105
|
+
const regex = new RegExp(`\\b(${escapedTerm})\\b`, "gi"); // Global + Case-Insensitive
|
|
105
106
|
let match;
|
|
106
107
|
while ((match = regex.exec(bodyValue)) !== null) { // Iterate all matches for the term
|
|
107
108
|
const exactMatch = match[0]; // Capture the exact match from the original text
|
package/dist/highlight.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeInputs = sanitizeInputs;
|
|
4
|
+
exports.addSecurityHeaders = addSecurityHeaders;
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
/**
|
|
7
|
+
* Middleware to sanitize input parameters and remove potentially dangerous characters
|
|
8
|
+
*/
|
|
9
|
+
function sanitizeInputs(req, res, next) {
|
|
10
|
+
try {
|
|
11
|
+
// Sanitize query parameters
|
|
12
|
+
for (const [key, value] of Object.entries(req.query)) {
|
|
13
|
+
if (typeof value === 'string') {
|
|
14
|
+
// Remove null bytes and control characters
|
|
15
|
+
const sanitized = value.replace(/[\x00-\x1f\x7f-\x9f]/g, '');
|
|
16
|
+
req.query[key] = sanitized;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
next();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new errors_1.AnnoSearchValidationError('Invalid input detected');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Middleware to add security headers
|
|
27
|
+
*/
|
|
28
|
+
function addSecurityHeaders(req, res, next) {
|
|
29
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
30
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
31
|
+
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
32
|
+
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
33
|
+
next();
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/middleware/sanitize.ts"],"names":[],"mappings":";;AAMA,wCAcC;AAKD,gDAMC;AA9BD,sCAAsD;AAEtD;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC1E,IAAI,CAAC;QACD,4BAA4B;QAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,2CAA2C;gBAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;gBAC7D,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YAC/B,CAAC;QACL,CAAC;QACD,IAAI,EAAE,CAAC;IACX,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,kCAAyB,CAAC,wBAAwB,CAAC,CAAC;IAClE,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC9E,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACzC,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC;AACX,CAAC"}
|
package/dist/search.js
CHANGED
|
@@ -16,6 +16,7 @@ const errors_1 = require("./errors");
|
|
|
16
16
|
const iiif_1 = require("./iiif");
|
|
17
17
|
const validate_1 = require("./validate");
|
|
18
18
|
const highlight_1 = require("./highlight");
|
|
19
|
+
const utils_1 = require("./utils");
|
|
19
20
|
const contentType = 'application/json';
|
|
20
21
|
const quickwitClient = (0, quickwit_1.createClient)(contentType);
|
|
21
22
|
function buildDateQueryFromString(dateRangesString) {
|
|
@@ -28,22 +29,35 @@ function buildDateQueryFromString(dateRangesString) {
|
|
|
28
29
|
if (!start || !end) {
|
|
29
30
|
throw new errors_1.AnnoSearchValidationError(`Invalid date range format: ${range}`);
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
// Escape the date values to prevent injection
|
|
33
|
+
const escapedStart = (0, utils_1.escapeQuickwitQuery)(start);
|
|
34
|
+
const escapedEnd = (0, utils_1.escapeQuickwitQuery)(end);
|
|
35
|
+
return `created:[${escapedStart} TO ${escapedEnd}]`;
|
|
32
36
|
})
|
|
33
37
|
.join(" OR ");
|
|
34
38
|
}
|
|
35
39
|
function buildUserQueryFromString(userString) {
|
|
36
|
-
// Split the string into an array using space as the delimiter
|
|
37
40
|
const users = userString.split(" ");
|
|
38
|
-
// Map each user into a Quickwit-compatible query fragment
|
|
39
41
|
return users
|
|
40
|
-
.map(user =>
|
|
42
|
+
.map(user => {
|
|
43
|
+
const sanitizedUser = (0, utils_1.escapeQuickwitQuery)(user.trim());
|
|
44
|
+
if (!sanitizedUser)
|
|
45
|
+
return null;
|
|
46
|
+
return `(creator:"${sanitizedUser}" OR creator.id:"${sanitizedUser}")`;
|
|
47
|
+
})
|
|
48
|
+
.filter(Boolean)
|
|
41
49
|
.join(" OR ");
|
|
42
50
|
}
|
|
43
51
|
function buildSearchQueryFromString(qString) {
|
|
44
52
|
const terms = qString.split(" ");
|
|
45
53
|
return terms
|
|
46
|
-
.map(term =>
|
|
54
|
+
.map(term => {
|
|
55
|
+
const sanitizedTerm = (0, utils_1.escapeQuickwitQuery)(term.trim());
|
|
56
|
+
if (!sanitizedTerm)
|
|
57
|
+
return null;
|
|
58
|
+
return `(body.value:"${sanitizedTerm}")`;
|
|
59
|
+
})
|
|
60
|
+
.filter(Boolean)
|
|
47
61
|
.join(" AND ");
|
|
48
62
|
}
|
|
49
63
|
function searchIndex(indexId, q, motivation, maxHits, page, searchUrl, date, user) {
|
|
@@ -57,7 +71,7 @@ function searchIndex(indexId, q, motivation, maxHits, page, searchUrl, date, use
|
|
|
57
71
|
(0, validate_1.validateMotivation)(motivation);
|
|
58
72
|
(0, validate_1.validateUser)(user);
|
|
59
73
|
const qQuery = buildSearchQueryFromString(q);
|
|
60
|
-
const motivationQuery = motivation ? ` AND motivation:"${motivation}"` : '';
|
|
74
|
+
const motivationQuery = motivation ? ` AND motivation:"${(0, utils_1.escapeQuickwitQuery)(motivation)}"` : '';
|
|
61
75
|
const dateQuery = date ? ` AND (${buildDateQueryFromString(date)})` : '';
|
|
62
76
|
const userQuery = user ? ` AND (${buildUserQueryFromString(user)})` : '';
|
|
63
77
|
const fullQuery = `${qQuery}${motivationQuery}${dateQuery}${userQuery}`;
|
|
@@ -77,7 +91,8 @@ function searchIndex(indexId, q, motivation, maxHits, page, searchUrl, date, use
|
|
|
77
91
|
});
|
|
78
92
|
}
|
|
79
93
|
function buildAutocompleteQueryFromString(qString) {
|
|
80
|
-
|
|
94
|
+
const sanitizedQuery = (0, utils_1.escapeQuickwitQuery)(qString.trim());
|
|
95
|
+
return `term:${sanitizedQuery}*`;
|
|
81
96
|
}
|
|
82
97
|
function searchAutocomplete(indexId, q, maxHits, searchUrl, ignoredParams) {
|
|
83
98
|
return __awaiter(this, void 0, void 0, function* () {
|
package/dist/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -72,6 +72,9 @@ function serve(client) {
|
|
|
72
72
|
const host = client.getHost();
|
|
73
73
|
const corsOrigin = client.getCorsOrigin();
|
|
74
74
|
app.use((0, pino_http_1.default)({ logger: logger_1.default }));
|
|
75
|
+
// Add security middleware
|
|
76
|
+
app.use(utils_1.addSecurityHeaders);
|
|
77
|
+
app.use(utils_1.sanitizeInputs);
|
|
75
78
|
app.use((0, cors_1.default)({
|
|
76
79
|
origin: corsOrigin, // Allow only specified origin
|
|
77
80
|
methods: ['GET', 'POST', 'OPTIONS'], // Allowed methods
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,8CAWC;AAED,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.js
CHANGED
|
@@ -19,6 +19,13 @@ exports.handleWebError = handleWebError;
|
|
|
19
19
|
exports.fetchJson = fetchJson;
|
|
20
20
|
exports.createJsonl = createJsonl;
|
|
21
21
|
exports.normalizeTerm = normalizeTerm;
|
|
22
|
+
exports.escapeRegex = escapeRegex;
|
|
23
|
+
exports.escapeQuickwitQuery = escapeQuickwitQuery;
|
|
24
|
+
exports.sanitizeFieldValue = sanitizeFieldValue;
|
|
25
|
+
exports.validateNoSpecialChars = validateNoSpecialChars;
|
|
26
|
+
exports.validateQueryComplexity = validateQueryComplexity;
|
|
27
|
+
exports.sanitizeInputs = sanitizeInputs;
|
|
28
|
+
exports.addSecurityHeaders = addSecurityHeaders;
|
|
22
29
|
const axios_1 = __importDefault(require("axios"));
|
|
23
30
|
const errors_1 = require("./errors");
|
|
24
31
|
const axios_2 = require("axios");
|
|
@@ -124,6 +131,84 @@ function normalizeTerm(term) {
|
|
|
124
131
|
return term
|
|
125
132
|
.trim()
|
|
126
133
|
.toLowerCase()
|
|
127
|
-
|
|
134
|
+
// More restrictive: only allow letters, numbers, and safe punctuation
|
|
135
|
+
.replace(/^[^\p{L}\p{N}\-_.]+|[^\p{L}\p{N}\-_.]+$/gu, "")
|
|
136
|
+
// Remove any remaining potentially dangerous characters
|
|
137
|
+
.replace(/[{}[\]()~*?\\+"`]/g, "");
|
|
138
|
+
}
|
|
139
|
+
function escapeRegex(term) {
|
|
140
|
+
// Escape special characters in the term to make it regex-safe
|
|
141
|
+
return term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Escape special Quickwit query characters to prevent DSL injection
|
|
145
|
+
*/
|
|
146
|
+
function escapeQuickwitQuery(input) {
|
|
147
|
+
// Escape special Quickwit query characters
|
|
148
|
+
return input.replace(/\\/g, '\\\\')
|
|
149
|
+
.replace(/"/g, '\\"')
|
|
150
|
+
.replace(/'/g, "\\'")
|
|
151
|
+
.replace(/[+~*?{}[\]()]/g, '\\$&');
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* More aggressive sanitization for field values
|
|
155
|
+
*/
|
|
156
|
+
function sanitizeFieldValue(value) {
|
|
157
|
+
return value.replace(/[^a-zA-Z0-9\s\-_.@]/g, '');
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Validate that input doesn't contain potentially dangerous characters
|
|
161
|
+
*/
|
|
162
|
+
function validateNoSpecialChars(input) {
|
|
163
|
+
const dangerousChars = /[{}[\]()~*?\\+"`]/;
|
|
164
|
+
if (dangerousChars.test(input)) {
|
|
165
|
+
throw new errors_1.AnnoSearchValidationError('Input contains invalid characters');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Validate query complexity to prevent complex injection attacks
|
|
170
|
+
*/
|
|
171
|
+
function validateQueryComplexity(query) {
|
|
172
|
+
const termCount = query.split(/\s+/).length;
|
|
173
|
+
const operatorCount = (query.match(/\b(AND|OR|NOT)\b/gi) || []).length;
|
|
174
|
+
const parenthesesCount = (query.match(/[()]/g) || []).length;
|
|
175
|
+
if (operatorCount > 10) {
|
|
176
|
+
throw new errors_1.AnnoSearchValidationError('Query too complex: too many operators');
|
|
177
|
+
}
|
|
178
|
+
if (parenthesesCount > 20) {
|
|
179
|
+
throw new errors_1.AnnoSearchValidationError('Query too complex: too many parentheses');
|
|
180
|
+
}
|
|
181
|
+
if (termCount > 20) {
|
|
182
|
+
throw new errors_1.AnnoSearchValidationError('Query too complex: too many terms');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Middleware to sanitize input parameters and remove potentially dangerous characters
|
|
187
|
+
*/
|
|
188
|
+
function sanitizeInputs(req, res, next) {
|
|
189
|
+
try {
|
|
190
|
+
// Sanitize query parameters
|
|
191
|
+
for (const [key, value] of Object.entries(req.query)) {
|
|
192
|
+
if (typeof value === 'string') {
|
|
193
|
+
// Remove null bytes and control characters
|
|
194
|
+
const sanitized = value.replace(/[\x00-\x1f\x7f-\x9f]/g, '');
|
|
195
|
+
req.query[key] = sanitized;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
next();
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
throw new errors_1.AnnoSearchValidationError('Invalid input detected');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Middleware to add security headers
|
|
206
|
+
*/
|
|
207
|
+
function addSecurityHeaders(req, res, next) {
|
|
208
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
209
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
210
|
+
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
211
|
+
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
212
|
+
next();
|
|
128
213
|
}
|
|
129
214
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAQA,8BAEC;AAGD,4BAoBC;AAKD,kCAGC;AAED,wCAwCC;AAID,8BAOC;AAED,kCAMC;AAMD,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/validate.js
CHANGED
|
@@ -25,9 +25,21 @@ function validateSearchQueryParameter(query) {
|
|
|
25
25
|
if (!trimmedQuery) {
|
|
26
26
|
throw new errors_1.AnnoSearchValidationError('Missing query parameter.');
|
|
27
27
|
}
|
|
28
|
+
// Add length limits
|
|
29
|
+
if (trimmedQuery.length > 500) {
|
|
30
|
+
throw new errors_1.AnnoSearchValidationError('Query too long (max 500 characters)');
|
|
31
|
+
}
|
|
32
|
+
// Check for dangerous patterns
|
|
33
|
+
(0, utils_1.validateNoSpecialChars)(trimmedQuery);
|
|
34
|
+
// Check query complexity
|
|
35
|
+
(0, utils_1.validateQueryComplexity)(trimmedQuery);
|
|
28
36
|
const minKeywordLength = 3;
|
|
29
37
|
const whitelistedShortKeywords = new Set(["uk", "ai", "us"]);
|
|
30
38
|
const keywords = trimmedQuery.split(/\s+/);
|
|
39
|
+
// Limit number of terms
|
|
40
|
+
if (keywords.length > 20) {
|
|
41
|
+
throw new errors_1.AnnoSearchValidationError('Too many search terms (max 20)');
|
|
42
|
+
}
|
|
31
43
|
for (const keyword of keywords) {
|
|
32
44
|
const normalizedKeyword = (0, utils_1.normalizeTerm)(keyword);
|
|
33
45
|
if (normalizedKeyword.length < minKeywordLength && !whitelistedShortKeywords.has(normalizedKeyword)) {
|
|
@@ -40,7 +52,13 @@ function validateSearchQueryParameter(query) {
|
|
|
40
52
|
}
|
|
41
53
|
function validateAutocompleteQueryParameter(query) {
|
|
42
54
|
const minQueryLength = 3;
|
|
55
|
+
const maxQueryLength = 100; // Add max length
|
|
43
56
|
const trimmedQuery = query.trim();
|
|
57
|
+
if (trimmedQuery.length > maxQueryLength) {
|
|
58
|
+
throw new errors_1.AnnoSearchValidationError(`Autocomplete query too long (max ${maxQueryLength} characters)`);
|
|
59
|
+
}
|
|
60
|
+
// Check for dangerous patterns
|
|
61
|
+
(0, utils_1.validateNoSpecialChars)(trimmedQuery);
|
|
44
62
|
const normalizedQuery = (0, utils_1.normalizeTerm)(trimmedQuery);
|
|
45
63
|
if (!normalizedQuery) {
|
|
46
64
|
throw new errors_1.AnnoSearchValidationError('Missing autocomplete query parameter after normalization.');
|
package/dist/validate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":";;;AAaA,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":";;;AAaA,oEAmCC;AAGD,gFAsBC;AAID,wCAIC;AAED,gDAIC;AAED,0CAIC;AAED,gDASC;AAED,gDAwBC;AAGD,oCAYC;AAjJD,qCAAqD;AACrD,mCAAyF;AAE5E,QAAA,WAAW,GAAG;IACvB,UAAU;IACV,eAAe;IACf,iBAAiB;IACjB,cAAc;IACd,cAAc;IACd,YAAY;IACZ,SAAS;CACZ,CAAC;AAEF,SAAgB,4BAA4B,CAAC,KAAa;IACtD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,MAAM,IAAI,kCAAyB,CAAC,0BAA0B,CAAC,CAAC;IACpE,CAAC;IAED,oBAAoB;IACpB,IAAI,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,kCAAyB,CAAC,qCAAqC,CAAC,CAAC;IAC/E,CAAC;IAED,+BAA+B;IAC/B,IAAA,8BAAsB,EAAC,YAAY,CAAC,CAAC;IAErC,yBAAyB;IACzB,IAAA,+BAAuB,EAAC,YAAY,CAAC,CAAC;IAEtC,MAAM,gBAAgB,GAAG,CAAC,CAAC;IAC3B,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE3C,wBAAwB;IACxB,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,kCAAyB,CAAC,gCAAgC,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,iBAAiB,GAAG,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;QACjD,IAAI,iBAAiB,CAAC,MAAM,GAAG,gBAAgB,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClG,MAAM,IAAI,kCAAyB,CAAC,YAAY,OAAO,sBAAsB,gBAAgB,mBAAmB,CAAC,CAAC;QACtH,CAAC;QACD,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrB,MAAM,IAAI,kCAAyB,CAAC,YAAY,OAAO,qEAAqE,CAAC,CAAC;QAClI,CAAC;IACL,CAAC;AACL,CAAC;AAGD,SAAgB,kCAAkC,CAAC,KAAa;IAC5D,MAAM,cAAc,GAAG,CAAC,CAAC;IACzB,MAAM,cAAc,GAAG,GAAG,CAAC,CAAC,iBAAiB;IAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAElC,IAAI,YAAY,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QACvC,MAAM,IAAI,kCAAyB,CAAC,oCAAoC,cAAc,cAAc,CAAC,CAAC;IAC1G,CAAC;IAED,+BAA+B;IAC/B,IAAA,8BAAsB,EAAC,YAAY,CAAC,CAAC;IAErC,MAAM,eAAe,GAAG,IAAA,qBAAa,EAAC,YAAY,CAAC,CAAC;IACpD,IAAI,CAAC,eAAe,EAAE,CAAC;QACnB,MAAM,IAAI,kCAAyB,CAAC,2DAA2D,CAAC,CAAC;IACrG,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,kCAAyB,CAAC,6CAA6C,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,eAAe,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAC1C,MAAM,IAAI,kCAAyB,CAAC,uCAAuC,cAAc,mBAAmB,CAAC,CAAC;IAClH,CAAC;AACL,CAAC;AAID,SAAgB,cAAc,CAAC,MAAc;IACzC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,IAAI,kCAAyB,CAAC,gBAAgB,CAAC,CAAC;IAC1D,CAAC;AACL,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAkB;IACjD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,kCAAyB,CAAC,0DAA0D,CAAC,CAAC;IACpG,CAAC;AACL,CAAC;AAED,SAAgB,eAAe,CAAC,OAAe;IAC3C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,kCAAyB,CAAC,6DAA6D,CAAC,CAAC;IACvG,CAAC;AACL,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAkB;IACjD,2BAA2B;IAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO;IACX,CAAC;IAED,IAAI,CAAC,mBAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,kCAAyB,CAAC,8BAA8B,CAAC,CAAC;IACxE,CAAC;AACL,CAAC;AAED,SAAgB,kBAAkB,CAAC,MAAc;IAC7C,2BAA2B;IAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAM;IACV,CAAC;IACD,4BAA4B;IAC5B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,oEAAoE;IACpE,MAAM,YAAY,GAAG,8EAA8E,CAAC;IACpG,mBAAmB;IACnB,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,kCAAyB,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,8DAA8D;QAC9D,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAE9B,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;YAChF,MAAM,IAAI,kCAAyB,CAAC,uBAAuB,KAAK,EAAE,CAAC,CAAC;QACxE,CAAC;IACL,CAAC;AACL,CAAC;AAGD,SAAgB,YAAY,CAAC,IAAY;IACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO;IACX,CAAC;IACD,2BAA2B;IAC3B,MAAM,UAAU,GAAG,uCAAuC,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,kCAAyB,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;AACL,CAAC"}
|