bigpowers 2.34.1 → 2.35.0

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 (48) hide show
  1. package/.pi/package.json +2 -2
  2. package/.pi/prompts/deploy.md +53 -28
  3. package/.pi/prompts/develop-tdd.md +5 -80
  4. package/.pi/prompts/migrate-spec.md +273 -197
  5. package/.pi/prompts/publish-package.md +125 -67
  6. package/.pi/prompts/release-branch.md +85 -69
  7. package/.pi/prompts/security-review.md +323 -0
  8. package/.pi/prompts/smoke-test.md +98 -58
  9. package/.pi/prompts/using-bigpowers.md +2 -2
  10. package/.pi/prompts/validate-contracts.md +169 -54
  11. package/.pi/prompts/wire-ci.md +147 -89
  12. package/.pi/skills/deploy/SKILL.md +53 -28
  13. package/.pi/skills/develop-tdd/SKILL.md +5 -80
  14. package/.pi/skills/migrate-spec/SKILL.md +273 -197
  15. package/.pi/skills/publish-package/SKILL.md +125 -67
  16. package/.pi/skills/release-branch/SKILL.md +85 -69
  17. package/.pi/skills/security-review/SKILL.md +324 -0
  18. package/.pi/skills/smoke-test/SKILL.md +98 -58
  19. package/.pi/skills/using-bigpowers/SKILL.md +2 -2
  20. package/.pi/skills/validate-contracts/SKILL.md +169 -54
  21. package/.pi/skills/wire-ci/SKILL.md +147 -89
  22. package/CHANGELOG.md +14 -0
  23. package/README.md +4 -4
  24. package/SKILL-INDEX.md +2 -2
  25. package/deploy/REFERENCE.md +82 -0
  26. package/deploy/SKILL.md +3 -63
  27. package/develop-tdd/SKILL.md +5 -80
  28. package/migrate-spec/REFERENCE.md +268 -0
  29. package/migrate-spec/SKILL.md +5 -199
  30. package/package.json +2 -2
  31. package/publish-package/REFERENCE.md +239 -0
  32. package/publish-package/SKILL.md +8 -192
  33. package/release-branch/REFERENCE.md +83 -0
  34. package/release-branch/SKILL.md +2 -69
  35. package/scripts/generate-reference-tables.sh +1 -0
  36. package/scripts/sync-skills.sh +4 -1
  37. package/security-review/REFERENCE-confidence-rubric.md +85 -0
  38. package/security-review/REFERENCE-false-positives.md +68 -0
  39. package/security-review/REFERENCE-vuln-categories.md +103 -0
  40. package/security-review/SKILL.md +63 -0
  41. package/skills-lock.json +14 -9
  42. package/smoke-test/REFERENCE.md +162 -0
  43. package/smoke-test/SKILL.md +5 -130
  44. package/using-bigpowers/SKILL.md +2 -2
  45. package/validate-contracts/REFERENCE.md +183 -0
  46. package/validate-contracts/SKILL.md +6 -77
  47. package/wire-ci/REFERENCE.md +257 -0
  48. package/wire-ci/SKILL.md +8 -210
