@softspark/ai-toolkit 2.4.1 → 2.6.1
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.
- package/AGENTS.md +33 -20
- package/CHANGELOG.md +57 -0
- package/README.md +29 -13
- package/app/.claude-plugin/plugin.json +3 -2
- package/app/ARCHITECTURE.md +11 -0
- package/app/agents/code-reviewer.md +6 -7
- package/app/agents/frontend-specialist.md +33 -2
- package/app/agents/seo-specialist.md +1 -1
- package/app/personas/frontend-lead.md +48 -5
- package/app/skills/a11y-validate/SKILL.md +377 -0
- package/app/skills/a11y-validate/reference/aria-patterns.md +259 -0
- package/app/skills/a11y-validate/reference/eaa-compliance.md +252 -0
- package/app/skills/a11y-validate/reference/mobile-eaa.md +329 -0
- package/app/skills/a11y-validate/reference/wcag-2-1-aa.md +285 -0
- package/app/skills/a11y-validate/reference/wcag-2-2-aa.md +221 -0
- package/app/skills/a11y-validate/scripts/a11y-scanner.py +639 -0
- package/app/skills/clean-code/reference/python.md +3 -3
- package/app/skills/design-engineering/SKILL.md +2 -5
- package/app/skills/hipaa-validate/SKILL.md +39 -23
- package/app/skills/hipaa-validate/scripts/hipaa_scan.py +64 -7
- package/app/skills/review/SKILL.md +30 -6
- package/app/skills/seo-validate/SKILL.md +460 -0
- package/app/skills/seo-validate/reference/core-web-vitals.md +445 -0
- package/app/skills/seo-validate/reference/geo-aeo-patterns.md +259 -0
- package/app/skills/seo-validate/reference/geo-guidelines.md +248 -0
- package/app/skills/seo-validate/reference/schema-types.md +465 -0
- package/app/skills/seo-validate/reference/spa-ssg-patterns.md +351 -0
- package/app/skills/seo-validate/reference/w3c-guidelines.md +289 -0
- package/app/skills/seo-validate/scripts/seo-scanner.py +549 -0
- package/bin/ai-toolkit.js +24 -9
- package/kb/reference/architecture-overview.md +1 -1
- package/kb/reference/comparison.md +1 -1
- package/kb/reference/opencode-compatibility.md +161 -0
- package/kb/reference/skills-catalog.md +3 -1
- package/llms-full.txt +177 -6
- package/llms.txt +1 -0
- package/manifest.json +3 -3
- package/package.json +6 -3
- package/scripts/config_cli.py +4 -10
- package/scripts/doctor.py +3 -3
- package/scripts/generate_opencode.py +117 -0
- package/scripts/generate_opencode_agents.py +126 -0
- package/scripts/generate_opencode_commands.py +158 -0
- package/scripts/generate_opencode_json.py +133 -0
- package/scripts/generate_opencode_plugin.py +169 -0
- package/scripts/install_steps/ai_tools.py +117 -1
- package/scripts/install_steps/install_state.py +1 -1
- package/scripts/plugin.py +1 -1
|
@@ -100,7 +100,11 @@ Scan the full project for log/print statements that reference PHI keywords.
|
|
|
100
100
|
| `console\.\w+\(.*req\.body` | WARN | JS/TS | Raw request body may contain PHI |
|
|
101
101
|
| `JSON\.stringify\(.*patient` | WARN | JS/TS | Full patient object serialization |
|
|
102
102
|
| `print\(.*\b(patient\|ssn\|social.security)` | HIGH | Python | PHI in print statements |
|
|
103
|
-
| `logging\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Python | PHI
|
|
103
|
+
| `(logging\|logger\|pprint)\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Python | PHI in logger/named logger/pprint output |
|
|
104
|
+
| `print\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body may contain PHI (Django/Flask/FastAPI) |
|
|
105
|
+
| `(logging\|logger)\.\w+\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body in logger |
|
|
106
|
+
| `\brepr\(.*\b(patient\|ssn\|mrn)` | WARN | Python | repr() may expose PHI fields |
|
|
107
|
+
| `\bvars\(.*\b(patient\|ssn\|mrn)` | WARN | Python | vars() dumps all PHI fields |
|
|
104
108
|
| `fmt\.Print.*\b(patient\|ssn\|mrn)` | HIGH | Go | PHI in fmt output |
|
|
105
109
|
| `log\.\w+\(.*\b(patient\|ssn\|mrn)` | HIGH | Go/Any | PHI in log calls |
|
|
106
110
|
| `System\.out\.print.*\b(patient\|ssn\|mrn)` | HIGH | Java | PHI in stdout |
|
|
@@ -110,7 +114,7 @@ Scan the full project for log/print statements that reference PHI keywords.
|
|
|
110
114
|
| `Console\.Write.*\b(patient\|ssn\|mrn)` | HIGH | C# | PHI in Console output |
|
|
111
115
|
| `_logger\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | C# | PHI in ILogger calls |
|
|
112
116
|
|
|
113
|
-
> **Language coverage note**: JS/TS patterns are the most comprehensive. Go, Ruby, and Java have baseline coverage for common log patterns. Contributions for additional language-specific patterns are welcome.
|
|
117
|
+
> **Language coverage note**: JS/TS and Python patterns are the most comprehensive. Go, Ruby, and Java have baseline coverage for common log patterns. Contributions for additional language-specific patterns are welcome.
|
|
114
118
|
|
|
115
119
|
**Minimum Necessary violations** (§164.502(b)):
|
|
116
120
|
|
|
@@ -135,7 +139,7 @@ Scan the full project for files that handle PHI data operations but lack audit-r
|
|
|
135
139
|
|
|
136
140
|
**PHI route file definition**: A file qualifies if it contains BOTH:
|
|
137
141
|
1. A healthcare keyword from Step 0 (`patient`, `diagnosis`, `medication`, etc.)
|
|
138
|
-
2. A data operation pattern: `router`, `app.get`, `app.post`, `app.put`, `app.delete`, `@RequestMapping`, `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `Model.find`, `Model.save`, `Model.update`, `db.query`, `db.execute`, `cursor.execute`, `repository.`, `findBy`, `save(`, `delete(`
|
|
142
|
+
2. A data operation pattern: `router`, `app.get`, `app.post`, `app.put`, `app.delete`, `@RequestMapping`, `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `Model.find`, `Model.save`, `Model.update`, `db.query`, `db.execute`, `cursor.execute`, `repository.`, `findBy`, `save(`, `delete(`, `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `\bsession.(query|add|execute|delete|merge)\b` (word-anchored — SQLAlchemy only, avoids matching Express `req.session.save`)
|
|
139
143
|
|
|
140
144
|
Files with a healthcare keyword but no data operation pattern are excluded.
|
|
141
145
|
|
|
@@ -158,13 +162,20 @@ See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(b) for audit
|
|
|
158
162
|
|
|
159
163
|
*Context-gated: scans PHI-adjacent files only.*
|
|
160
164
|
|
|
161
|
-
| Pattern | Severity | Description |
|
|
162
|
-
|
|
163
|
-
| `http://` in API calls (not `localhost`/`127.0.0.1`) | HIGH | §164.312(e)(1) requires encryption in transit |
|
|
164
|
-
| Missing TLS/SSL config in database connections | HIGH | Database connections must be encrypted |
|
|
165
|
-
| `rejectUnauthorized:\s*false` | HIGH | TLS verification disabled |
|
|
166
|
-
| `ws://` (WebSocket without TLS) | WARN | Unencrypted WebSocket may carry PHI |
|
|
167
|
-
|
|
|
165
|
+
| Pattern | Severity | Language | Description |
|
|
166
|
+
|---------|----------|----------|-------------|
|
|
167
|
+
| `http://` in API calls (not `localhost`/`127.0.0.1`) | HIGH | Any | §164.312(e)(1) requires encryption in transit |
|
|
168
|
+
| Missing TLS/SSL config in database connections | HIGH | Any | Database connections must be encrypted |
|
|
169
|
+
| `rejectUnauthorized:\s*false` | HIGH | Any | TLS verification disabled |
|
|
170
|
+
| `ws://` (WebSocket without TLS) | WARN | Any | Unencrypted WebSocket may carry PHI |
|
|
171
|
+
| `verify\s*=\s*False` | HIGH | Python | TLS verification disabled (requests/httpx) |
|
|
172
|
+
| `InsecureRequestWarning` | WARN | Python | TLS warning suppressed |
|
|
173
|
+
| `[,(]\s*ssl\s*=\s*False\b` | HIGH | Python | SSL disabled in connector call (anchored to arg position to avoid matching `is_ssl_enabled = False`) |
|
|
174
|
+
| `ssl\.CERT_NONE` | HIGH | Python | TLS certificate verification disabled (anchored to `ssl.` module) |
|
|
175
|
+
| `check_hostname\s*=\s*False` | HIGH | Python | TLS hostname verification disabled |
|
|
176
|
+
| `urllib3\.disable_warnings` | WARN | Python | TLS warnings suppressed (urllib3) |
|
|
177
|
+
| `SECURE_SSL_REDIRECT\s*=\s*False` | WARN | Python | Django HTTPS redirect disabled (commonly False in dev settings — verify production config) |
|
|
178
|
+
| `NODE_TLS_REJECT_UNAUTHORIZED.*0` | HIGH | JS/TS | TLS rejection disabled globally |
|
|
168
179
|
|
|
169
180
|
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(e)(1) for transmission security requirements.
|
|
170
181
|
|
|
@@ -194,13 +205,16 @@ See: [reference/phi-identifiers.md](reference/phi-identifiers.md) for the full l
|
|
|
194
205
|
|
|
195
206
|
*Context-gated: scans PHI-adjacent files only. Heuristic — flags potential gaps.*
|
|
196
207
|
|
|
197
|
-
**Auth keywords** (co-occurrence check): `auth`, `authenticate`, `requireAuth`, `isAuthenticated`, `protect`, `guard`, `Authorize`, `login_required`, `Permission`
|
|
208
|
+
**Auth keywords** (co-occurrence check): `auth`, `authenticate`, `requireAuth`, `isAuthenticated`, `protect`, `guard`, `Authorize`, `login_required`, `Permission`, `permission_required`, `LoginRequiredMixin`, `PermissionRequiredMixin`, `IsAuthenticated`, `Depends`, `Security`
|
|
198
209
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
|
202
|
-
|
|
203
|
-
|
|
|
210
|
+
**Data operation patterns** (Python frameworks): `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `cursor.execute`, `\bsession.(query|execute)\b` (word-anchored — SQLAlchemy only)
|
|
211
|
+
|
|
212
|
+
| Pattern | Severity | Language | Description |
|
|
213
|
+
|---------|----------|----------|-------------|
|
|
214
|
+
| PHI route file without any auth keywords in same file | WARN | Any | POTENTIAL access control gap — verify auth middleware covers these routes (§164.312(d)) |
|
|
215
|
+
| `Access-Control-Allow-Origin:\s*\*` or `origin:\s*(true\|\*)` in PHI-adjacent files | HIGH | Any | Unrestricted cross-origin access to PHI endpoints |
|
|
216
|
+
| Routes marked `public`, `noAuth`, `anonymous` exposing PHI keywords | HIGH | Any | PHI must require authentication |
|
|
217
|
+
| `permission_classes\s*=.*AllowAny` | WARN | Python | DRF AllowAny — verify no PHI exposed |
|
|
204
218
|
|
|
205
219
|
> **Note**: Auth middleware is commonly applied at router-level or app-level. The co-occurrence heuristic checks the same file only. False positives expected when auth is configured globally. Use `.hipaaignore` to suppress.
|
|
206
220
|
|
|
@@ -253,13 +267,15 @@ Instead of per-finding rows, emit a single **BAA Verification Checklist** in the
|
|
|
253
267
|
|
|
254
268
|
Detects PHI storage patterns without encryption references. Per §164.312(a)(2)(iv), ePHI must be encrypted when stored.
|
|
255
269
|
|
|
256
|
-
| Pattern | Severity | Description |
|
|
257
|
-
|
|
258
|
-
| `encrypt\s*[:=]\s*false` in database config files | HIGH | §164.312(a)(2)(iv) — Encryption explicitly disabled |
|
|
259
|
-
| File write operations (`writeFile`, `fs.write`, `open(.*w`, `File.Create`) in PHI-adjacent code without encryption references | WARN | PHI written to disk may lack encryption at rest |
|
|
260
|
-
| Database connection without `ssl`, `encrypt`, or `tls` keywords in PHI-adjacent config | WARN | Database storing PHI should enforce encrypted connections |
|
|
261
|
-
| `localStorage.setItem` or `sessionStorage.setItem` with PHI keywords | HIGH | Browser storage is unencrypted — PHI must not be stored client-side without encryption |
|
|
262
|
-
| `SharedPreferences` or `UserDefaults` with PHI keywords | HIGH | Mobile local storage is unencrypted by default |
|
|
270
|
+
| Pattern | Severity | Language | Description |
|
|
271
|
+
|---------|----------|----------|-------------|
|
|
272
|
+
| `encrypt\s*[:=]\s*false` in database config files | HIGH | Any | §164.312(a)(2)(iv) — Encryption explicitly disabled |
|
|
273
|
+
| File write operations (`writeFile`, `fs.write`, `open(.*w`, `File.Create`) in PHI-adjacent code without encryption references | WARN | Any | PHI written to disk may lack encryption at rest |
|
|
274
|
+
| Database connection without `ssl`, `encrypt`, or `tls` keywords in PHI-adjacent config | WARN | Any | Database storing PHI should enforce encrypted connections |
|
|
275
|
+
| `localStorage.setItem` or `sessionStorage.setItem` with PHI keywords | HIGH | JS/TS | Browser storage is unencrypted — PHI must not be stored client-side without encryption |
|
|
276
|
+
| `SharedPreferences` or `UserDefaults` with PHI keywords | HIGH | Java/Any | Mobile local storage is unencrypted by default |
|
|
277
|
+
| `pickle\.(dump\|dumps)\(` with PHI keywords | HIGH | Python | pickle serialization is unencrypted — PHI must be encrypted at rest |
|
|
278
|
+
| `shelve\.open\(` with PHI keywords | HIGH | Python | shelve storage is unencrypted — PHI must be encrypted at rest |
|
|
263
279
|
|
|
264
280
|
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(a)(2)(iv) for encryption requirements.
|
|
265
281
|
|
|
@@ -62,6 +62,19 @@ LANGUAGE_INDICATORS = {
|
|
|
62
62
|
"*.csproj": "csharp",
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
# Map language tag to file extensions. Used by scan_patterns to avoid
|
|
66
|
+
# cross-language double-flagging when the same regex is valid for more
|
|
67
|
+
# than one language (e.g. `logger.info(...)` in Python vs Java).
|
|
68
|
+
LANG_EXTENSIONS = {
|
|
69
|
+
"js": {".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"},
|
|
70
|
+
"ts": {".ts", ".tsx"},
|
|
71
|
+
"python": {".py", ".pyi"},
|
|
72
|
+
"java": {".java", ".kt", ".scala"},
|
|
73
|
+
"go": {".go"},
|
|
74
|
+
"ruby": {".rb", ".erb"},
|
|
75
|
+
"csharp": {".cs"},
|
|
76
|
+
}
|
|
77
|
+
|
|
65
78
|
# ---------------------------------------------------------------------------
|
|
66
79
|
# Pattern definitions per category
|
|
67
80
|
# ---------------------------------------------------------------------------
|
|
@@ -72,9 +85,15 @@ CAT1_PATTERNS = [
|
|
|
72
85
|
(r"console\.log\(.*patient", "HIGH", "js", "Patient data in console.log", "1"),
|
|
73
86
|
(r"console\.\w+\(.*req\.body", "WARN", "js", "Raw request body may contain PHI", "1"),
|
|
74
87
|
(r"JSON\.stringify\(.*patient", "WARN", "js", "Full patient object serialization", "1"),
|
|
75
|
-
# Python
|
|
88
|
+
# Python (logger pattern covers logging.*, logger.*, and pprint.* in one regex
|
|
89
|
+
# to avoid overlapping findings and double-flag with the Java `logger.` pattern.
|
|
90
|
+
# Language is enforced by file extension via LANG_EXTENSIONS.)
|
|
76
91
|
(r"print\(.*\b(patient|ssn|social.security)", "HIGH", "python", "PHI in print statement", "1"),
|
|
77
|
-
(r"logging\.\w+\(.*\b(patient|ssn|mrn|dob)", "HIGH", "python", "PHI
|
|
92
|
+
(r"(logging|logger|pprint)\.\w+\(.*\b(patient|ssn|mrn|dob)", "HIGH", "python", "PHI in Python logger/pprint", "1"),
|
|
93
|
+
(r"print\(.*request\.(data|json|form|POST|body)", "WARN", "python", "Raw request body may contain PHI", "1"),
|
|
94
|
+
(r"(logging|logger)\.\w+\(.*request\.(data|json|form|POST|body)", "WARN", "python", "Raw request body in logger", "1"),
|
|
95
|
+
(r"\brepr\(.*\b(patient|ssn|mrn)", "WARN", "python", "repr() may expose PHI fields", "1"),
|
|
96
|
+
(r"\bvars\(.*\b(patient|ssn|mrn)", "WARN", "python", "vars() dumps all PHI fields", "1"),
|
|
78
97
|
# Go
|
|
79
98
|
(r"fmt\.Print.*\b(patient|ssn|mrn)", "HIGH", "go", "PHI in fmt output", "1"),
|
|
80
99
|
(r"log\.\w+\(.*\b(patient|ssn|mrn)", "HIGH", "go", "PHI in log call", "1"),
|
|
@@ -101,6 +120,14 @@ CAT3_PATTERNS = [
|
|
|
101
120
|
(r"NODE_TLS_REJECT_UNAUTHORIZED.*0", "HIGH", "js", "TLS rejection disabled globally", "3"),
|
|
102
121
|
(r"verify\s*=\s*False", "HIGH", "python", "TLS verification disabled (requests)", "3"),
|
|
103
122
|
(r"InsecureRequestWarning", "WARN", "python", "TLS warning suppressed", "3"),
|
|
123
|
+
# Anchored to argument position ([, or () to avoid matching `is_ssl_enabled = False`
|
|
124
|
+
(r"[,(]\s*ssl\s*=\s*False\b", "HIGH", "python", "SSL disabled in connector call", "3"),
|
|
125
|
+
(r"ssl\.CERT_NONE", "HIGH", "python", "TLS certificate verification disabled (ssl.CERT_NONE)", "3"),
|
|
126
|
+
(r"check_hostname\s*=\s*False", "HIGH", "python", "TLS hostname verification disabled", "3"),
|
|
127
|
+
(r"urllib3\.disable_warnings", "WARN", "python", "TLS warnings suppressed (urllib3)", "3"),
|
|
128
|
+
# WARN (not HIGH): commonly False in DEBUG/dev settings — compliance reviewer
|
|
129
|
+
# must confirm production config. Avoids flooding every Django project.
|
|
130
|
+
(r"SECURE_SSL_REDIRECT\s*=\s*False", "WARN", "python", "Django HTTPS redirect disabled (verify prod config)", "3"),
|
|
104
131
|
]
|
|
105
132
|
|
|
106
133
|
# Category 4: Hardcoded PHI/Test Data
|
|
@@ -119,6 +146,9 @@ CAT7_PATTERNS = [
|
|
|
119
146
|
(r"sessionStorage\.setItem\(.*\b(patient|ssn|mrn|phi|health)", "HIGH", "js", "PHI in session storage", "7"),
|
|
120
147
|
(r"SharedPreferences.*\b(patient|ssn|mrn|phi|health)", "HIGH", "java", "PHI in unencrypted mobile storage", "7"),
|
|
121
148
|
(r"UserDefaults.*\b(patient|ssn|mrn|phi|health)", "HIGH", "any", "PHI in unencrypted UserDefaults", "7"),
|
|
149
|
+
# Python
|
|
150
|
+
(r"pickle\.(dump|dumps)\(.*\b(patient|phi|health|ssn|mrn)", "HIGH", "python", "PHI in unencrypted pickle", "7"),
|
|
151
|
+
(r"shelve\.open\(.*\b(patient|phi|health|ssn|mrn)", "HIGH", "python", "PHI in unencrypted shelve storage", "7"),
|
|
122
152
|
]
|
|
123
153
|
|
|
124
154
|
# Category 8: PHI Temp File Exposure
|
|
@@ -132,12 +162,17 @@ CAT8_PATTERNS = [
|
|
|
132
162
|
CAT5_AUTH_KEYWORDS = [
|
|
133
163
|
"auth", "authenticate", "requireAuth", "isAuthenticated",
|
|
134
164
|
"protect", "guard", "Authorize", "login_required", "Permission",
|
|
165
|
+
# Python frameworks
|
|
166
|
+
"permission_required", "LoginRequiredMixin", "PermissionRequiredMixin",
|
|
167
|
+
"IsAuthenticated", "Depends", "Security",
|
|
135
168
|
]
|
|
136
169
|
|
|
137
170
|
CAT5_PATTERNS = [
|
|
138
171
|
(r"Access-Control-Allow-Origin:\s*\*", "HIGH", "any", "Unrestricted CORS on PHI endpoint", "5"),
|
|
139
172
|
(r"origin:\s*(true|\*)", "HIGH", "any", "Unrestricted CORS origin", "5"),
|
|
140
173
|
(r"\b(public|noAuth|anonymous)\b.*\b(patient|phi|health|medical)", "HIGH", "any", "Public route exposing PHI", "5"),
|
|
174
|
+
# Python
|
|
175
|
+
(r"permission_classes\s*=.*AllowAny", "WARN", "python", "DRF AllowAny — verify no PHI exposed", "5"),
|
|
141
176
|
]
|
|
142
177
|
|
|
143
178
|
# HIPAA rule citations per category
|
|
@@ -284,7 +319,15 @@ def detect_languages(root: Path) -> set[str]:
|
|
|
284
319
|
|
|
285
320
|
def scan_patterns(files: list[Path], patterns: list[tuple],
|
|
286
321
|
languages: set[str], root: Path) -> list[dict]:
|
|
287
|
-
"""Run regex patterns against files, return findings.
|
|
322
|
+
"""Run regex patterns against files, return findings.
|
|
323
|
+
|
|
324
|
+
Language-tagged patterns fire only when:
|
|
325
|
+
1. The project's detected languages include the tag, AND
|
|
326
|
+
2. The file's extension matches that language (per LANG_EXTENSIONS).
|
|
327
|
+
|
|
328
|
+
This prevents cross-language double-flagging when two languages share
|
|
329
|
+
a regex (e.g. `logger.info(patient)` valid in both Python and Java).
|
|
330
|
+
"""
|
|
288
331
|
findings = []
|
|
289
332
|
for fpath in files:
|
|
290
333
|
try:
|
|
@@ -292,11 +335,16 @@ def scan_patterns(files: list[Path], patterns: list[tuple],
|
|
|
292
335
|
except (OSError, PermissionError):
|
|
293
336
|
continue
|
|
294
337
|
rel = str(fpath.relative_to(root))
|
|
338
|
+
ext = fpath.suffix.lower()
|
|
295
339
|
|
|
296
340
|
for line_num, line in enumerate(lines, 1):
|
|
297
341
|
for pat, severity, lang, desc, cat in patterns:
|
|
298
|
-
if lang != "any"
|
|
299
|
-
|
|
342
|
+
if lang != "any":
|
|
343
|
+
if lang not in languages:
|
|
344
|
+
continue
|
|
345
|
+
exts = LANG_EXTENSIONS.get(lang)
|
|
346
|
+
if exts and ext not in exts:
|
|
347
|
+
continue
|
|
300
348
|
if re.search(pat, line, re.IGNORECASE):
|
|
301
349
|
findings.append({
|
|
302
350
|
"file": rel,
|
|
@@ -333,7 +381,12 @@ def scan_cat2_audit_gaps(phi_files: list[Path], root: Path) -> list[dict]:
|
|
|
333
381
|
r"@(Request|Get|Post|Put|Delete)Mapping|"
|
|
334
382
|
r"Model\.(find|save|update|delete)|"
|
|
335
383
|
r"db\.(query|execute)|cursor\.execute|"
|
|
336
|
-
r"repository\.|findBy|\.save\(|\.delete\(
|
|
384
|
+
r"repository\.|findBy|\.save\(|\.delete\(|"
|
|
385
|
+
# Python frameworks (SQLAlchemy session methods only — avoids matching
|
|
386
|
+
# Express req.session.save/destroy which use different method names)
|
|
387
|
+
r"@app\.route|@blueprint\.route|"
|
|
388
|
+
r"@api_view|ViewSet|APIView|"
|
|
389
|
+
r"\bsession\.(query|add|execute|delete|merge)\b)",
|
|
337
390
|
re.IGNORECASE,
|
|
338
391
|
)
|
|
339
392
|
audit_kw = re.compile(
|
|
@@ -382,7 +435,11 @@ def scan_cat5_access_gaps(phi_files: list[Path], languages: set[str],
|
|
|
382
435
|
)
|
|
383
436
|
data_ops = re.compile(
|
|
384
437
|
r"(router|app\.(get|post|put|delete)|"
|
|
385
|
-
r"@(Request|Get|Post|Put|Delete)Mapping
|
|
438
|
+
r"@(Request|Get|Post|Put|Delete)Mapping|"
|
|
439
|
+
# Python frameworks (session methods anchored to SQLAlchemy)
|
|
440
|
+
r"@app\.route|@blueprint\.route|"
|
|
441
|
+
r"@api_view|ViewSet|APIView|"
|
|
442
|
+
r"cursor\.execute|\bsession\.(query|execute)\b)",
|
|
386
443
|
re.IGNORECASE,
|
|
387
444
|
)
|
|
388
445
|
|
|
@@ -24,7 +24,7 @@ Reviews code changes for quality and issues.
|
|
|
24
24
|
Before starting manual review, run the diff analyzer script to get a structured risk assessment:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
python3
|
|
27
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/diff-analyzer.py [base_branch]
|
|
28
28
|
# Default base branch: main
|
|
29
29
|
# Example: python3 scripts/diff-analyzer.py develop
|
|
30
30
|
```
|
|
@@ -90,11 +90,35 @@ After all reviewers complete:
|
|
|
90
90
|
- [ ] No code duplication
|
|
91
91
|
- [ ] Appropriate abstractions
|
|
92
92
|
|
|
93
|
-
### Security
|
|
94
|
-
- [ ]
|
|
95
|
-
- [ ]
|
|
96
|
-
- [ ]
|
|
97
|
-
- [ ]
|
|
93
|
+
### Security (OWASP Top 10)
|
|
94
|
+
- [ ] A01: Proper auth/authorization on all endpoints
|
|
95
|
+
- [ ] A02: No weak crypto, HTTPS for external comms
|
|
96
|
+
- [ ] A03: Input validation, parameterized queries, output encoding (XSS)
|
|
97
|
+
- [ ] A04: Threat model assumptions documented for new features
|
|
98
|
+
- [ ] A05: No debug mode, default credentials, or verbose errors in prod config
|
|
99
|
+
- [ ] A06: Dependencies checked for known CVEs
|
|
100
|
+
- [ ] A07: No hardcoded secrets, session management correct
|
|
101
|
+
- [ ] A08: Integrity checks on deserialized data, CI/CD pipeline safety
|
|
102
|
+
- [ ] A09: Security-relevant events logged (without PII)
|
|
103
|
+
- [ ] A10: External URL handling validates scheme/host (SSRF prevention)
|
|
104
|
+
|
|
105
|
+
### API / Contract Changes
|
|
106
|
+
- [ ] Backward compatibility preserved (no silent breaking changes)
|
|
107
|
+
- [ ] API versioning updated if contract changed
|
|
108
|
+
- [ ] Schema validation on request/response
|
|
109
|
+
- [ ] Error responses follow project convention
|
|
110
|
+
|
|
111
|
+
### Concurrency / Async
|
|
112
|
+
- [ ] Shared mutable state protected (locks, atomics, channels)
|
|
113
|
+
- [ ] No fire-and-forget promises without error handling
|
|
114
|
+
- [ ] Database transactions scoped correctly (no long-held locks)
|
|
115
|
+
- [ ] Race condition risk assessed for concurrent access paths
|
|
116
|
+
|
|
117
|
+
### Migrations / Schema Changes
|
|
118
|
+
- [ ] Migration is reversible (has rollback path)
|
|
119
|
+
- [ ] No table locks on large tables during peak hours
|
|
120
|
+
- [ ] Data backfill handles NULL/missing values
|
|
121
|
+
- [ ] Indexes added for new query patterns
|
|
98
122
|
|
|
99
123
|
### Performance
|
|
100
124
|
- [ ] No N+1 queries
|