@stroq/cli 0.15.0 → 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
|
@@ -11467,6 +11467,7 @@ async function readCursorSession(path) {
|
|
|
11467
11467
|
var HEAD_BYTES = 64 * 1024;
|
|
11468
11468
|
var claudeCodeReader = {
|
|
11469
11469
|
agent: "claude-code",
|
|
11470
|
+
label: "Claude Code",
|
|
11470
11471
|
find: findTranscripts,
|
|
11471
11472
|
read: readTranscript,
|
|
11472
11473
|
root: "~/.claude/projects",
|
|
@@ -11481,6 +11482,7 @@ var claudeCodeReader = {
|
|
|
11481
11482
|
};
|
|
11482
11483
|
var codexReader = {
|
|
11483
11484
|
agent: "codex",
|
|
11485
|
+
label: "Codex CLI",
|
|
11484
11486
|
find: (cwd) => findCodexRollouts(cwd),
|
|
11485
11487
|
read: readCodexRollout,
|
|
11486
11488
|
root: "~/.codex/sessions",
|
|
@@ -11493,6 +11495,7 @@ var codexReader = {
|
|
|
11493
11495
|
};
|
|
11494
11496
|
var cursorReader = {
|
|
11495
11497
|
agent: "cursor",
|
|
11498
|
+
label: "Cursor",
|
|
11496
11499
|
find: (cwd) => findCursorSessions(cwd),
|
|
11497
11500
|
read: readCursorSession,
|
|
11498
11501
|
root: tilde(cursorStateDb()),
|
|
@@ -11522,6 +11525,10 @@ function tryParse(line3) {
|
|
|
11522
11525
|
return null;
|
|
11523
11526
|
}
|
|
11524
11527
|
}
|
|
11528
|
+
function readerLabels() {
|
|
11529
|
+
const labels = READERS.map((r) => r.label);
|
|
11530
|
+
return labels.length <= 1 ? labels[0] ?? "" : `${labels.slice(0, -1).join(", ")} and ${labels[labels.length - 1]}`;
|
|
11531
|
+
}
|
|
11525
11532
|
var READER_ROOTS = () => READERS.map((r) => r.root).join(" or ");
|
|
11526
11533
|
async function readerForFile(path) {
|
|
11527
11534
|
let head = "";
|
|
@@ -11554,6 +11561,45 @@ async function newestTranscript(cwd) {
|
|
|
11554
11561
|
// src/sent/scan.ts
|
|
11555
11562
|
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve9 } from "path";
|
|
11556
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
|
+
|
|
11557
11603
|
// src/sent/report.ts
|
|
11558
11604
|
var MAX_OCCURRENCES = 5;
|
|
11559
11605
|
function byTime(a, b) {
|
|
@@ -11621,8 +11667,8 @@ function fileEvidenceFor(tool) {
|
|
|
11621
11667
|
if (SHELL_TOOLS4.has(tool)) return "named";
|
|
11622
11668
|
return null;
|
|
11623
11669
|
}
|
|
11624
|
-
function credentialFilesIn(input, scope, sessionCwd) {
|
|
11625
|
-
const leaves = collectStrings(input);
|
|
11670
|
+
function credentialFilesIn(tool, input, scope, sessionCwd) {
|
|
11671
|
+
const leaves = SHELL_TOOLS4.has(tool) ? collectStrings(input).map(withoutHeredocData) : collectStrings(input);
|
|
11626
11672
|
return scope.sourcePaths.filter(
|
|
11627
11673
|
(path) => spellingsOf(path, scope, sessionCwd).some(
|
|
11628
11674
|
(spelling) => leaves.some((leaf) => mentions(leaf, spelling))
|
|
@@ -11692,7 +11738,7 @@ async function scanTranscript(transcript, source, index, scope) {
|
|
|
11692
11738
|
}
|
|
11693
11739
|
const evidence = fileEvidenceFor(event.tool);
|
|
11694
11740
|
if (evidence !== null) {
|
|
11695
|
-
for (const path of credentialFilesIn(event.input, scope, transcript.cwd)) {
|
|
11741
|
+
for (const path of credentialFilesIn(event.tool, event.input, scope, transcript.cwd)) {
|
|
11696
11742
|
files.push({ path, tool: event.tool, evidence, call, at: event.at });
|
|
11697
11743
|
}
|
|
11698
11744
|
}
|
|
@@ -11735,7 +11781,7 @@ function scanAuditLog(allEntries, sessionId, scope) {
|
|
|
11735
11781
|
const files = entries.filter((e) => e.phase === "post").flatMap((entry2) => {
|
|
11736
11782
|
const evidence = fileEvidenceFor(entry2.tool);
|
|
11737
11783
|
if (evidence === null) return [];
|
|
11738
|
-
return credentialFilesIn({ summary: entry2.summary }, scope, null).map((path) => ({
|
|
11784
|
+
return credentialFilesIn(entry2.tool, { summary: entry2.summary }, scope, null).map((path) => ({
|
|
11739
11785
|
path,
|
|
11740
11786
|
tool: entry2.tool,
|
|
11741
11787
|
evidence,
|
|
@@ -11780,10 +11826,12 @@ Flags:
|
|
|
11780
11826
|
--fail-on-finding exit 1 when a credential is found (for a scheduled job)
|
|
11781
11827
|
-h, --help show this
|
|
11782
11828
|
|
|
11783
|
-
Reads
|
|
11784
|
-
which from the file itself
|
|
11785
|
-
|
|
11786
|
-
|
|
11829
|
+
Reads sessions recorded by ${readerLabels()}.
|
|
11830
|
+
--transcript works out which from the file itself; a Cursor session is
|
|
11831
|
+
addressed as <store>#<session>. It reads this machine's credential files to
|
|
11832
|
+
know what to look for, and prints names and sources only, never a value. A
|
|
11833
|
+
finding exits 0 by default: a session that already happened cannot be
|
|
11834
|
+
un-sent by today's commit.
|
|
11787
11835
|
`;
|
|
11788
11836
|
async function runSent(args) {
|
|
11789
11837
|
let parsed;
|
|
@@ -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