@@ -33,225 +33,41 @@ If no manifest is found, prompt the user to specify the type or pass `--type <np
33
33
  Before attempting any publish, run all applicable checks:
34
34
 
35
35
  **npm (`package.json`):**
36
- ```bash
37
- # Check auth token exists
38
- if [ -z "${NPM_TOKEN:-}" ]; then
39
- if [ ! -f ~/.npmrc ] || ! grep -q "_authToken" ~/.npmrc; then
40
- echo "FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add //registry.npmjs.org/:_authToken=<token> to .npmrc"
41
- exit 1
42
- fi
43
- fi
44
-
45
- # Check version not already published
46
- PACKAGE_NAME=$(node -p "require('./package.json').name")
47
- CURRENT_VER=$(node -p "require('./package.json').version")
48
- if npm view "$PACKAGE_NAME@$CURRENT_VER" version 2>/dev/null; then
49
- echo "FAIL: Version $CURRENT_VER already published for $PACKAGE_NAME. Bump version first."
50
- exit 1
51
- fi
52
-
53
- # Check build artifacts are fresh
54
- if [ -d dist ] || [ -d lib ]; then
55
- LATEST_BUILD=$(find dist lib 2>/dev/null -name "*.js" -o -name "*.cjs" -o -name "*.mjs" | xargs ls -t 2>/dev/null | head -1)
56
- PACKAGE_MODIFIED=$(stat -f %m package.json 2>/dev/null || stat -c %Y package.json 2>/dev/null)
57
- if [ -n "$LATEST_BUILD" ] && [ -n "$PACKAGE_MODIFIED" ]; then
58
- BUILD_TIME=$(stat -f %m "$LATEST_BUILD" 2>/dev/null || stat -c %Y "$LATEST_BUILD" 2>/dev/null)
59
- if [ "$BUILD_TIME" -lt "$PACKAGE_MODIFIED" ]; then
60
- echo "WARNING: Build artifacts may be stale (package.json modified after last build). Run npm run build first."
61
- fi
62
- fi
63
- fi
64
-
65
- # Check CHANGELOG is updated
66
- if [ -f CHANGELOG.md ]; then
67
- if ! grep -q "$CURRENT_VER" CHANGELOG.md 2>/dev/null; then
68
- echo "WARNING: Version $CURRENT_VER not found in CHANGELOG.md. Update changelog before publish."
69
- fi
70
- fi
71
- ```
36
+ See [REFERENCE.md](REFERENCE.md)
72
37
 
73
38
  **crates.io (`Cargo.toml`):**
74
- ```bash
75
- # Check auth token exists
76
- if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
77
- if [ ! -f ~/.cargo/config.toml ] || ! grep -q "token" ~/.cargo/config.toml; then
78
- echo "FAIL: CARGO_REGISTRY_TOKEN not set. Set via: export CARGO_REGISTRY_TOKEN=<token> or add to ~/.cargo/config.toml"
79
- exit 1
80
- fi
81
- fi
82
-
83
- # Check version not already published
84
- CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
85
- CURRENT_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
86
- if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\""; then
87
- echo "FAIL: Version $CURRENT_VER already published for $CRATE_NAME. Bump version in Cargo.toml first."
88
- exit 1
89
- fi
90
- ```
39
+ See [REFERENCE.md](REFERENCE.md)
91
40
 
92
41
  **PyPI (`setup.py` / `pyproject.toml`):**
93
- ```bash
94
- # Check auth token exists
95
- if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
96
- if [ ! -f ~/.pypirc ]; then
97
- echo "FAIL: PyPI token not configured. Set TWINE_PASSWORD or create ~/.pypirc"
98
- exit 1
99
- fi
100
- fi
101
-
102
- # Check for build artifacts
103
- if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
104
- echo "WARNING: No .whl files found in dist/. Run: python -m build"
105
- fi
106
- ```
42
+ See [REFERENCE.md](REFERENCE.md)
107
43
 
108
44
  ### 3. Run publish
109
45
 
110
46
  After all prerequisite checks pass, run the registry-specific command:
111
47
 
112
- ```bash
113
- # npm
114
- npm publish --access public
115
-
116
- # crates.io
117
- cargo publish
118
-
119
- # PyPI
120
- python -m twine upload dist/* # or: poetry publish
121
-
122
- # Homebrew (opens PR, does not publish directly)
123
- brew bump-formula-pr --url=<tarball-url> <formula-name>
124
- ```
48
+ See [REFERENCE.md](REFERENCE.md)
125
49
 
126
50
  ### 4. Verify publish success
127
51
 
128
52
  After publish, confirm the version appears on the registry:
129
53
 
130
- ```bash
131
- # npm
132
- npm view "$PACKAGE_NAME" versions --json 2>/dev/null | grep -q "\"$CURRENT_VER\"" && echo "OK: npm publish confirmed"
133
-
134
- # crates.io
135
- cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER\"" && echo "OK: crates.io publish confirmed"
136
-
137
- # PyPI
138
- pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
139
- ```
54
+ See [REFERENCE.md](REFERENCE.md)
140
55
 
141
56
  ### 5. Error handling
142
57
 
143
58
  On failure, surface actionable hints:
144
59
 
145
- ```bash
146
- # Generic failure handler
147
- if [ $? -ne 0 ]; then
148
- case "$REGISTRY" in
149
- npm)
150
- echo "FAIL: npm publish failed."
151
- echo " Common causes:"
152
- echo " - NPM_TOKEN not set in secrets: add to GitHub repo secrets"
153
- echo " - Version already published: bump version in package.json"
154
- echo " - Two-factor auth required: use --otp=<code> flag"
155
- echo " - Package scoped but not public: add --access public"
156
- ;;
157
- crates.io)
158
- echo "FAIL: cargo publish failed."
159
- echo " Common causes:"
160
- echo " - CARGO_REGISTRY_TOKEN not configured: see ~/.cargo/config.toml"
161
- echo " - Version already published: bump version in Cargo.toml"
162
- echo " - Local changes not committed: cargo publish requires clean working tree"
163
- ;;
164
- pypi)
165
- echo "FAIL: PyPI publish failed."
166
- echo " Common causes:"
167
- echo " - TWINE_PASSWORD not configured: set env var or ~/.pypirc"
168
- echo " - Build artifacts missing: run python -m build first"
169
- echo " - Version conflict: version already exists on PyPI"
170
- ;;
171
- esac
172
- exit 1
173
- fi
174
- ```
60
+ See [REFERENCE.md](REFERENCE.md)
175
61
 
176
62
  ### 6. Dry-run mode (`--dry-run`)
177
63
 
178
64
  Run `--dry-run` to verify all prerequisites without actually publishing:
179
65
 
180
- ```bash
181
- # Example output
182
- $ publish-package --dry-run
183
-
184
- [DRY-RUN] Detected package type: npm
185
- [DRY-RUN] Package: my-package v0.4.0
186
- [DRY-RUN] Checking NPM_TOKEN... OK
187
- [DRY-RUN] Checking version 0.4.0 not already published... OK
188
- [DRY-RUN] Checking build artifacts... WARNING: package.json modified after build
189
- [DRY-RUN] Checking CHANGELOG... OK
190
- [DRY-RUN] Would run: npm publish --access public
191
- [DRY-RUN] Exiting without publishing.
192
- ```
66
+ See [REFERENCE.md](REFERENCE.md)
193
67
 
194
68
  ### 7. Dry-run mode per registry
195
69
 
196
- ```bash
197
- # npm dry-run
198
- npm publish --access public --dry-run
199
-
200
- # crates.io dry-run (cargo does not have a publish dry-run; use --dry-run flag for validation only)
201
- cargo package --list 2>/dev/null
202
-
203
- # PyPI dry-run
204
- python -m twine upload --repository testpypi dist/* # test.pypi.org
205
- ```
206
-
207
- ## Options
208
-
209
- | Flag | Description |
210
- |------|-------------|
211
- | `--dry-run` | Verify prerequisites and show publish command without executing |
212
- | `--registry <type>` | Force registry type (skip auto-detection) |
213
- | `--otp <code>` | One-time password for npm 2FA |
214
- | `--no-verify` | Skip prerequisite checks (use with caution) |
215
-
216
- ## Examples
217
-
218
- ### Publish an npm package
219
-
220
- ```bash
221
- # Verify first
222
- publish-package --dry-run
223
-
224
- # Publish
225
- publish-package
226
-
227
- # Output:
228
- # [npm] Publishing my-package v0.4.0...
229
- # OK: npm publish confirmed (my-package@0.4.0 on registry)
230
- ```
231
-
232
- ### Publish a Rust crate
233
-
234
- ```bash
235
- export CARGO_REGISTRY_TOKEN=<token>
236
- publish-package --dry-run
237
- publish-package
238
- ```
239
-
240
- ### Missing token scenario
241
-
242
- ```bash
243
- $ publish-package
244
- FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
245
- ```
246
-
247
- ## Integration with release-branch
248
-
249
- When wired into `release-branch`, add a step after git push:
250
-
251
- ```
252
- 6a. Run publish-package to publish to package registries
253
- → verify: publish-package --dry-run && publish-package
254
- ```
70
+ See [REFERENCE.md](REFERENCE.md)
255
71
 
256
72
  ## Verify
257
73
 
@@ -1,5 +1,7 @@
1
1
  # Release Branch — Reference
2
2
 
3
+ # Release Branch — Reference
4
+
3
5
  ## PR body template (team-pr mode)
4
6
 
5
7
  ```bash
@@ -53,3 +55,84 @@ After landing the branch, record delivery metrics for this story:
53
55
  cycle_minutes: 90
54
56
  bcp_per_hour: 2.0
55
57
  ```
58
+
59
+ ---
60
+
61
+ ## Solo-local fallback detail
62
+
63
+ The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
64
+
65
+ **Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
66
+
67
+ ## Handoff
68
+
69
+ Gate: READY -> next: survey-context
70
+ Writes: state.yaml handoff.next_skill = survey-context
71
+
72
+ ---
73
+
74
+ ## Reference block 1
75
+
76
+ ```bash
77
+ # Fallback: manual squash-merge when land-branch.sh is absent
78
+ FEATURE_BRANCH=<task-slug>
79
+ DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
80
+
81
+ # Ensure we're on the feature branch
82
+ if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
83
+ git checkout "$FEATURE_BRANCH"
84
+ fi
85
+
86
+ # Checkout default branch and update
87
+ git checkout "$DEFAULT_BRANCH"
88
+ git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
89
+
90
+ # Squash-merge the feature branch
91
+ git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
92
+
93
+ # Push
94
+ git push origin "$DEFAULT_BRANCH"
95
+
96
+ # Clean up local feature branch
97
+ git branch -d "$FEATURE_BRANCH"
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Reference block 2
103
+
104
+ ```bash
105
+ echo "==> Polling CI for main branch..."
106
+ TIMEOUT=600 # 10 minutes
107
+ INTERVAL=30 # poll every 30 seconds
108
+ ELAPSED=0
109
+
110
+ while [ $ELAPSED -lt $TIMEOUT ]; do
111
+ CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
112
+ CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
113
+ CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
114
+ CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
115
+ CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
116
+
117
+ if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
118
+ echo "OK: CI passed for $(git rev-parse --short HEAD)"
119
+ bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
120
+ echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
121
+ break
122
+ fi
123
+
124
+ if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
125
+ echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
126
+ echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
127
+ echo " Handoff to fix-bug with the failure URL above."
128
+ return 1
129
+ fi
130
+
131
+ sleep $INTERVAL
132
+ ELAPSED=$((ELAPSED + INTERVAL))
133
+ echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
134
+ done
135
+
136
+ echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
137
+ return 1
138
+ ```
@@ -63,29 +63,7 @@ bash scripts/land-branch.sh <task-slug> "feat(scope): description"
63
63
  ```
64
64
 
65
65
  **Path B — `scripts/land-branch.sh` missing (fallback):**
66
- ```bash
67
- # Fallback: manual squash-merge when land-branch.sh is absent
68
- FEATURE_BRANCH=<task-slug>
69
- DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
70
-
71
- # Ensure we're on the feature branch
72
- if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
73
- git checkout "$FEATURE_BRANCH"
74
- fi
75
-
76
- # Checkout default branch and update
77
- git checkout "$DEFAULT_BRANCH"
78
- git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
79
-
80
- # Squash-merge the feature branch
81
- git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
82
-
83
- # Push
84
- git push origin "$DEFAULT_BRANCH"
85
-
86
- # Clean up local feature branch
87
- git branch -d "$FEATURE_BRANCH"
88
- ```
66
+ See [REFERENCE.md](REFERENCE.md)
89
67
 
90
68
  **Report which path was taken.** Print exactly:
91
69
  - `"used land-branch.sh"` if Path A
@@ -117,41 +95,7 @@ mv specs/epics/eNN-slug specs/epics/archive/
117
95
 
118
96
  After push (solo-local step 5 or team-pr step 7), verify the CI workflow completes successfully:
119
97
 
120
- ```bash
121
- echo "==> Polling CI for main branch..."
122
- TIMEOUT=600 # 10 minutes
123
- INTERVAL=30 # poll every 30 seconds
124
- ELAPSED=0
125
-
126
- while [ $ELAPSED -lt $TIMEOUT ]; do
127
- CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
128
- CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
129
- CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
130
- CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
131
- CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
132
-
133
- if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
134
- echo "OK: CI passed for $(git rev-parse --short HEAD)"
135
- bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
136
- echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
137
- break
138
- fi
139
-
140
- if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
141
- echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
142
- echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
143
- echo " Handoff to fix-bug with the failure URL above."
144
- return 1
145
- fi
146
-
147
- sleep $INTERVAL
148
- ELAPSED=$((ELAPSED + INTERVAL))
149
- echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
150
- done
151
-
152
- echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
153
- return 1
154
- ```
98
+ See [REFERENCE.md](REFERENCE.md)
155
99
 
156
100
  - [ ] CI workflow passes after push
157
101
  - [ ] `release.ci_verified: true` documented in state.yaml
@@ -176,14 +120,3 @@ git checkout main && git status && pwd
176
120
  ```
177
121
 
178
122
  Report: "Branch released. Integrate mode: <solo-local|team-pr>. cwd: $(pwd) on $(git branch --show-current)."
179
-
180
- ## Solo-local fallback detail
181
-
182
- The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
183
-
184
- **Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
185
-
186
- ## Handoff
187
-
188
- Gate: READY -> next: survey-context
189
- Writes: state.yaml handoff.next_skill = survey-context
@@ -6,6 +6,7 @@ set -euo pipefail
6
6
 
7
7
  REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
8
8
  TARGET="$REPO_ROOT/docs/references/model-profiles.md"
9
+ mkdir -p "$(dirname "$TARGET")"
9
10
 
10
11
  cd "$REPO_ROOT"
11
12
 
@@ -231,6 +231,9 @@ if [[ -f "$validate_script" ]] && command -v python3 &>/dev/null; then
231
231
  fi
232
232
 
233
233
  # Regenerate derived reference tables from live SKILL.md frontmatter
234
- bash "$REPO_ROOT/scripts/generate-reference-tables.sh"
234
+ # Only in dev context (with .git) — not during consumer npm install where docs/ is excluded
235
+ if [[ -d "$REPO_ROOT/.git" ]]; then
236
+ bash "$REPO_ROOT/scripts/generate-reference-tables.sh"
237
+ fi
235
238
 
236
239
  exit 0
@@ -0,0 +1,85 @@
1
+ # Confidence Scoring Rubric
2
+
3
+ Every finding that survives Phase 4 false-positive filtering receives a confidence
4
+ score from 1 (speculative) to 10 (certain). Only findings ≥ 8 are reported.
5
+
6
+ ## Score 9–10: Certain Exploit Path
7
+
8
+ **Criteria:**
9
+ - Concrete, testable exploit with clear reproduction steps
10
+ - No assumptions about uncommon configurations
11
+ - No chain of multiple unlikely conditions
12
+ - Attacker has full control over the input vector
13
+
14
+ **Examples:**
15
+ - User-supplied SQL in a `SELECT` statement with no parameterization
16
+ - `os.system(f"rm {user_path}")` where user controls the path
17
+ - Pickle deserialization of user-supplied data without any wrapping
18
+
19
+ **Severity:** HIGH
20
+
21
+ ## Score 8: Clear Vulnerability Pattern
22
+
23
+ **Criteria:**
24
+ - Well-known vulnerability pattern with standard exploitation method
25
+ - Requires specific conditions but conditions are commonly met
26
+ - Exploitability is well-documented in OWASP / CVE databases
27
+
28
+ **Examples:**
29
+ - JWT without signature verification in authentication middleware
30
+ - SSRF where attacker controls the full URL including host
31
+ - Hardcoded AWS secret key in source code
32
+
33
+ **Severity:** HIGH or MEDIUM
34
+
35
+ ## Score 7: Suspicious Pattern
36
+
37
+ **Criteria:**
38
+ - Unusual code that may indicate a vulnerability
39
+ - Requires specific conditions that may not be present
40
+ - Alternative secure interpretation is equally likely
41
+ - Defense-in-depth concern rather than direct exploit
42
+
43
+ **Examples:**
44
+ - A function accepting user input that passes through multiple layers before reaching a sink (unclear if sanitized)
45
+ - Custom encryption implementation (likely weak, but may not process sensitive data)
46
+ - Path construction that looks safe but has a subtle bypass
47
+
48
+ **Severity:** LOW or suppress
49
+
50
+ ## Score < 7: Do Not Report
51
+
52
+ **Criteria:**
53
+ - Theoretical concern without exploit path
54
+ - Requires unrealistic attacker capabilities
55
+ - Violates one or more hard exclusion rules
56
+ - Better handled by separate tooling (dependency scanner, SAST, secret scanner)
57
+ - Purely stylistic or best-practice concern without security impact
58
+
59
+ **Examples:**
60
+ - "This function doesn't validate all inputs" without proving the validated input is the attack surface
61
+ - "This uses MD5" where the hash is not used for security (e.g., cache key)
62
+ - "This function could consume too much memory" (DOS exclusion)
63
+
64
+ **Action:** Suppress entirely. Do not include in report.
65
+
66
+ ## Severity Mapping
67
+
68
+ Once confidence ≥ 8 is confirmed, map to severity:
69
+
70
+ | Severity | Impact | Examples |
71
+ |----------|--------|---------|
72
+ | **CRITICAL** | Remote compromise, full data breach | RCE, auth bypass with admin escalation, SQLi with data exfiltration |
73
+ | **HIGH** | Significant security boundary crossed | SSRF to internal services, hardcoded cloud credentials, insecure deserialization |
74
+ | **MEDIUM** | Limited impact or requires conditions | Stored XSS behind auth, IDOR on non-sensitive data, weak but not broken crypto |
75
+ | **LOW** | Defense-in-depth, minimal blast radius | Missing security header, verbose error messages in non-production |
76
+
77
+ ## Quality Gate
78
+
79
+ The confidence rubric double-checks each finding against three lenses:
80
+
81
+ | Lens | Question |
82
+ |------|----------|
83
+ | **Exploitability** | Can a real attacker trigger this from a trust boundary? |
84
+ | **Actionability** | Would a security engineer accept a fix recommendation for this? |
85
+ | **Precedent** | Has this type of finding passed/failed human review before? |
@@ -0,0 +1,68 @@
1
+ # False-Positive Exclusion Rules
2
+
3
+ Applied during Phase 4 of the scan. Findings matching any hard exclusion are
4
+ automatically suppressed. Precedents from prior reviews guide borderline cases.
5
+
6
+ ## Hard Exclusions
7
+
8
+ Automatically exclude findings matching these patterns:
9
+
10
+ | # | Rule | Rationale |
11
+ |---|------|-----------|
12
+ | 1 | **Denial of Service (DOS)** — resource exhaustion, CPU/memory attacks | Handled separately; not actionable in code review |
13
+ | 2 | **Secrets on disk** if otherwise secured | Secrets management is a separate concern |
14
+ | 3 | **Rate limiting** concerns | Operational, not a code vulnerability |
15
+ | 4 | **Memory consumption / CPU exhaustion** | Not actionable in diff review |
16
+ | 5 | **Input validation on non-security-critical fields** without proven exploit path | Theoretical, not concrete |
17
+ | 6 | **GitHub Actions input sanitization** unless clearly triggerable via untrusted input | Most workflow vulns are not exploitable |
18
+ | 7 | **Lack of hardening measures** | Code is not expected to implement all best practices |
19
+ | 8 | **Race conditions / timing attacks** that are theoretical | Only report if concretely problematic |
20
+ | 9 | **Outdated third-party libraries** | Managed separately by dependency scanners |
21
+ | 10 | **Memory safety** in Rust or other memory-safe languages | Impossible by language guarantees |
22
+ | 11 | **Unit test files only** | Not production risk |
23
+ | 12 | **Log spoofing** | Outputting unsanitized input to logs is not a vuln |
24
+ | 13 | **SSRF that only controls path** | Only host/protocol control is exploitable |
25
+ | 14 | **User-controlled content in AI system prompts** | Not a security vulnerability |
26
+ | 15 | **Regex injection** | Injecting untrusted content into regex is not a vuln |
27
+ | 16 | **Regex DOS** | Excluded alongside general DOS |
28
+ | 17 | **Documentation files** (.md, .txt) | Insecure docs are not code vulnerabilities |
29
+ | 18 | **Lack of audit logs** | Not a vulnerability |
30
+
31
+ ## Precedent Rules
32
+
33
+ These guide borderline cases based on prior human review decisions:
34
+
35
+ | # | Precedent | Reasoning |
36
+ |---|-----------|-----------|
37
+ | 1 | **Logging high-value secrets in plaintext IS a vuln.** Logging URLs is safe. | Secrets in logs = credential exposure; URLs are not secrets |
38
+ | 2 | **UUIDs are unguessable** — no validation needed | Cryptographic property of UUID v4/v7 |
39
+ | 3 | **Environment variables and CLI flags are trusted values** | Attackers cannot modify these in secure environments |
40
+ | 4 | **Resource management issues** (memory leaks, fd leaks) are NOT valid | Operational, not security |
41
+ | 5 | **Tabnabbing, XS-Leaks, prototype pollution, open redirects** — do NOT report unless extremely high confidence | Subtle, low-impact, high false-positive rate |
42
+ | 6 | **React/Angular XSS** — safe unless `dangerouslySetInnerHTML`, `bypassSecurityTrustHtml`, etc. | Framework auto-escapes |
43
+ | 7 | **GitHub Action workflow vulns** — verify concrete attack path before reporting | Most are theoretical |
44
+ | 8 | **Client-side JS/TS auth checks** — not a vuln; server is authoritative | Client code is untrusted |
45
+ | 9 | **IPython notebook vulns** — only report if concrete untrusted-input trigger | Most are not exploitable |
46
+ | 10 | **Logging non-PII data** — not a vuln even if sensitive. Only PII/secrets/passwords. | Intent: operational logging vs credential exposure |
47
+ | 11 | **Shell script command injection** — only report if concrete untrusted-input path | Most shell scripts don't process untrusted input |
48
+
49
+ ## Confidence Scoring
50
+
51
+ Findings that survive exclusions get a confidence score (1–10):
52
+
53
+ | Range | Meaning | Action |
54
+ |-------|---------|--------|
55
+ | 9–10 | Certain exploit path, testable | Report as HIGH |
56
+ | 8 | Clear vulnerability pattern | Report as HIGH/MEDIUM |
57
+ | 7 | Suspicious, needs conditions | Report as LOW or suppress |
58
+ | <7 | Too speculative | **Do not report** |
59
+
60
+ **Hard threshold:** Only report findings with confidence ≥ 8.
61
+
62
+ ## Signal Quality Criteria
63
+
64
+ For remaining findings, assess:
65
+ 1. Is there a concrete, exploitable vulnerability with a clear attack path?
66
+ 2. Does this represent a real security risk (vs theoretical best practice)?
67
+ 3. Are there specific code locations and reproduction steps?
68
+ 4. Would this finding be actionable for a security team?