Skip to content

v0.3.0 - Secret egress guard and stroq attack

Choose a tag to compare

@AGGIB AGGIB released this 04 Sep 23:57
· 137 commits to main since this release

Stroq 0.3.0 ships the two remaining parts of the killer-feature research: the secret egress guard and stroq attack.

Secret egress guard (#9)

  • Values of known secrets — the project's .env* files, ~/.aws/credentials, ~/.npmrc, ~/.netrc, ~/.docker/config.json, and credential-shaped environment variables (hashed live, never stored) — are indexed as salted hashes in ~/.stroq/secrets.json.
  • An outbound action (network command, web fetch, MCP call, external push, encoded exec) whose arguments contain one of those values is denied by the new first default rule deny-secret-egress (action class secret.egress). The reason names the secret and its file, never the value; the value is redacted from the audit summary in raw, decoded and URL-encoded forms.
  • stroq canary [--name <NAME>] prints a decoy secret to plant; any outbound use of it is a certain positive that also marks the session suspect.
  • stroq doctor reports the index and fails when a source could not be read, .env* files were dropped, or the index was corrupt; stroq why explains secret-egress denials; WebFetch now fails closed on engine errors.
  • Hardened after review: candidate extraction is bounded by input bytes (not by a candidate count an attacker could pad past), URL/hostname/_URL-style values are not indexed, at most 32 project .env* files are read. Limits and the false-positive recovery path are documented in the README.
  • Upgrade note: a custom ~/.stroq/policy.yaml replaces the default policy, so add deny-secret-egress (first) to be protected.

stroq attack (#10)

  • Replays twelve recorded, incident-backed attack scenarios — a protestware README, Sentry agentjacking, Comment-and-Control, s1ngularity, RoguePilot's $schema token fetch, an env | curl exfiltration, a hooks-removal write, the rm -rf ~ and drizzle-kit push --force incidents, a ToxicSkills base64 installer, a fetched page asking for ~/.ssh/id_rsa, and a parent-directory wipe — through the engine with your policy, in throwaway directories, and prints blocked / asked / passed per scenario with totals. Exit code 1 when any scenario misbehaves, so a weakened policy fails CI; --json for badges; --only <id> for one scenario. Each scenario cites the public incident it models.
  • Classifier coverage the suite exposed: rm -r of any ~… target, terraform/tofu destroy, terraform apply -destroy, pulumi destroy, drizzle-kit push --force, prisma migrate reset, prisma db push --force-reset / --accept-data-loss, supabase db reset --linked, gh repo delete are shell.destructive; gh repo create … --push is git.push_external.

Verification

  • 660+ tests, coverage ≈ 96 / 87 / 99 / 97 (statements / branches / functions / lines), CI on Node 22 and 24 including the demo and the attack suite.
  • stroq attack with the default policy: 12 scenarios: 8 blocked, 4 asked, 0 passed through — every attack was stopped.

Install: npm install -g @stroq/cli then stroq init, or npx @stroq/cli init.