{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-a93ca710fdb5ec29", "name": "Stray `console.log` in TS/JS \u2014 backend/check_br5.js:11", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/check_br5.js:11"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9185865a0d23c944", "name": "Stray `console.log` in TS/JS \u2014 backend/src/index.js:16", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/src/index.js:16"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-421892a268baf970", "name": "Stray `console.log` in TS/JS \u2014 backend/src/parsers/productivity.js:79", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/src/parsers/productivity.js:79"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-488eb211ee39623d", "name": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-m9PGaA-_.js:212", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-m9PGaA-_.js:212"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b4dc95b8ab8c4bd2", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-m9PGaA-_.js:33", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-m9PGaA-_.js:33"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-26d8468306837435", "name": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-Bc2snuRD.js:212", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-Bc2snuRD.js:212"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-930106f837390116", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-Bc2snuRD.js:33", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-Bc2snuRD.js:33"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b6246796427f3475", "name": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-BIaLuTjl.js:212", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-BIaLuTjl.js:212"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7b85724ef723d9e1", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-BIaLuTjl.js:33", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-BIaLuTjl.js:33"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1f66ad88286ca30a", "name": "Dockerfile runs as root: backend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3d2a6283f9ebab24", "name": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-60427b03771411b6", "name": "Dockerfile runs as root: frontend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: frontend/Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b048d166901fd868", "name": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-634b1ea2aa2ae306", "name": "Insecure pattern 'cors_wildcard' in backend/src/index.js:5", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in backend/src/index.js:5"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-17a46a67c85594f8", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-m9PGaA-_.js:37", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-m9PGaA-_.js:37"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-596b12c65be39865", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-Bc2snuRD.js:37", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-Bc2snuRD.js:37"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e808fe1148cc2704", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-BIaLuTjl.js:37", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-BIaLuTjl.js:37"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6893a6c8b0861585", "name": "Very low test-to-source ratio", "shortDescription": {"text": "Very low test-to-source ratio"}, "fullDescription": {"text": "0 test file(s) for 32 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-141b30a41e03817b", "name": "No license file detected", "shortDescription": {"text": "No license file detected"}, "fullDescription": {"text": "No LICENSE/COPYING/NOTICE file was found. Generated repositories often omit licensing, which blocks reuse and automated intake."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-faccb9061e9b52a0", "name": "No README detected", "shortDescription": {"text": "No README detected"}, "fullDescription": {"text": "No README file was found. Generated repos without README context are hard to operate, validate, or safely hand off."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3a092b5c39e242a1", "name": "Node manifest has dependencies but no lockfile: backend/package.json", "shortDescription": {"text": "Node manifest has dependencies but no lockfile: backend/package.json"}, "fullDescription": {"text": "`package.json` declares dependencies, but no same-directory npm/pnpm/yarn/bun lockfile was found. Generated projects without lockfiles are less reproducible and harder to secure-scan precisely."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b9088664ace7f748", "name": "Composite production-readiness gap", "shortDescription": {"text": "Composite production-readiness gap"}, "fullDescription": {"text": "Multiple low-cost hardening controls are missing together: license, ci, tests, operator-readme, lockfile. Opus verification showed these co-occurring gaps are a better readiness signal than reading each flag in isolation."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-43a7ee742a3b038d", "name": "Commented-code block (6 lines) in backend/src/routes/quality.js:12", "shortDescription": {"text": "Commented-code block (6 lines) in backend/src/routes/quality.js:12"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-28352b25284fa092", "name": "Legacy-named symbol `quality_legacy` in backend/src/routes/upload.js:87", "shortDescription": {"text": "Legacy-named symbol `quality_legacy` in backend/src/routes/upload.js:87"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b5e36a66ecc4503b", "name": "Legacy-named symbol `quality_legacy` in frontend/src/screens/UploadPage.jsx:190", "shortDescription": {"text": "Legacy-named symbol `quality_legacy` in frontend/src/screens/UploadPage.jsx:190"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cc880cdd8c12cba6", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-m9PGaA-_.js:1", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-m9PGaA-_.js:1"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-8f840dce5c3624f8", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-Bc2snuRD.js:1", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-Bc2snuRD.js:1"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c591959bc3230aa4", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-BIaLuTjl.js:1", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-BIaLuTjl.js:1"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1b5a76780c3df9aa", "name": "1 env vars used in code but missing from .env.example", "shortDescription": {"text": "1 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `BASE_URL`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bac314f2eed583e6", "name": "JS POST `/admin/quotas` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:226", "shortDescription": {"text": "JS POST `/admin/quotas` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:226"}, "fullDescription": {"text": "Admin-scoped JS route with no recognizable auth: no middleware-position guard, no router-level guard above it in this file, and no inline permission call within the first 15 lines of the handler. If auth is applied where this router is mounted, dismiss with reason `by_design` or tag the route `// public-by-design`."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-7676234d8712b126", "name": "JS DELETE `/admin/quotas/${id}` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:238", "shortDescription": {"text": "JS DELETE `/admin/quotas/${id}` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:238"}, "fullDescription": {"text": "Admin-scoped JS route with no recognizable auth: no middleware-position guard, no router-level guard above it in this file, and no inline permission call within the first 15 lines of the handler. If auth is applied where this router is mounted, dismiss with reason `by_design` or tag the route `// public-by-design`."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/25192"}, "properties": {"repository": "Daividdi/shiftsync-bi", "repoUrl": "https://github.com/Daividdi/shiftsync-bi", "branch": "main"}, "results": [{"ruleId": "scanner-a93ca710fdb5ec29", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/check_br5.js:11"}, "properties": {"repobilityId": "d62cd9b725c07402", "scanner": "scanner-primary", "fingerprint": "a93ca710fdb5ec29", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-9185865a0d23c944", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/src/index.js:16"}, "properties": {"repobilityId": "03d5d680343d7d14", "scanner": "scanner-primary", "fingerprint": "9185865a0d23c944", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-421892a268baf970", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/src/parsers/productivity.js:79"}, "properties": {"repobilityId": "62260a0f8f887cda", "scanner": "scanner-primary", "fingerprint": "421892a268baf970", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-488eb211ee39623d", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-m9PGaA-_.js:212"}, "properties": {"repobilityId": "24655ea529a66748", "scanner": "scanner-primary", "fingerprint": "488eb211ee39623d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-b4dc95b8ab8c4bd2", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-m9PGaA-_.js:33"}, "properties": {"repobilityId": "e9b59a376ecf32ae", "scanner": "scanner-primary", "fingerprint": "b4dc95b8ab8c4bd2", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-26d8468306837435", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-Bc2snuRD.js:212"}, "properties": {"repobilityId": "f2e6bd259f20cffb", "scanner": "scanner-primary", "fingerprint": "26d8468306837435", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-930106f837390116", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-Bc2snuRD.js:33"}, "properties": {"repobilityId": "e88e1810e9f3e6ee", "scanner": "scanner-primary", "fingerprint": "930106f837390116", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-b6246796427f3475", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend-dist/assets/index-BIaLuTjl.js:212"}, "properties": {"repobilityId": "7a0214f0d521e49c", "scanner": "scanner-primary", "fingerprint": "b6246796427f3475", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7b85724ef723d9e1", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend-dist/assets/index-BIaLuTjl.js:33"}, "properties": {"repobilityId": "66ffe986ddaf6478", "scanner": "scanner-primary", "fingerprint": "7b85724ef723d9e1", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-1f66ad88286ca30a", "level": "warning", "message": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "properties": {"repobilityId": "7afd2b0e8a8c9eeb", "scanner": "scanner-primary", "fingerprint": "1f66ad88286ca30a", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-3d2a6283f9ebab24", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:20-alpine"}, "properties": {"repobilityId": "e866ff9772e76d62", "scanner": "scanner-primary", "fingerprint": "3d2a6283f9ebab24", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-60427b03771411b6", "level": "warning", "message": {"text": "Dockerfile runs as root: frontend/Dockerfile"}, "properties": {"repobilityId": "735c01d8531dfd2c", "scanner": "scanner-primary", "fingerprint": "60427b03771411b6", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-b048d166901fd868", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: nginx:alpine"}, "properties": {"repobilityId": "42eb610cbdd1d922", "scanner": "scanner-primary", "fingerprint": "b048d166901fd868", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-634b1ea2aa2ae306", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in backend/src/index.js:5"}, "properties": {"repobilityId": "6dc1d23eac019019", "scanner": "scanner-primary", "fingerprint": "634b1ea2aa2ae306", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/src/index.js"}, "region": {"startLine": 5}}}]}, {"ruleId": "scanner-17a46a67c85594f8", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-m9PGaA-_.js:37"}, "properties": {"repobilityId": "cc95ebffd1dca5a9", "scanner": "scanner-primary", "fingerprint": "17a46a67c85594f8", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend-dist/assets/index-m9PGaA-_.js"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-596b12c65be39865", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-Bc2snuRD.js:37"}, "properties": {"repobilityId": "6affc13b320fe28b", "scanner": "scanner-primary", "fingerprint": "596b12c65be39865", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend-dist/assets/index-Bc2snuRD.js"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-e808fe1148cc2704", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend-dist/assets/index-BIaLuTjl.js:37"}, "properties": {"repobilityId": "056a2d737d49c87a", "scanner": "scanner-primary", "fingerprint": "e808fe1148cc2704", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend-dist/assets/index-BIaLuTjl.js"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-6893a6c8b0861585", "level": "warning", "message": {"text": "Very low test-to-source ratio"}, "properties": {"repobilityId": "54a7de3f06314bf0", "scanner": "scanner-primary", "fingerprint": "6893a6c8b0861585", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["tests", "coverage"]}}, {"ruleId": "scanner-141b30a41e03817b", "level": "note", "message": {"text": "No license file detected"}, "properties": {"repobilityId": "83862ad70c131cda", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-faccb9061e9b52a0", "level": "note", "message": {"text": "No README detected"}, "properties": {"repobilityId": "70083f2c25a73c47", "scanner": "scanner-primary", "fingerprint": "faccb9061e9b52a0", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["docs", "readme", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-3a092b5c39e242a1", "level": "note", "message": {"text": "Node manifest has dependencies but no lockfile: backend/package.json"}, "properties": {"repobilityId": "fc853e57ce7048c4", "scanner": "scanner-primary", "fingerprint": "3a092b5c39e242a1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["dependency", "lockfile", "reproducibility", "generated-repo-pattern"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/package.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "466a9f38b65e4f30", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-b9088664ace7f748", "level": "warning", "message": {"text": "Composite production-readiness gap"}, "properties": {"repobilityId": "8baa38d8d6b22713", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-43a7ee742a3b038d", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/src/routes/quality.js:12"}, "properties": {"repobilityId": "bed2af5a8404e1cb", "scanner": "scanner-primary", "fingerprint": "43a7ee742a3b038d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-28352b25284fa092", "level": "note", "message": {"text": "Legacy-named symbol `quality_legacy` in backend/src/routes/upload.js:87"}, "properties": {"repobilityId": "3675534c39564da8", "scanner": "scanner-primary", "fingerprint": "28352b25284fa092", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-b5e36a66ecc4503b", "level": "note", "message": {"text": "Legacy-named symbol `quality_legacy` in frontend/src/screens/UploadPage.jsx:190"}, "properties": {"repobilityId": "33850713ea5a0e79", "scanner": "scanner-primary", "fingerprint": "b5e36a66ecc4503b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-cc880cdd8c12cba6", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-m9PGaA-_.js:1"}, "properties": {"repobilityId": "117f7b694344842e", "scanner": "scanner-primary", "fingerprint": "cc880cdd8c12cba6", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-8f840dce5c3624f8", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-Bc2snuRD.js:1"}, "properties": {"repobilityId": "da27ff68677a3a19", "scanner": "scanner-primary", "fingerprint": "8f840dce5c3624f8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c591959bc3230aa4", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend-dist/assets/index-BIaLuTjl.js:1"}, "properties": {"repobilityId": "3eb90ca61a391c5b", "scanner": "scanner-primary", "fingerprint": "c591959bc3230aa4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-1b5a76780c3df9aa", "level": "none", "message": {"text": "1 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "d04379b337b44a15", "scanner": "scanner-primary", "fingerprint": "1b5a76780c3df9aa", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-bac314f2eed583e6", "level": "error", "message": {"text": "JS POST `/admin/quotas` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:226"}, "properties": {"repobilityId": "34633555545254c8", "scanner": "scanner-primary", "fingerprint": "bac314f2eed583e6", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.js.admin_unauth"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/screens/QuotaAdminScreen.jsx"}, "region": {"startLine": 226}}}]}, {"ruleId": "scanner-7676234d8712b126", "level": "error", "message": {"text": "JS DELETE `/admin/quotas/${id}` admin endpoint without auth \u2014 frontend/src/screens/QuotaAdminScreen.jsx:238"}, "properties": {"repobilityId": "cdb87f4931495727", "scanner": "scanner-primary", "fingerprint": "7676234d8712b126", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["auth", "owasp", "auth.js.admin_unauth"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/screens/QuotaAdminScreen.jsx"}, "region": {"startLine": 238}}}]}]}]}