push-sentinel 0.1.1 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +47 -54
  2. package/package.json +1 -1
  3. package/src/scan.js +16 -4
package/README.md CHANGED
@@ -1,88 +1,79 @@
1
1
  # push-sentinel
2
2
 
3
- Warns you if secrets are in your git commits before push.
3
+ **Catches secrets in your git commits before they leave your machine.**
4
4
 
5
- ## What it does
5
+ You've seen the stories. Someone pushes an AWS key to a public repo. Bots scrape GitHub in seconds. The bill arrives the next morning: $8,000.
6
6
 
7
- Scans the commits you are about to push for potential secrets (API keys, private keys, tokens) and prints a warning. **It does not block the push by default** — it is a safety net, not a gatekeeper.
7
+ push-sentinel sits in your `pre-push` hook and warns you before that happens.
8
8
 
9
- ## Install
10
-
11
- ```sh
12
- npx push-sentinel install
13
9
  ```
10
+ $ git push
14
11
 
15
- This writes a `pre-push` hook to `.git/hooks/`. Any existing hook is preserved as `pre-push.local` and called automatically after the scan.
16
-
17
- ## Usage
18
-
19
- ### Automatic (after install)
20
-
21
- The hook runs on every `git push`. No action required.
22
-
23
- ```
24
12
  [push-sentinel] ⚠ Potential secrets found:
25
13
 
26
14
  [HIGH] src/config.ts:12
27
15
  AKIAIO...
28
- → Risk: Full access to AWS resources. Attacker can create/delete instances, incur charges, or exfiltrate data.
16
+ → Risk: Full access to AWS resources. Attacker can create/delete
17
+ instances, incur charges, or exfiltrate data.
29
18
  → To ignore this line: push-sentinel ignore src/config.ts:12
30
19
 
31
20
  Push continues. Double-check before sharing.
32
21
  ```
33
22
 
34
- ### Manual scan
23
+ ## Install
35
24
 
36
25
  ```sh
37
- npx push-sentinel scan
26
+ npx push-sentinel install
38
27
  ```
39
28
 
40
- ### Block push on HIGH findings
29
+ That's it. Runs automatically on every `git push` from now on.
41
30
 
42
- To treat HIGH severity findings as blocking errors, edit `.git/hooks/pre-push` and change the scan line to:
31
+ ## What it detects
43
32
 
