snoopios
v0.9.4
Published
Check a domain, a git checkout, a Postgres database, or twenty providers whose tokens should never leave your machine (hosting, identity, monitoring, CI, code and secret scanners, password managers) the way a compliance reviewer would. Read-only, runs on
Maintainers
Readme
snoopios
The checks Snoopios runs every hour for its customers, run once
from your own machine. Every check returns pass, fail or unknown, and unknown is
never a pass. Exit code 1 when anything fails, so it sits in CI. Nothing is sent to
Snoopios or anyone else.
scan a domain
npx snoopios scan example.comHTTPS redirect, HSTS, a Content-Security-Policy that stops exfiltration, the basic
hardening headers, TLS version and certificate expiry, HSTS preload, SPF, DMARC, CAA,
security.txt and a privacy page that names a controller and a date. Add --email resend
(or postmark, mailgun, ses, other) for the sending domain: DKIM, SPF on the
return path, DMARC enforcement and reporting, MTA-STS and TLS-RPT.
run a provider whose token cannot be made read-only
NETLIFY_AUTH_TOKEN=… npx snoopios run netlify
NEON_API_KEY=… npx snoopios run neon
RENDER_API_KEY=… npx snoopios run render
HEROKU_API_KEY=… npx snoopios run heroku
CLERK_SECRET_KEY=… npx snoopios run clerk
UPSTASH_EMAIL=… UPSTASH_API_KEY=… npx snoopios run upstash
BETTERSTACK_API_TOKEN=… npx snoopios run betterstack
RAILWAY_TOKEN=… npx snoopios run railway
CIRCLECI_TOKEN=… CIRCLECI_PROJECT=gh/org/repo npx snoopios run circleci
CHECKLY_API_KEY=… CHECKLY_ACCOUNT_ID=… npx snoopios run checkly
TURSO_API_TOKEN=… TURSO_ORG=… npx snoopios run turso
WORKOS_API_KEY=… npx snoopios run workos
SNYK_TOKEN=… SNYK_ORG_ID=… npx snoopios run snyk
SEMGREP_APP_TOKEN=… SEMGREP_DEPLOYMENT=… npx snoopios run semgrep
GITGUARDIAN_API_KEY=… npx snoopios run gitguardian
AIKIDO_CLIENT_ID=… AIKIDO_CLIENT_SECRET=… npx snoopios run aikido
SONAR_TOKEN=… SONAR_PROJECT_KEY=… npx snoopios run sonarqube
OP_EVENTS_TOKEN=… OP_REGION=eu npx snoopios run onepassword
BW_CLIENT_ID=… BW_CLIENT_SECRET=… BW_REGION=eu npx snoopios run bitwarden
DOPPLER_TOKEN=… npx snoopios run dopplerMost of these providers' tokens cannot be scoped read-only (Upstash's can, but nothing reads that back and its API returns database credentials), so Snoopios never holds them. The CLI reads the token from your environment, runs the checks here and prints the report. The token never leaves your machine, and every request is a read.
- Netlify: HTTPS forced on every site, sites behind site protection, secret-looking variables marked secret, live sites sending the basic hardening headers.
- Neon: database reachable only from listed addresses, production branch protected, at least seven days of point-in-time restore, no preview branch older than thirty days.
- Render: a health check on every web service, every custom domain verified, deploy failures not ignored.
- Heroku: a certificate on every custom domain, no app left in maintenance mode, every app on a supported stack, the web tier on more than one dyno.
- Clerk: redirect URLs HTTPS and not local, JWT templates expiring within an hour, no dormant account able to sign in.
- Upstash: TLS on every Redis database, daily backups on paid ones, nothing suspended. Credentials in the API response are dropped before anything is printed.
- Better Stack: monitors present and none paused, certificate checks on HTTPS monitors, checks at least every five minutes, every monitor alerting somebody.
- Railway (project token): health check on every public service, restart policy not Never, more than one replica, custom domains pointing at Railway. Variables are never read.
- CircleCI (one project): builds hidden from the public, settings changed by admins only, forks do not receive secrets.
- Checkly: checks present and none muted, every check alerts somebody, certificate expiry alerts on, checks from more than one location.
- Turso: delete protection on every database and group, owners held by few.
- WorkOS: SSO connections live, directory syncs healthy, customer domains verified, user emails verified.
- Snyk, Semgrep, Aikido (the scanner's own findings, read and never re-run): nothing critical open, serious findings closed within thirty days, nothing open past ninety, and for Snyk and Semgrep every project scanned in the last fortnight.
- GitGuardian: no committed credential still valid, no critical secret incident open,
incidents closed within thirty days and none older than ninety. Needs
sources:readas well asincidents:read, so an unmonitored workspace is never reported clean. - SonarQube and SonarCloud: the quality gate passing and actually testing something,
analysed in the last fortnight, security rating A. Set
SONAR_HOST_URLfor a self-hosted server. - 1Password (Events API token, sign-in attempts and audit events only): every sign-in used a second factor, no account being guessed at, an audit log you can produce.
- Bitwarden (organisation API key;
BW_REGION=eufor bitwarden.eu): everyone with vault access has a second factor, the Enterprise policies that require it and keep company items in the company, nobody seeing every collection by accident, nobody stuck halfway through joining. - Doppler (personal token): no service token that can write, none pointing at a root config, none older than a year.
push results to your Snoopios project (--push)
run and repo keep everything on your machine by default. Add --push and the results
(check, status, what was observed, the evidence) go to your project; the provider token
still never leaves the machine. On the project page, open Run locally and push and
create a key; it is shown once and stored hashed.
SNOOPIOS_INGEST_KEY=snpi_… NETLIFY_AUTH_TOKEN=… npx snoopios run netlify --pushPushed results are labelled Run by you on the check page, in every generated document
and on the trust page. They never render as observed by Snoopios. Add --ci (or run
under GitHub Actions or GitLab CI, which are detected) and they are labelled Run in CI
with the run URL recorded, which is stronger evidence because a third party attests when
and where it ran.
hourly, from GitHub Actions
name: snoopios
on:
schedule:
- cron: "17 * * * *"
workflow_dispatch:
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx snoopios@latest repo . --push --ci --fail-on high
env:
SNOOPIOS_INGEST_KEY: ${{ secrets.SNOOPIOS_INGEST_KEY }}
- run: npx snoopios@latest run netlify --push --ci
env:
SNOOPIOS_INGEST_KEY: ${{ secrets.SNOOPIOS_INGEST_KEY }}
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}hourly, from a machine you keep on
17 * * * * cd /path/to/checkout && SNOOPIOS_INGEST_KEY=snpi_… npx snoopios@latest repo . --pushThe key can only post results. Revoke it from the project page at any time.
check a git checkout
npx snoopios repo .No token, any git host. Tracked .env files, .gitignore coverage, credential shapes anywhere
in the full history (each hit named by file, commit and line, never by its value), a
lockfile beside every manifest, SECURITY.md and CODEOWNERS, Dependabot or Renovate
configuration, and npm audit for critical or high findings in what ships. The audit runs
twice, with and without dev dependencies, so a finding only in development tooling is named
but does not fail the check. Only the audit touches the network.
ask Supabase what a visitor can read
npx snoopios supabaseRun it from the project's folder and it needs nothing typed, in any shell: the project URL
and public key are read from the NEXT_PUBLIC_ (or VITE_, EXPO_PUBLIC_, PUBLIC_)
Supabase names in .env.local or .env, the values your app already ships to every
browser, and no other line of those files is read. Or give them yourself:
npx snoopios supabase https://<project-ref>.supabase.co with SUPABASE_ANON_KEY set
(in PowerShell, $env:SUPABASE_ANON_KEY = "…" first).
No password and no account: just the project's public key. If one of those browser-shipped
names holds a service-role or secret key, it says so and stops: that key is in every
visitor's browser already, and it bypasses row-level security. For each table it asks for one row as headers
only, so no data is downloaded, and names every table that would have returned a row to
anybody. A service-role or secret key is refused, because it bypasses row-level security
and every table would look open. Hosted Supabase does not list its tables to the public
key, so run it from the project's folder: the tables are read from supabase/migrations.
Or name them with --tables profiles,orders. An empty table with row-level security off looks
closed, so for the full answer run doctor as well, or connect Supabase at
https://snoopios.com.
doctor a Postgres database
npx snoopios doctor postgres://user:pass@host:5432/dbThe Supabase SQL checks against any connection string you already have, including a
local Supabase: row-level security on every public table, no policy that lets anon
write, the private schema closed to session roles, SECURITY DEFINER functions pinning
search_path, and anon-callable definers that are safe to expose. SELECT statements
only. Also reads DATABASE_URL when no argument is given. The server's certificate is
verified, against Supabase's own root for *.supabase.com and your system's roots for
anything else, so the password is never sent to a server that only claims to be yours.
output
Every line carries the check's severity, and each fail comes with the fix and, where the check can say it, exactly what it found: the file and commit, the package, the missing file.
--md prints a report in Markdown instead: what needs attention with the fix, what could
not be checked, what passed, and the framework controls each check evidences (Cyber
Essentials, UK GDPR, SOC 2, ISO 27001). It says it was run once by you and is not a
certification. Redirect it to a file to hand to a customer or an assessor:
npx snoopios repo . --md > repo-report.md
npx snoopios scan example.com --md > domain-report.md--json prints the observed facts and the severity for every check.
--fail-on <low|medium|high|critical> sets the lowest severity that turns the exit code to
- The default is
low, any fail. In CI,--fail-on highkeeps an optional improvement, such as joining the HSTS preload list, from turning the build red. To keep it all checked every hour, with stored evidence, accepted risks and a public trust page, connect at https://snoopios.com.
Source of the published bundle, changelog and security policy: https://github.com/archemalabs/snoopios-cli
MIT © Archema Labs Ltd
