@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.1",
5
+ "version": "0.15.2",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stroq-openclaw-plugin",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "private": true,
5
5
  "description": "Stroq's OpenClaw plugin entry: forwards before_tool_call and after_tool_call to the Stroq CLI.",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stroq/cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Local action firewall for AI agents: scans what the agent reads, taints the session, blocks dangerous follow-up actions",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",