nexrall-code 0.5.72 → 0.5.73
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/dist/index.js +61 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10895,7 +10895,25 @@ var require_securityLint = __commonJS({
|
|
|
10895
10895
|
// SCREAMING_SNAKE identifier (an env-var name) is excluded, along with the
|
|
10896
10896
|
// usual placeholder vocabulary. The value must also look like actual secret
|
|
10897
10897
|
// material: mixed case or digits, not a lone lowercase word.
|
|
10898
|
-
|
|
10898
|
+
//
|
|
10899
|
+
// `\{\{` was added after porting this module to the Nexrall backend and
|
|
10900
|
+
// re-measuring there: the only hit across 100 route/service files was
|
|
10901
|
+
// `"x-api-key": "{{PAYOS_API_KEY}}"` inside a connector's DOCUMENTATION
|
|
10902
|
+
// string — a mustache/handlebars placeholder, i.e. the opposite of a leaked
|
|
10903
|
+
// credential. `${...}` was already excluded for exactly this reason; this is
|
|
10904
|
+
// the same idea for the other common templating syntax, and it cannot mask a
|
|
10905
|
+
// real secret because a literal `{{` never appears inside one.
|
|
10906
|
+
//
|
|
10907
|
+
// EXCLUSIONS ARE SCOPED TO THE VALUE (`[^'"`]*`), NOT THE WHOLE LINE (`.*`).
|
|
10908
|
+
// Found by the tests written for the Nexrall backend port: the lookahead
|
|
10909
|
+
// scanned the entire rest of the line, so ANY trailing comment containing a
|
|
10910
|
+
// placeholder word silenced a genuine finding — `const pw = "<real secret>";
|
|
10911
|
+
// // xxx` went SILENT, as did `// test`. An agent writing production code
|
|
10912
|
+
// adds trailing comments constantly, so this was not a rare edge case.
|
|
10913
|
+
// Bounding the lookahead at the closing quote keeps the placeholder
|
|
10914
|
+
// vocabulary matching the VALUE (the only place it was ever meant to) while
|
|
10915
|
+
// making a trailing comment irrelevant.
|
|
10916
|
+
re: /(?:password|passwd|secret|api[_-]?key|apikey|access[_-]?token)['"`]?\s*[:=]\s*['"`](?![A-Z0-9_]+['"`])(?![^'"`]*(?:\$\{|\{\{|process\.env|os\.environ|example|changeme|placeholder|redacted|xxx|test|dummy|fake|sample|your[_-]?|<|\*{3}))(?=[^'"`]*[0-9A-Z])[^'"`\s]{10,}['"`]/,
|
|
10899
10917
|
message: "Hardcoded credential literal. Read it from the environment/secret store instead, and rotate the exposed value.",
|
|
10900
10918
|
includeComments: true
|
|
10901
10919
|
},
|
|
@@ -10925,7 +10943,23 @@ var require_securityLint = __commonJS({
|
|
|
10925
10943
|
// outside: req/request/params/query/body/input/user/args, or a bare
|
|
10926
10944
|
// `'...' + ident`. This trades recall for precision on purpose — thorough SQL
|
|
10927
10945
|
// review is the security-auditor agent's job, not an inline regex's.
|
|
10928
|
-
|
|
10946
|
+
//
|
|
10947
|
+
// THE GAP IS PER-ALTERNATIVE, and that asymmetry is load-bearing. The concat
|
|
10948
|
+
// branch originally shared the no-quote gap, which made it miss the QUOTED
|
|
10949
|
+
// concatenation form — the more dangerous one, since the value lands inside
|
|
10950
|
+
// a string literal where a lone `'` breaks out of the query:
|
|
10951
|
+
//
|
|
10952
|
+
// "DELETE FROM s WHERE t = " + query.token -> flagged
|
|
10953
|
+
// "DELETE FROM s WHERE t = '" + query.token + "'" -> MISSED
|
|
10954
|
+
//
|
|
10955
|
+
// Loosening the gap for ALL branches fixes that but costs precision, measured
|
|
10956
|
+
// on the Nexrall backend: the `${…}` branch then travels PAST the end of the
|
|
10957
|
+
// SQL string to a later interpolation, flagging correctly-parameterised
|
|
10958
|
+
// queries like `UPDATE users SET ${sets.join(',')} WHERE id=$${params.length}`
|
|
10959
|
+
// (0/100 flagged files became 2/100). So only the concat branch gets the loose
|
|
10960
|
+
// gap — it must cross a quote by construction — while the others stay confined
|
|
10961
|
+
// to a single string segment.
|
|
10962
|
+
re: /\b(?:SELECT|INSERT\s+INTO|UPDATE|DELETE\s+FROM)\b(?:[^;'"`]{0,160}(?:\$\{\s*(?:req|request|params?|query|body|input|user|args|ctx)\b|%\s*\(\s*(?:request|params?|query|body|input|user)\b)|[^;]{0,160}['"`]\s*\+\s*(?:req|request|params?|query|body|input|user|args|ctx)\b)/i,
|
|
10929
10963
|
message: "SQL built by interpolating a request-derived value. Use a parameterised query ($1 / ? placeholders) \u2014 this is the classic injection sink."
|
|
10930
10964
|
},
|
|
10931
10965
|
{
|
|
@@ -14510,6 +14544,30 @@ ${lines.join("\n")}`;
|
|
|
14510
14544
|
return { output: `Found ${photos.length} photo(s) for "${query}":
|
|
14511
14545
|
${lines.join("\n")}` };
|
|
14512
14546
|
}
|
|
14547
|
+
async function webSearch(input) {
|
|
14548
|
+
const query = typeof input.query === "string" ? input.query.trim() : "";
|
|
14549
|
+
if (!query)
|
|
14550
|
+
return { error: "Missing required parameter: query" };
|
|
14551
|
+
const token = (0, auth_1.getToken)();
|
|
14552
|
+
if (!token)
|
|
14553
|
+
return { error: "Not authenticated. Run `nexrall-code login` first." };
|
|
14554
|
+
try {
|
|
14555
|
+
const r2 = await _httpsPost(`${client_1.API_BASE}/api/code/tools/web_search`, JSON.stringify({ query }), { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, 3e4);
|
|
14556
|
+
let json = {};
|
|
14557
|
+
try {
|
|
14558
|
+
json = JSON.parse(r2.body);
|
|
14559
|
+
} catch (_) {
|
|
14560
|
+
}
|
|
14561
|
+
if (r2.status !== 200)
|
|
14562
|
+
return { error: json.error || `Server error ${r2.status}` };
|
|
14563
|
+
const text = json.text ?? "";
|
|
14564
|
+
if (!text)
|
|
14565
|
+
return { error: "web_search succeeded but returned no results text." };
|
|
14566
|
+
return { output: text };
|
|
14567
|
+
} catch (err) {
|
|
14568
|
+
return { error: `web_search failed: ${err.message}` };
|
|
14569
|
+
}
|
|
14570
|
+
}
|
|
14513
14571
|
function memoryScopeOf(input) {
|
|
14514
14572
|
return input.scope === "global" ? "global" : "project";
|
|
14515
14573
|
}
|
|
@@ -14605,6 +14663,7 @@ ${expanded}` };
|
|
|
14605
14663
|
move_file: moveFile,
|
|
14606
14664
|
delete_file: deleteFile,
|
|
14607
14665
|
fetch_url: fetchUrl,
|
|
14666
|
+
web_search: webSearch,
|
|
14608
14667
|
generate_image: generateImage,
|
|
14609
14668
|
stock_photo: stockPhoto,
|
|
14610
14669
|
todo_write: todoWrite,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexrall-code",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.73",
|
|
4
4
|
"description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"release": "node build.js && node scripts/upload-release.cjs"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@nexrall/code-core": "^1.4.
|
|
42
|
+
"@nexrall/code-core": "^1.4.43",
|
|
43
43
|
"chalk": "^5.3.0",
|
|
44
44
|
"commander": "^12.0.0",
|
|
45
45
|
"diff": "^5.2.0",
|