@stroq/cli 0.19.0 → 0.19.1

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 CHANGED
@@ -9,7 +9,18 @@
9
9
  <a href="https://github.com/AGGIB/Stroq/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License: Apache 2.0"></a>
10
10
  </p>
11
11
 
12
- **Local action firewall for AI coding agents.** Stroq scans what your agent reads (files, web pages, MCP tool results, command output) for indirect prompt injection, taints the session when it finds instruction-like text, and deterministically blocks the dangerous follow-up actions an injected agent would take — outbound network commands, secret access, external git pushes, encoded execution, self-tampering. Everything runs locally; nothing is sent to a cloud.
12
+ # Stroq — find known secrets in AI coding-agent sessions
13
+
14
+ **Check a session you already ran:** `stroq sent` looks for exact matches to credentials currently available on your machine in local Claude Code, Codex CLI and Cursor session records. It reports the credential name, source file and recorded tool call without printing the value. A match proves that the value appears in a local record; it does not prove that a model provider received it, that the credential is still valid or that a breach occurred.
15
+
16
+ ```bash
17
+ npx @stroq/cli sent --last # inspect the newest supported session in this project
18
+ npx @stroq/cli replay --last # trace recorded content to later agent actions
19
+ ```
20
+
21
+ Run these commands from the project directory with Node.js 22 or newer. They work on sessions from before Stroq was installed. `npx` downloads the CLI from npm; `sent` reads local credential sources to know what values to match and does not upload them. See the [guide's coverage and limits](https://github.com/AGGIB/Stroq/blob/main/docs/GUIDE.md).
22
+
23
+ **Guard future sessions:** Stroq scans content visible to installed agent hooks, carries suspicion and source information into later decisions, and applies a local policy to the tool calls those hooks expose. It supports native hooks, an OpenClaw plugin and a stdio MCP proxy; coverage differs by agent and channel. The hooks do not send telemetry.
13
24
 
14
25
  Supported today: **Claude Code**, **Cursor**, **Codex**, **Copilot CLI**, **Windsurf**, **Google Antigravity** (native hooks) · **OpenClaw** (in-process plugin) · **any MCP client** (stdio proxy).
15
26
 
@@ -22,6 +33,7 @@ npx @stroq/cli init --agent codex # Codex CLI: writes .codex/hooks.json
22
33
  npx @stroq/cli init --agent copilot # Copilot CLI: writes .github/hooks/stroq.json
23
34
  npx @stroq/cli init --agent openclaw # OpenClaw: installs a plugin into ~/.stroq/openclaw-plugin
24
35
  npx @stroq/cli init --agent windsurf # Windsurf: merges into .windsurf/hooks.json
36
+ npx @stroq/cli init --agent antigravity # Google Antigravity: merges into .agents/hooks.json
25
37
  npx @stroq/cli init --agent mcp --client claude-desktop # any MCP client: wraps its stdio servers
26
38
  npx @stroq/cli doctor # check the installation
27
39
  ```
@@ -36,21 +48,23 @@ MCP proxy note: for clients with no hook API, `--agent mcp` rewrites the client'
36
48
 
37
49
  ## Commands
38
50
 
39
- | Command | What it does |
40
- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
- | `stroq init [--agent <name>] [--user] [--dry-run]` | Install hooks for `claude-code`, `cursor`, `codex`, `copilot`, `openclaw` or `windsurf`, or wrap an MCP client's stdio servers with `--agent mcp --client <name>` or `--config <path>` (`--user` for the home-directory copy) |
42
- | `stroq hook <agent>` | Hook entrypoint (reads the event on stdin; `copilot` and `openclaw` take a `pre`/`post` argument, the others do not) |
43
- | `stroq mcp --server <name> -- <cmd>` | MCP stdio proxy: judges every `tools/call` and scans every result for one wrapped server |
44
- | `stroq doctor` | Check Node version, rules, hooks for every agent, self-test |
45
- | `stroq log [--count 20]` | Show recent audit entries |
46
- | `stroq verify` | Verify the audit hash chain |
47
- | `stroq untaint [--session <id>] [--all]` | Clear a false-positive session's taint and provenance, or every session's |
48
- | `stroq why [--seq <n>]` | Explain the most recent denied/asked action: rule, provenance, taint |
49
- | `stroq canary [--name <NAME>]` | Print a canary secret to plant; its outbound use is denied and taints the session |
50
- | `stroq attack [--json] [--only <id>] [--fuzz]` | Replay 20 recorded incidents against your policy; `--fuzz` crosses every scenario with a deterministic mutation set and reports the variants that still reach `allow`; exit 1 if any gets through |
51
- | `stroq exposure [--probe] [--share] [--json]` | Map this machine's agent surface and report what reaches you; exit 1 on any finding |
52
- | `stroq bench [--corpus <dir>] [--json] [--verbose]` | Measure the shipped rule set's false-positive rate against a corpus of benign developer documentation; `--verbose` lists the flagged files |
53
- | `stroq coverage [--format <table\|navigator>] [--json]` | Print the control mapping against MITRE ATLAS and OWASP ASI, built from the attack corpus's own scenario tags; `--format=navigator` emits an ATT&CK Navigator layer |
51
+ | Command | What it does |
52
+ | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53
+ | `stroq init [--agent <name>] [--user] [--dry-run]` | Install hooks for `claude-code`, `cursor`, `codex`, `copilot`, `openclaw`, `windsurf` or `antigravity`, or wrap an MCP client's stdio servers with `--agent mcp --client <name>` or `--config <path>` (`--user` for the home-directory copy) |
54
+ | `stroq hook <agent>` | Hook entrypoint (reads the event on stdin; `copilot` and `openclaw` take a `pre`/`post` argument, the others do not) |
55
+ | `stroq mcp --server <name> -- <cmd>` | MCP stdio proxy: judges every `tools/call` and scans every result for one wrapped server |
56
+ | `stroq doctor` | Check Node version, rules, hooks for every agent, self-test |
57
+ | `stroq log [--count 20] [--json]` | Show recent audit entries; `--json` prints one entry per line |
58
+ | `stroq verify` | Verify the audit hash chain |
59
+ | `stroq untaint [--session <id>] [--all]` | Clear a false-positive session's taint and provenance, or every session's |
60
+ | `stroq why [--seq <n>]` | Explain the most recent denied/asked action: rule, provenance, taint |
61
+ | `stroq sent [--last] [--transcript <path>] [--json]` | Match known local credentials against a recorded session, including tool results where a transcript is available; report names and sources, never values |
62
+ | `stroq replay [--last] [--transcript <path>] [--json]` | Reconstruct which recorded content preceded later agent actions and show the matching evidence |
63
+ | `stroq canary [--name <NAME>] [--file <path>]` | Print a canary secret to plant; its outbound use is denied and taints the session. `--file` plants it as a decoy file: any call naming the file is denied and taints the session |
64
+ | `stroq attack [--json] [--only <id>] [--fuzz]` | Replay 21 documented-incident and synthetic scenarios against your policy; `--fuzz` crosses each with a deterministic mutation set and reports variants that reach `allow`; exit 1 if any gets through |
65
+ | `stroq exposure [--probe] [--share] [--json]` | Map this machine's agent surface and report what reaches you; exit 1 on any finding |
66
+ | `stroq bench [--corpus <dir>] [--json] [--verbose]` | Measure the shipped rule set's false-positive rate against a corpus of benign developer documentation; `--verbose` lists the flagged files |
67
+ | `stroq coverage [--format <table\|navigator>] [--json]` | Print the control mapping against MITRE ATLAS and OWASP ASI, built from the attack corpus's own scenario tags; `--format=navigator` emits an ATT&CK Navigator layer |
54
68
 
55
69
  `stroq exposure` reads files only. `--probe` is the one flag that starts a process: it launches each configured stdio MCP server, asks once for `tools/list`, scans the tool descriptions and shuts the server down — no tool is ever called. Without it, tool-description poisoning is not covered by the run, and the report says so. `--share` prints a redacted summary built from a whitelist, locally; nothing is transmitted.
56
70
 
package/dist/index.js CHANGED
@@ -11711,8 +11711,8 @@ var VIA_LABEL = {
11711
11711
  tool_argument: "in the arguments of"
11712
11712
  };
11713
11713
  var FILE_EVIDENCE_LINE = {
11714
- read: "its contents came back to the model",
11715
- named: "named in the command; whether its contents were printed depends on the command"
11714
+ read: "a Read/Grep call was recorded for this path; its returned content is not established here",
11715
+ named: "named in a shell command; whether it read or printed the file is unknown"
11716
11716
  };
11717
11717
  function timestamp(iso) {
11718
11718
  return Number.isNaN(Date.parse(iso)) ? "an unrecorded time" : iso.replace(".000Z", "Z");
@@ -11751,8 +11751,8 @@ function coverageLines(report2) {
11751
11751
  const lines = [
11752
11752
  "COVERAGE",
11753
11753
  ` Matched against ${c.indexedSecrets} value(s) indexed from: ${sources}`,
11754
- " Reading those credential files is what this command does; it opens nothing else,",
11755
- " and it stores and prints names and sources only, never a value.",
11754
+ " To match known values, this command reads supported local credential files",
11755
+ " and project .env sources. It stores and prints names and sources, never values.",
11756
11756
  " Credential-shaped variables in the environment this command ran with are matched",
11757
11757
  " too, and are not counted above.",
11758
11758
  " A credential you have rotated or deleted since that session is not in the index,",
@@ -11760,39 +11760,38 @@ function coverageLines(report2) {
11760
11760
  ];
11761
11761
  if (c.toolResultsRead) {
11762
11762
  lines.push(
11763
- ` Tool results were read in full from the agent's own transcript (${c.results} of ${c.calls} calls).`
11763
+ ` Recorded tool result text was scanned from the agent transcript (${c.results} of ${c.calls} calls).`
11764
11764
  );
