Skip to content

SymbolStar/shipcheck

Repository files navigation

shipcheck

Best-effort pre-publish PII and secret check. Not a replacement for manual review, a full secret scanner, or a security audit. Use it as one more pair of eyes before you npm publish, clawhub publish, or git push to public.

npx @symbolstar/shipcheck

By default, shipcheck scans only the files that would actually be published from an npm package (static package.json.files + .npmignore + .gitignore resolution — it does not invoke npm pack). For generic repos or OpenClaw skills:

shipcheck --scan-mode=dir ./path/to/repo

What it catches

Category Examples Severity
secrets AWS access key, GitHub PAT (ghp_/gho_/ghu_/ghs_/ghr_), OpenAI sk-, Anthropic sk-ant-, Google AIza…, Slack xox[bp]-…, JWT, PEM/SSH private key (~30 rules) critical
identity Email, China mobile + E.164, /Users/<name>/ and /home/<name>/ absolute paths, SSH fingerprint high
infra RFC1918 private IPs, 100.64/10 Tailscale CGNAT, *.tail<id>.ts.net, *.lan/*.local, private git remotes high
business User-defined forbidden_terms from shipcheck.config.json (project codenames, internal product names…) medium
softNL Chinese first-person personal context in *.md (我家 / 我老板 / 我同事 + 关系词) info
binaries *.png/.jpg/.mp4/.zip/.pdf > 50 KB in the publish set warn

Install

# One-shot
npx -y @symbolstar/shipcheck

# As a dev dependency + prepublishOnly hook
npm i -D @symbolstar/shipcheck
npx shipcheck init

shipcheck init merges scripts.prepublishOnly (it appends; it will not clobber an existing chain) and seeds a .shipcheckignore template.

Commands

shipcheck [path]                       # scan; default path is "."
shipcheck init                         # add prepublishOnly + .shipcheckignore template
shipcheck --allow <finding-id>         # append an allow line to .shipcheckignore (asks for reason)
shipcheck --scan-mode=dir|npm          # default: npm
shipcheck --format=stylish|json        # default: stylish
shipcheck --severity-threshold=high    # critical|high|medium|warn|info (default: high)
shipcheck --include-deps               # include node_modules
shipcheck --include-git                # include .git
shipcheck --max-size=10MB              # max per-file content scan size
shipcheck --skip                       # bypass (red banner + logged to .shipcheck/skips.log)

Exit codes follow the eslint shape: 0 clean, 1 blocking findings (>= threshold), 2 tool error.

.shipcheckignore

Gitignore-style globs. Append # rule:<id> to scope the ignore to one rule (otherwise it ignores every rule for the matching files):

# Ignore everything in fixtures/ for the aws rule only
fixtures/** # rule:secret.aws-access-key

# Allow the email rule once for a specific file
README.md # rule:identity.email

# Untargeted: ignore the whole path for every rule
CHANGELOG.md

shipcheck.config.json (optional)

{
  "forbidden_terms": ["MyInternalProject", "secret-codename"]
}

Each term is matched case-insensitively as a literal substring across scanned content. Use this to keep project codenames, customer names, or other org-specific strings out of public packages.

Reports

Stylish output (default) prints colorized findings grouped by file with rule id, severity, line/column, and a triage hint:

src/config.ts
  14:9  high     identity macOS home absolute path  identity.macos-home-path 4f3db8c69dc6
    hint: (a) allow  (b) remove  (c) replace with placeholder

JSON output (--format=json) writes .shipcheck/last-report.json with:

{
  "tool":    { "name": "@symbolstar/shipcheck", "version": "0.1.0" },
  "gitSha":  "099c371",
  "files":   [{ "file": "...", "size": 1234, "binaryKind": "png" }],
  "findings": [{ "id": "...", "ruleId": "...", "severity": "high", "file": "...", "line": 14, "column": 9, "message": "...", "snippet": "...", "severityMasked": true }]
}

--allow <finding-id> reads this report to look up the file path and rule id for the allow line.

Caveats (please read)

  • No entropy / heuristic scanning. v0.1 is pure regex + small DSLs. You will miss novel-format secrets. Use a dedicated secret scanner (gitleaks, trufflehog) for security-critical workflows.
  • Best-effort manifest resolution. shipcheck does not run npm pack. Edge cases in files globs, bundleDependencies, or workspace packing may differ.
  • False positives are normal. That's why .shipcheckignore exists and --allow is interactive. Tune as you go.
  • Not a CI gate replacement. Treat the exit-1 as advisory, not load-bearing. If you bypass with --skip, that bypass is logged to .shipcheck/skips.log for after-the-fact accountability.

Roadmap (v0.2+)

  • gitleaks delegation behind --use-gitleaks
  • --baseline (snapshot known findings, fail only on new ones)
  • SARIF output
  • // shipcheck-allow:<rule-id> inline comment support
  • Entropy + redaction heuristics
  • ClawHub publish hook + VS Code surface

License

MIT

About

Best-effort pre-publish PII and secret check for npm packages, OpenClaw skills, and local repos.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors