@stroq/cli 0.15.1 → 0.15.2
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
CHANGED
|
@@ -11561,6 +11561,45 @@ async function newestTranscript(cwd) {
|
|
|
11561
11561
|
// src/sent/scan.ts
|
|
11562
11562
|
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve9 } from "path";
|
|
11563
11563
|
|
|
11564
|
+
// src/sent/heredoc.ts
|
|
11565
|
+
var HEREDOC = /(?<!<)<<(-?)\s*(['"]?)([A-Za-z_][\w.-]*)\2/g;
|
|
11566
|
+
var EXECUTES_STDIN = /^(?:sudo\s+)?(?:(?:\S*\/)?env\s+(?:\S+=\S*\s+)*)?(?:\S*\/)?(?:sh|bash|zsh|dash|ksh|fish|python\d*(?:\.\d+)?|node|deno|bun|tsx|ruby|perl|php|osascript|ssh|eval|source|\.|xargs|npx|pnpm|uv)(?:\s|$)/;
|
|
11567
|
+
function bodyIsExecuted(line3, operatorStart, operatorEnd) {
|
|
11568
|
+
const before = line3.slice(0, operatorStart).split(/&&|\|\||;|\$\(|\|/);
|
|
11569
|
+
const stages = [before[before.length - 1] ?? "", ...line3.slice(operatorEnd).split("|").slice(1)];
|
|
11570
|
+
return stages.some((stage) => EXECUTES_STDIN.test(stage.trim()));
|
|
11571
|
+
}
|
|
11572
|
+
function withoutHeredocData(command) {
|
|
11573
|
+
if (!command.includes("<<")) return command;
|
|
11574
|
+
const lines = command.split("\n");
|
|
11575
|
+
const kept = [];
|
|
11576
|
+
let i = 0;
|
|
11577
|
+
while (i < lines.length) {
|
|
11578
|
+
const line3 = lines[i] ?? "";
|
|
11579
|
+
kept.push(line3);
|
|
11580
|
+
const operators = [...line3.matchAll(HEREDOC)];
|
|
11581
|
+
i += 1;
|
|
11582
|
+
if (operators.length === 0) continue;
|
|
11583
|
+
for (const op of operators) {
|
|
11584
|
+
const dash = op[1] === "-";
|
|
11585
|
+
const delimiter3 = op[3] ?? "";
|
|
11586
|
+
let end = i;
|
|
11587
|
+
while (end < lines.length) {
|
|
11588
|
+
const candidate = lines[end] ?? "";
|
|
11589
|
+
if ((dash ? candidate.replace(/^\t+/, "") : candidate) === delimiter3) break;
|
|
11590
|
+
end += 1;
|
|
11591
|
+
}
|
|
11592
|
+
if (end >= lines.length) return command;
|
|
11593
|
+
const start = op.index;
|
|
11594
|
+
const executed = bodyIsExecuted(line3, start, start + op[0].length);
|
|
11595
|
+
if (executed) kept.push(...lines.slice(i, end));
|
|
11596
|
+
kept.push(lines[end] ?? "");
|
|
11597
|
+
i = end + 1;
|
|
11598
|
+
}
|
|
11599
|
+
}
|
|
11600
|
+
return kept.join("\n");
|
|
11601
|
+
}
|
|
11602
|
+
|
|
11564
11603
|
// src/sent/report.ts
|
|
11565
11604
|
var MAX_OCCURRENCES = 5;
|
|
11566
11605
|
function byTime(a, b) {
|
|
@@ -11628,8 +11667,8 @@ function fileEvidenceFor(tool) {
|
|
|
11628
11667
|
if (SHELL_TOOLS4.has(tool)) return "named";
|
|
11629
11668
|
return null;
|
|
11630
11669
|
}
|
|
11631
|
-
function credentialFilesIn(input, scope, sessionCwd) {
|
|
11632
|
-
const leaves = collectStrings(input);
|
|
11670
|
+
function credentialFilesIn(tool, input, scope, sessionCwd) {
|
|
11671
|
+
const leaves = SHELL_TOOLS4.has(tool) ? collectStrings(input).map(withoutHeredocData) : collectStrings(input);
|
|
11633
11672
|
return scope.sourcePaths.filter(
|
|
11634
11673
|
(path) => spellingsOf(path, scope, sessionCwd).some(
|
|
11635
11674
|
(spelling) => leaves.some((leaf) => mentions(leaf, spelling))
|
|
@@ -11699,7 +11738,7 @@ async function scanTranscript(transcript, source, index, scope) {
|
|
|
11699
11738
|
}
|
|
11700
11739
|
const evidence = fileEvidenceFor(event.tool);
|
|
11701
11740
|
if (evidence !== null) {
|
|
11702
|
-
for (const path of credentialFilesIn(event.input, scope, transcript.cwd)) {
|
|
11741
|
+
for (const path of credentialFilesIn(event.tool, event.input, scope, transcript.cwd)) {
|
|
11703
11742
|
files.push({ path, tool: event.tool, evidence, call, at: event.at });
|
|
11704
11743
|
}
|
|
11705
11744
|
}
|
|
@@ -11742,7 +11781,7 @@ function scanAuditLog(allEntries, sessionId, scope) {
|
|
|
11742
11781
|
const files = entries.filter((e) => e.phase === "post").flatMap((entry2) => {
|
|
11743
11782
|
const evidence = fileEvidenceFor(entry2.tool);
|
|
11744
11783
|
if (evidence === null) return [];
|
|
11745
|
-
return credentialFilesIn({ summary: entry2.summary }, scope, null).map((path) => ({
|
|
11784
|
+
return credentialFilesIn(entry2.tool, { summary: entry2.summary }, scope, null).map((path) => ({
|
|
11746
11785
|
path,
|
|
11747
11786
|
tool: entry2.tool,
|
|
11748
11787
|
evidence,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "stroq",
|
|
3
3
|
"name": "Stroq",
|
|
4
4
|
"description": "Local action firewall for OpenClaw: scans what the agent reads, taints the session, blocks or asks before dangerous tool calls.",
|
|
5
|
-
"version": "0.15.
|
|
5
|
+
"version": "0.15.2",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
package/package.json
CHANGED