11765
11765
  } else {
11766
11766
  lines.push(
11767
- " The audit log records what each call SENT, never what came back, so only tool",
11768
- " arguments and credential-file reads are covered here. Run `stroq sent --last`",
11769
- " to read the agent's own transcript instead, which still has the result text."
11767
+ " The audit log records call arguments, never what came back, so only recorded",
11768
+ " argument matches and supported file-path references are covered here.",
11769
+ " Run `stroq sent --last` to read the agent's own transcript instead,",
11770
+ " which may still have the result text."
11770
11771
  );
11771
11772
  }
11772
11773
  return lines;
11773
11774
  }
11774
11775
  var MEANING = [
11775
11776
  "WHAT THIS SAYS, AND WHAT IT DOES NOT",
11776
- " What is above was in the text of that session, so it went to the model provider",
11777
- " along with everything else in it. That is how a coding agent works.",
11778
- " Nothing here says the provider retained any of it, that a person ever saw it, or",
11779
- " that this was a breach. It says the value was in that traffic, and that you may",
11780
- " not have known it was.",
11781
- " If one of them matters, rotate it. Rotating is cheap; being sure is not."
11777
+ " These findings come from a local agent transcript or Stroq audit log.",
11778
+ " Where shown, a matching value appeared in a tool result or call argument.",
11779
+ " A file entry records a supported tool using or naming its path.",
11780
+ " This record alone cannot confirm a later model request, delivery to a provider,",
11781
+ " the recipient, retention, human access, or whether a credential is still valid.",
11782
+ " It does not prove a breach. Review the session and rotate active credentials",
11783
+ " when the potential exposure warrants it."
11782
11784
  ];