44
- ```sh
45
- npx push-sentinel scan --local-sha "$local_sha" --remote-sha "$remote_sha" --block-on-high
46
- ```
33
+ | Pattern | Severity |
34
+ |---------|----------|
35
+ | Private Key (RSA, EC, OPENSSH, DSA, PKCS#8) | 🔴 HIGH |
36
+ | AWS Access Key (`AKIA...`) | 🔴 HIGH |
37
+ | AWS Secret Key (entropy-based) | 🔴 HIGH |
38
+ | GitHub Token (`ghp_`, `github_pat_`) | 🔴 HIGH |
39
+ | Anthropic API Key (`sk-ant-...`) | 🟡 MEDIUM |
40
+ | OpenAI API Key (`sk-...`) | 🟡 MEDIUM |
41
+ | Generic API Key (variable name + high entropy) | 🟢 LOW |
42
+ | `.env` file committed | 🟡 MEDIUM |
47
43
 
48
- ## Suppressing false positives
44
+ ## False positive? Ignore it in one command
49
45
 
50
46
  ```sh
51
- # Ignore a specific line
52
- push-sentinel ignore src/config.ts:12
47
+ push-sentinel ignore src/config.ts:12 # ignore a specific line
48
+ push-sentinel ignore --pattern OPENAI_API_KEY # ignore a pattern everywhere
49
+ push-sentinel ignore --list # see all ignore rules
50
+ ```
53
51
 
54
- # Ignore all matches of a pattern name
55
- push-sentinel ignore --pattern OPENAI_API_KEY
52
+ Rules are saved to `.push-sentinel-ignore` in your repo root.
56
53
 
57
- # List current ignore rules
58
- push-sentinel ignore --list
54
+ ## Why warning-only by default?
59
55
 
60
- # Remove a rule
61
- push-sentinel ignore --remove OPENAI_API_KEY
62
- ```
56
+ Blocking pushes creates friction. Friction leads to `--no-verify`. A warning at push time is early enough to catch real accidents — and you'll actually leave it installed.
63
57
 
64
- Rules are saved to `.push-sentinel-ignore` in the repo root. Add it to `.gitignore` or commit it — your choice.
58
+ Want hard blocking for HIGH findings? Add `--block-on-high`:
65
59
 
66
- ## Detected patterns
60
+ ```sh
61
+ # edit .git/hooks/pre-push, change the scan line to:
62
+ npx push-sentinel scan --local-sha "$local_sha" --remote-sha "$remote_sha" --block-on-high
63
+ ```
67
64
 
68
- | Pattern | Severity |
69
- |---------|----------|
70
- | Private Key (RSA, EC, OPENSSH, DSA, PKCS#8) | HIGH |
71
- | AWS Access Key (`AKIA...`) | HIGH |
72
- | AWS Secret Key (entropy-based) | HIGH |
73
- | GitHub Token (`ghp_`, `github_pat_`) | HIGH |
74
- | Anthropic API Key (`sk-ant-...`) | MEDIUM |
75
- | OpenAI API Key (`sk-...`) | MEDIUM |
76
- | Generic API Key (variable name + high entropy) | LOW |
77
- | `.env` file committed | MEDIUM |
65
+ ## Manual scan
78
66
 
79
- ## Non-blocking design
67
+ ```sh
68
+ npx push-sentinel scan
69
+ ```
80
70
 
81
- push-sentinel warns it does not block — because:
71
+ Manual scan checks, in order:
82
72
 
83
- - Blocking creates friction that causes developers to skip or uninstall the hook
84
- - A warning seen at push time is still early enough to catch accidental leaks
85
- - Use `--block-on-high` if you want stricter enforcement for HIGH-severity findings
73
+ - commits not yet pushed to your upstream
74
+ - staged changes
75
+ - unstaged working tree changes
76
+ - the last commit as a final fallback
86
77
 
87
78
  ## Uninstall
88
79
 
@@ -90,9 +81,11 @@ push-sentinel warns — it does not block — because:
90
81
  npx push-sentinel uninstall
91
82
  ```
92
83
 
93
- The original `pre-push` hook (if any) is automatically restored.
84
+ Your original `pre-push` hook is restored automatically.
94
85
 
95
- ## Requirements
86
+ ## Details
96
87
 
88
+ - Scans only the commits being pushed — not your entire history
89
+ - Zero dependencies (Node.js stdlib only)
97
90
  - Node.js >= 16
98
- - No additional dependencies
91
+ - Existing `pre-push` hooks are preserved and still run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "push-sentinel",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Warns you if secrets are in your git diff before push.",
5
5
  "bin": {
6
6
  "push-sentinel": "bin/cli.js"
package/src/scan.js CHANGED
@@ -119,14 +119,24 @@ function runGit(args) {
119
119
  return result.status === 0 ? (result.stdout || '') : null;
120
120
  }
121
121
 
122
+ function runGitNonEmpty(args) {
123
+ const out = runGit(args);
124
+ return out && out.trim() ? out : null;
125
+ }
126
+
122
127
  function getPushDiff(localSha, remoteSha) {
123
128
  const args = getDiffArgs(localSha, remoteSha);
124
129
  if (args) {
125
130
  const out = runGit(args);
126
131
  if (out !== null) return out;
127
132
  }
128
- // Fallback for manual scan
129
- return runGit(['log', '@{u}..HEAD', '-p']) ?? runGit(['log', '-1', '-p', 'HEAD']) ?? '';
133
+ // Manual scan: inspect unpushed commits first, then staged changes, then working tree,
134
+ // and finally fall back to the last commit if none of those produce a diff.
135
+ return runGitNonEmpty(['log', '@{u}..HEAD', '-p'])
136
+ ?? runGitNonEmpty(['diff', '--cached'])
137
+ ?? runGitNonEmpty(['diff'])
138
+ ?? runGit(['log', '-1', '-p', 'HEAD'])
139
+ ?? '';
130
140
  }
131
141
 
132
142
  function getPushedFileList(localSha, remoteSha) {
@@ -135,8 +145,10 @@ function getPushedFileList(localSha, remoteSha) {
135
145
  const out = runGit(args);
136
146
  if (out !== null) return out.split('\n').map((f) => f.trim()).filter(Boolean);
137
147
  }
138
- // Fallback for manual scan
139
- const out = runGit(['diff', '--name-only', '@{u}..HEAD'])
148
+ // Manual scan: include files from unpushed commits, staged changes, and working tree.
149
+ const out = runGitNonEmpty(['diff', '--name-only', '@{u}..HEAD'])
150
+ ?? runGitNonEmpty(['diff', '--name-only', '--cached'])
151
+ ?? runGitNonEmpty(['diff', '--name-only'])
140
152
  ?? runGit(['diff', '--name-only', 'HEAD~1..HEAD'])
141
153
  ?? '';
142
154
  return out.split('\n').map((f) => f.trim()).filter(Boolean);