Skip to content

Commit 36efa49

Browse files
author
Arnold Cartagena
committed
fix: address PR review findings from security CI hardening
- Remove unused id-token:write permission from security-sweep workflow - Exclude accepted findings from open count in baseline report - Support Annotated[str, Field(max_length=...)] in input bounds linter - Document custom lint scripts as non-blocking until issues #12-#28 resolved
1 parent eb460a8 commit 36efa49

File tree

4 files changed

+14
-6
lines changed

4 files changed

+14
-6
lines changed

.github/workflows/security-sweep.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jobs:
2222
permissions:
2323
contents: read
2424
issues: write
25-
id-token: write
2625

2726
steps:
2827
- name: Checkout repository

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ Minimum ~43 adversarial tests before first push.
278278

279279
| Trigger | Checks | Cost |
280280
|---------|--------|------|
281-
| Every PR | `bandit -r src/ -ll -ii --exclude tests/`, `pip-audit`, `pnpm audit`, 3 custom lint scripts (tenant isolation, input bounds, timing-safe comparisons) | Free, ~10s |
281+
| Every PR | `bandit -r src/ -ll -ii --exclude tests/`, `pip-audit`, `pnpm audit`, 3 custom lint scripts (tenant isolation, input bounds, timing-safe comparisons) **lint scripts are non-blocking (`continue-on-error`) until pre-existing issues #12-#28 are resolved** | Free, ~10s |
282282
| Every PR | Claude code review via `review.yml` — reads diff, applies `code-reviewer.md` checklist, posts sticky PR comment | Claude OAuth (subscription) |
283283
| Weekly / pre-release | Full security sweep against `security/baseline.json` — only surfaces new or regressed findings | Claude OAuth |
284284

scripts/security-lint/check_input_bounds.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,19 @@ def _field_call_has_max_length(node: ast.expr) -> bool:
219219

220220

221221
def _field_has_max_length(assign: ast.AnnAssign) -> bool:
222-
"""Return True if the assignment has a Field() default with max_length."""
223-
if assign.value is None:
222+
"""Return True if max_length is declared as a default OR inside Annotated[...]."""
223+
# Check assign.value (e.g. name: str = Field(max_length=255))
224+
if assign.value is not None and _field_call_has_max_length(assign.value):
225+
return True
226+
# Check annotation for Annotated[str, Field(max_length=255)]
227+
ann = assign.annotation
228+
if not isinstance(ann, ast.Subscript):
229+
return False
230+
if not (isinstance(ann.value, ast.Name) and ann.value.id == "Annotated"):
231+
return False
232+
if not isinstance(ann.slice, ast.Tuple):
224233
return False
225-
return _field_call_has_max_length(assign.value)
234+
return any(_field_call_has_max_length(elt) for elt in ann.slice.elts[1:])
226235

227236

228237
# ---------------------------------------------------------------------------

security/manage-baseline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ def cmd_report(args: argparse.Namespace) -> None:
340340

341341
open_findings = {
342342
fid: f for fid, f in data["findings"].items()
343-
if f["status"] not in ("fixed",)
343+
if f["status"] not in ("fixed", "accepted")
344344
}
345345

346346
sorted_findings = sorted(open_findings.items(), key=severity_sort_key)

0 commit comments

Comments
 (0)