11783
11785
  function formatSent(report2) {
11784
11786
  const lines = [
11785
- "stroq sent \u2014 which of your credentials already reached a model provider",
11787
+ "stroq sent \u2014 credential evidence in recorded agent sessions",
11786
11788
  "",
11787
11789
  ` session ${report2.sessionId} \xB7 ${report2.coverage.calls} tool call(s)${duration2(report2)}`,
11788
11790
  origin(report2),
11789
11791
  ""
11790
11792
  ];
11791
11793
  if (report2.credentials.length > 0) {
11792
- lines.push(
11793
- `CREDENTIALS THAT WERE IN THIS SESSION'S TRAFFIC (${report2.credentials.length})`,
11794
- ""
11795
- );
11794
+ lines.push(`CREDENTIAL VALUES FOUND IN THIS SESSION RECORD (${report2.credentials.length})`, "");
11796
11795
  for (const credential of report2.credentials) lines.push(...credentialBlock(credential));
11797
11796
  }
11798
11797
  if (report2.files.length > 0) {
@@ -11804,16 +11803,16 @@ function formatSent(report2) {
11804
11803
  if (report2.files.some((f) => f.evidence === "read")) {
11805
11804
  lines.push(
11806
11805
  "",
11807
- " A file whose contents came back was sent to the model whole, including any",
11808
- " value Stroq does not have indexed and therefore could not name above."
11806
+ " A Read/Grep result may contain sensitive content absent from today's index.",
11807
+ " Inspect the agent transcript to learn what was actually returned."
11809
11808
  );
11810
11809
  }
11811
11810
  lines.push("");
11812
11811
  }
11813
11812
  if (report2.credentials.length === 0 && report2.files.length === 0) {
11814
11813
  lines.push(
11815
- "No indexed credential appeared in this session, and no credential file was",
11816
- "read or named by it. Read the coverage below before treating that as clean.",
11814
+ "No indexed credential match or credential-file finding was recorded for",
11815
+ "this session. Read the coverage below before treating that as clean.",
11817
11816
  ""
11818
11817
  );
11819
11818
  } else {
@@ -12758,7 +12757,7 @@ function emit(report2, out) {
12758
12757
  const found = report2.credentials.length > 0 || report2.files.length > 0;
12759
12758
  return out.failOnFinding && found ? 1 : 0;
12760
12759
  }
12761
- var USAGE = `stroq sent \u2014 which of your credentials already reached a model provider
12760
+ var USAGE = `stroq sent \u2014 credential evidence in recorded agent sessions
12762
12761
 
12763
12762
  stroq sent --last read the newest session in this directory
12764
12763
  stroq sent --transcript <path> read a specific transcript or rollout
@@ -12774,7 +12773,7 @@ Reads sessions recorded by ${readerLabels()}.
12774
12773
  addressed as <store>#<session>. It reads this machine's credential files to
12775
12774
  know what to look for, and prints names and sources only, never a value. A
12776
12775
  finding exits 0 by default: a session that already happened cannot be
12777
- un-sent by today's commit.
12776
+ changed by today's commit. A transcript match does not confirm provider delivery.
12778
12777
  `;
12779
12778
  async function runSent(args) {
12780
12779
  let parsed;
@@ -13073,15 +13072,16 @@ Commands:
13073
13072
  untaint [--session <id>] [--all] clear a false-positive session's taint, or every session's
13074
13073
  why [--seq <n>] explain the most recent denied/asked action: rule, provenance, taint
13075
13074
  replay [<session>] [--last] [--transcript <path>] [--json] [--list]
13076
- rebuild a session's causal history: which content the agent read,
13077
- and which actions came out of it. --last reads the agent's own
13075
+ rebuild the recorded sequence: which content the agent read,
13076
+ and which later actions matched it. --last reads the agent's own
13078
13077
  transcript, so it works on sessions that ran before you installed
13079
13078
  sent [<session>] [--last] [--transcript <path>] [--json] [--fail-on-finding]
13080
- which of your credentials already reached a model provider, in
13081
- which past session, put there by which tool call. --last reads
13079
+ which credentials appear in a recorded agent session, and in
13080
+ which tool result or call. This local evidence does not confirm
13081
+ a model request or provider delivery. --last reads
13082
13082
  the agent's own transcript, so it covers sessions from before
13083
13083
  you installed and can see what tools RETURNED, not just what
13084
- they sent. To match values it reads this machine's credential
13084
+ they called. To match values it reads this machine's credential
13085
13085
  files (~/.aws/credentials, ~/.npmrc, ~/.netrc,
13086
13086
  ~/.docker/config.json, ./.env*); it reports names and sources
13087
13087
  only, never a value. Exits 0 even when it finds something \u2014
@@ -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.19.0",
5
+ "version": "0.19.1",
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.19.0",
3
+ "version": "0.19.1",
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@stroq/cli",
3
- "version": "0.19.0",
4
- "description": "Local action firewall for AI agents: scans what the agent reads, taints the session, blocks dangerous follow-up actions",
3
+ "version": "0.19.1",
4
+ "description": "Find known secrets in local Claude Code, Codex and Cursor sessions; trace risky AI agent actions and guard future tool calls",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "bin": {
@@ -32,10 +32,13 @@
32
32
  "agent-security",
33
33
  "prompt-injection",
34
34
  "claude-code",
35
+ "codex",
36
+ "openclaw",
35
37
  "mcp",
36
38
  "firewall",
37
- "guardrails",
38
39
  "cursor",
40
+ "secret-scanning",
41
+ "credential-exposure",
39
42
  "llm-security"
40
43
  ],
41
44
  "publishConfig": {