46 lines
2.7 KiB
JSON
46 lines
2.7 KiB
JSON
{
|
|
"feature_id": "F-143",
|
|
"agent": "security",
|
|
"stage": "security_gate",
|
|
"verdict": "APPROVED",
|
|
"summary": "F-143 introduces NO database read path and NO migration, so there is no SQL injection surface in the new code: validation/reporting routes hold no `pool`, no raw SQL, no template literals concatenating user input. Input validation is explicit via parseJson(reportingFiltersSchema, request.query ?? {}) — querystring values flow only through zod.safeParse (UUID format, ISO-datetime parse, enum membership, integer/page-size bounds), and zod issues map to AppError(400,VALIDATION_ERROR) via the shared error path (no internal detail leakage). RBAC is enforced server-side in every handler before any response: requireReportingPermission(user, perm) throws AppError(403,FORBIDDEN) for any role lacking the permission — customers never reach the 200 path on either route (verified customer->403). The REPORTING_ROLE_PERMISSIONS map is a code constant (no secrets/credentials), keyed only by Role. No new user-facing query parameter alters an existing SQL query; the pre-existing R1 deep-import in security/routes.ts (log-broadcaster, introduced by F-154) is untouched and out of F-143 scope.",
|
|
"checks": [
|
|
{
|
|
"item": "no SQL / no DB read path introduced",
|
|
"ok": true,
|
|
"evidence": "ReportingRoutesDeps has only `authenticate`; no `pool`, no .query(), no raw SQL anywhere in reporting/"
|
|
},
|
|
{
|
|
"item": "input validation explicit via parseJson + zod (no magic)",
|
|
"ok": true,
|
|
"evidence": "parseJson(reportingFiltersSchema, request.query ?? {}); zod UUID/ISO-datetime/enum/int bounds; filters.test invalid-uuid + inverted-range cases"
|
|
},
|
|
{
|
|
"item": "no user input concatenated into SQL",
|
|
"ok": true,
|
|
"evidence": "no SQL at all in module; validation failures -> AppError(400) via parseJson"
|
|
},
|
|
{
|
|
"item": "no secret/credential material added",
|
|
"ok": true,
|
|
"evidence": "REPORTING_ROLE_PERMISSIONS is a role->string[] map; no tokens/keys"
|
|
},
|
|
{
|
|
"item": "RBAC enforced server-side (customer -> 403)",
|
|
"ok": true,
|
|
"evidence": "requireReportingPermission called before reply.send on both routes; routes.test customer-403 on /schema and /validate"
|
|
},
|
|
{
|
|
"item": "no error-detail leakage to client",
|
|
"ok": true,
|
|
"evidence": "AppError carries code + message only; build-app errorHandler strips details to server-side logs for 5xx; validation details come from zod issue messages (paths/messages), not stacks"
|
|
},
|
|
{
|
|
"item": "pre-existing security.routes.ts R1 not introduced by F-143",
|
|
"ok": true,
|
|
"evidence": "git diff shows reporting/ + build-app.ts only; security/routes.ts untouched"
|
|
}
|
|
],
|
|
"issues": []
|
|
}
|