{"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-fc7d8b3d02952404", "name": "Stray `console.log` in TS/JS \u2014 server.ts:32", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 server.ts:32"}, "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-d01fcfdc71666871", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/GameController.tsx:1341", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/GameController.tsx:1341"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e1d9550f43c7dd57", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/OpenWorld.tsx:782", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/OpenWorld.tsx:782"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1c8fb9463483c91a", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/MenuSelector.tsx:282", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/MenuSelector.tsx:282"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d3859e6245181d66", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/MenuSelector.tsx:105", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/MenuSelector.tsx:105"}, "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-cb70c1e3f6bdce03", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/PokemonCard.tsx:311", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PokemonCard.tsx:311"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4d6cd4e3515b1e1c", "name": "`truncate` class without `title=` for hover reveal \u2014 src/components/CareerMode.tsx:473", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/CareerMode.tsx:473"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e593fe5731c92489", "name": "Insecure pattern 'dangerous_innerhtml' in src/components/MenuSelector.tsx:105", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/MenuSelector.tsx:105"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). 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-c664253e088da81e", "name": "Very large file: src/components/GameController.tsx (1661 lines)", "shortDescription": {"text": "Very large file: src/components/GameController.tsx (1661 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9bc5171b39b09a37", "name": "Very large file: src/components/OpenWorld.tsx (904 lines)", "shortDescription": {"text": "Very large file: src/components/OpenWorld.tsx (904 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0ecef3e2dff76beb", "name": "Very large file: src/components/CareerMode.tsx (1073 lines)", "shortDescription": {"text": "Very large file: src/components/CareerMode.tsx (1073 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "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 15 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-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. 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}}]}}, "automationDetails": {"id": "repobility/25136"}, "properties": {"repository": "cryko98/pokemon", "repoUrl": "https://github.com/cryko98/pokemon", "branch": "main"}, "results": [{"ruleId": "scanner-fc7d8b3d02952404", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 server.ts:32"}, "properties": {"repobilityId": "63422c4893a0b074", "scanner": "scanner-primary", "fingerprint": "fc7d8b3d02952404", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-d01fcfdc71666871", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/GameController.tsx:1341"}, "properties": {"repobilityId": "503838a53643dba1", "scanner": "scanner-primary", "fingerprint": "d01fcfdc71666871", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e1d9550f43c7dd57", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/OpenWorld.tsx:782"}, "properties": {"repobilityId": "222ceddecb8af34c", "scanner": "scanner-primary", "fingerprint": "e1d9550f43c7dd57", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1c8fb9463483c91a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/MenuSelector.tsx:282"}, "properties": {"repobilityId": "bd05f3f1c65aff03", "scanner": "scanner-primary", "fingerprint": "1c8fb9463483c91a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d3859e6245181d66", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 src/components/MenuSelector.tsx:105"}, "properties": {"repobilityId": "fa3618249c607f3e", "scanner": "scanner-primary", "fingerprint": "d3859e6245181d66", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-cb70c1e3f6bdce03", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/PokemonCard.tsx:311"}, "properties": {"repobilityId": "51335580020d6bed", "scanner": "scanner-primary", "fingerprint": "cb70c1e3f6bdce03", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4d6cd4e3515b1e1c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 src/components/CareerMode.tsx:473"}, "properties": {"repobilityId": "a2bb8d03423032f4", "scanner": "scanner-primary", "fingerprint": "4d6cd4e3515b1e1c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e593fe5731c92489", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in src/components/MenuSelector.tsx:105"}, "properties": {"repobilityId": "cb61389cbfb11bc5", "scanner": "scanner-primary", "fingerprint": "e593fe5731c92489", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "src/components/MenuSelector.tsx"}, "region": {"startLine": 105}}}]}, {"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-c664253e088da81e", "level": "note", "message": {"text": "Very large file: src/components/GameController.tsx (1661 lines)"}, "properties": {"repobilityId": "8cc1addf476e4611", "scanner": "scanner-primary", "fingerprint": "c664253e088da81e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-9bc5171b39b09a37", "level": "note", "message": {"text": "Very large file: src/components/OpenWorld.tsx (904 lines)"}, "properties": {"repobilityId": "3cd65356d59f0a98", "scanner": "scanner-primary", "fingerprint": "9bc5171b39b09a37", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-0ecef3e2dff76beb", "level": "note", "message": {"text": "Very large file: src/components/CareerMode.tsx (1073 lines)"}, "properties": {"repobilityId": "8266806eb70a28ad", "scanner": "scanner-primary", "fingerprint": "0ecef3e2dff76beb", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"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": "06d769b207113c39", "scanner": "scanner-primary", "fingerprint": "141b30a41e03817b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["license", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "471d8d6025ea67c1", "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": "6a2ff16b734f09be", "scanner": "scanner-primary", "fingerprint": "b9088664ace7f748", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["production-readiness", "repo-hardening", "generated-repo-pattern"]}}]}]}