{"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": "CFG006", "name": "[CFG006] Missing .gitignore: No .gitignore file. Risk of committing secrets and build artifacts.", "shortDescription": {"text": "[CFG006] Missing .gitignore: No .gitignore file. Risk of committing secrets and build artifacts."}, "fullDescription": {"text": "Add a .gitignore appropriate for your language/framework."}, "properties": {"scanner": "repobility-threat-engine", "category": "practices", "severity": "medium", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "SEC046", "name": "[SEC046] Client-side open redirect \u2014 window.location = server-supplied URL: Assigning window.location from a server-supp", "shortDescription": {"text": "[SEC046] Client-side open redirect \u2014 window.location = server-supplied URL: Assigning window.location from a server-supplied URL trusts the server endpoint to never return a hostile destination. If that endpoint is ever subverted (compromis"}, "fullDescription": {"text": "Validate the URL is same-origin or on an explicit allowlist before assignment:\n  const u = new URL(serverUrl, location.href);\n  if (u.origin !== location.origin && !ALLOWED.includes(u.host)) return;\n  location.assign(u);\nEven better: have the server return a path (/checkout/done) instead of a full URL, and only allow same-origin navigation."}, "properties": {"scanner": "repobility-threat-engine", "category": "open_redirect", "severity": "medium", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "CORE_NO_CI", "name": "No CI/CD configuration found", "shortDescription": {"text": "No CI/CD configuration found"}, "fullDescription": {"text": "Add a CI/CD pipeline: create .github/workflows/ci.yml for GitHub Actions with steps to lint, test, and build on every push and pull request."}, "properties": {"scanner": "repobility-core", "category": "practices", "severity": "medium", "confidence": null, "cwe": "", "owasp": ""}}, {"id": "CORE_NO_README", "name": "No README file found", "shortDescription": {"text": "No README file found"}, "fullDescription": {"text": "Create a README.md with: project name and description, installation instructions, usage examples, configuration options, and contribution guidelines."}, "properties": {"scanner": "repobility-core", "category": "documentation", "severity": "medium", "confidence": null, "cwe": "", "owasp": ""}}, {"id": "AIC003", "name": "Duplicated implementation block across source files", "shortDescription": {"text": "Duplicated implementation block across source files"}, "fullDescription": {"text": "Duplicated blocks are a common artifact when generated code is pasted or recreated instead of reused. They increase maintenance cost because every future bug fix must be found in multiple locations."}, "properties": {"scanner": "repobility-ai-code-hygiene", "category": "quality", "severity": "low", "confidence": 0.86, "cwe": "", "owasp": ""}}, {"id": "CORE_NO_LICENSE", "name": "No LICENSE file", "shortDescription": {"text": "No LICENSE file"}, "fullDescription": {"text": "Add a LICENSE file to your repository. Use choosealicense.com to pick the right license (MIT for permissive, Apache 2.0 for patent protection, GPL for copyleft)."}, "properties": {"scanner": "repobility-core", "category": "documentation", "severity": "low", "confidence": null, "cwe": "", "owasp": ""}}, {"id": "MINED056", "name": "[MINED056] React Key As Index: key={index} in map() \u2014 re-renders the wrong elements on re-order.", "shortDescription": {"text": "[MINED056] React Key As Index: key={index} in map() \u2014 re-renders the wrong elements on re-order."}, "fullDescription": {"text": "Review and fix per the pattern semantics. See CWE-682 /  for context."}, "properties": {"scanner": "repobility-threat-engine", "category": "quality", "severity": "info", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "MINED058", "name": "[MINED058] React Dangerously Set Html: dangerouslySetInnerHTML bypasses Reacts JSX escaping. Pair with DOMPurify or neve", "shortDescription": {"text": "[MINED058] React Dangerously Set Html: dangerouslySetInnerHTML bypasses Reacts JSX escaping. Pair with DOMPurify or never use with user data."}, "fullDescription": {"text": "Review and fix per the pattern semantics. See CWE-79 / A03:2021 for context."}, "properties": {"scanner": "repobility-threat-engine", "category": "quality", "severity": "info", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "SEC029", "name": "[SEC029] Server-Side Request Forgery (SSRF) \u2014 outbound HTTP from user input: Outbound HTTP request to a user-controlled ", "shortDescription": {"text": "[SEC029] Server-Side Request Forgery (SSRF) \u2014 outbound HTTP from user input: Outbound HTTP request to a user-controlled URL without allowlist validation. Attackers can probe internal services (169.254.169.254 metadata, internal Kubernetes e"}, "fullDescription": {"text": "Validate the URL against an allowlist BEFORE fetching:\n  ALLOWED = {'images.example.com', 'cdn.example.com'}\n  host = urlparse(url).hostname\n  if host not in ALLOWED: abort(400)\nOr use a server-side proxy (Imgproxy / serve-files-only-from-S3) that isolates outbound network access from the request handler.\nBlock private CIDRs explicitly: 10/8, 172.16/12, 192.168/16, 169.254/16."}, "properties": {"scanner": "repobility-threat-engine", "category": "ssrf", "severity": "high", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "SEC128", "name": "[SEC128] Async function without await \u2014 fire-and-forget Promise (AI mistake): Async call invoked without `await` returns", "shortDescription": {"text": "[SEC128] Async function without await \u2014 fire-and-forget Promise (AI mistake): Async call invoked without `await` returns an unhandled Promise. The outer function resolves before the inner work completes \u2014 DB writes lost, emails not sent, ra"}, "fullDescription": {"text": "Add `await` before each async call, or chain with `.then`. If you intentionally want fire-and-forget, prefix with `void` (TS) or assign to `_` (Python with `asyncio.create_task`) to make the intent explicit and survive lint."}, "properties": {"scanner": "repobility-threat-engine", "category": "quality", "severity": "high", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "SEC040", "name": "[SEC040] innerHTML XSS \u2014 template literal with server-supplied data: Setting .innerHTML with a template literal that int", "shortDescription": {"text": "[SEC040] innerHTML XSS \u2014 template literal with server-supplied data: Setting .innerHTML with a template literal that interpolates server-supplied or user-supplied data is the canonical stored/reflected XSS vector. The browser parses the HTM"}, "fullDescription": {"text": "For plain text: use el.textContent = data.value (auto-escapes).\nFor HTML you need to render: el.innerHTML = DOMPurify.sanitize(html).\nFor React/Vue/Svelte: stop using innerHTML; use the framework's binding.\nWhen data comes from CV/PDF parsers, sanitize at the parser boundary too."}, "properties": {"scanner": "repobility-threat-engine", "category": "xss", "severity": "high", "confidence": 1.0, "cwe": "", "owasp": ""}}, {"id": "CORE_NO_TESTS", "name": "No test files found", "shortDescription": {"text": "No test files found"}, "fullDescription": {"text": "Add a test directory (tests/ or __tests__/) with unit tests for core functionality. Use pytest (Python), Jest (JS/TS), or go test (Go). Start with tests for critical business logic and security-sensitive functions."}, "properties": {"scanner": "repobility-core", "category": "testing", "severity": "high", "confidence": null, "cwe": "", "owasp": ""}}]}}, "automationDetails": {"id": "repobility/581"}, "properties": {"repository": "ermatteo/FC_nails", "repoUrl": "https://github.com/ermatteo/FC_nails.git", "branch": "main"}, "results": [{"ruleId": "CFG006", "level": "warning", "message": {"text": "[CFG006] Missing .gitignore: No .gitignore file. Risk of committing secrets and build artifacts."}, "properties": {"repobilityId": 42789, "scanner": "repobility-threat-engine", "fingerprint": "c65fc71ce58c37a0e07837c0fe294108b731c43ef16027a2f0971c757bbe9a16", "category": "practices", "severity": "medium", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "No .gitignore file found in repository root", "evidence": {"reason": "No .gitignore file found in repository root", "rule_id": "CFG006", "scanner": "repobility-threat-engine", "confidence": 1.0, "correlation_key": "repo|practices|cfg006"}}}, {"ruleId": "SEC046", "level": "warning", "message": {"text": "[SEC046] Client-side open redirect \u2014 window.location = server-supplied URL: Assigning window.location from a server-supplied URL trusts the server endpoint to never return a hostile destination. If that endpoint is ever subverted (compromised admin, JSON injection, MITM on a webhook), users get redirected to a phishing site they trust because the original page is yours. CWE-601 (server-side OR client-side). Complement to server-side SEC030."}, "properties": {"repobilityId": 42784, "scanner": "repobility-threat-engine", "fingerprint": "433d41848b6fc099c96bc043118c530fa0f408a5aa0040f608cbc73813f78663", "category": "open_redirect", "severity": "medium", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"match": "location.href = createPageUrl", "reason": "Pattern matched with no mitigating context found", "rule_id": "SEC046", "scanner": "repobility-threat-engine", "confidence": 1.0, "correlation_key": "fp|433d41848b6fc099c96bc043118c530fa0f408a5aa0040f608cbc73813f78663"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/ClientDetail.jsx"}, "region": {"startLine": 64}}}]}, {"ruleId": "CORE_NO_CI", "level": "warning", "message": {"text": "No CI/CD configuration found"}, "properties": {"repobilityId": 42773, "scanner": "repobility-core", "fingerprint": "ca5da3551af97272c4f099fc472740148135a15816b81b90bd862e8f91ec66ce", "category": "practices", "severity": "medium", "confidence": null, "triageState": "open", "verdict": "", "isResolved": false, "reason": "", "evidence": {"rule_id": "CORE_NO_CI", "scanner": "repobility-core", "correlation_key": "repo|practices|core_no_ci"}}}, {"ruleId": "CORE_NO_README", "level": "warning", "message": {"text": "No README file found"}, "properties": {"repobilityId": 42771, "scanner": "repobility-core", "fingerprint": "b55c73163757fe6b2364bb829fcd26e87b9d9e7b367dd2a3307a814b02b29cbd", "category": "documentation", "severity": "medium", "confidence": null, "triageState": "open", "verdict": "", "isResolved": false, "reason": "", "evidence": {"rule_id": "CORE_NO_README", "scanner": "repobility-core", "correlation_key": "repo|documentation|core_no_readme"}}}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42780, "scanner": "repobility-ai-code-hygiene", "fingerprint": "fbbb9881dce69505c68062625a8ceb291b911cb5267a7bb0a730c7a6351886dd", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/pages/Accounting.jsx", "duplicate_line": 430, "correlation_key": "fp|fbbb9881dce69505c68062625a8ceb291b911cb5267a7bb0a730c7a6351886dd"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Treatments.jsx"}, "region": {"startLine": 391}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42779, "scanner": "repobility-ai-code-hygiene", "fingerprint": "c6d35da5039d402267057fd5049f1d8cd6795e590f5d6c284876b1868c3dbafd", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/pages/Accounting.jsx", "duplicate_line": 134, "correlation_key": "fp|c6d35da5039d402267057fd5049f1d8cd6795e590f5d6c284876b1868c3dbafd"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Statistics.jsx"}, "region": {"startLine": 59}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42778, "scanner": "repobility-ai-code-hygiene", "fingerprint": "a2fd5e7d2b025b808f7263505d60c156bdbd68f247606c5140c77b11eba4ceb1", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/pages/Accounting.jsx", "duplicate_line": 779, "correlation_key": "fp|a2fd5e7d2b025b808f7263505d60c156bdbd68f247606c5140c77b11eba4ceb1"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Inventory.jsx"}, "region": {"startLine": 358}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42777, "scanner": "repobility-ai-code-hygiene", "fingerprint": "ea7909d8bab83867a8eed9fc6d59bf259bb8015e17a38ca7a7d8d13d64fb2b78", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/components/accounting/ExpenseFormDialog.jsx", "duplicate_line": 143, "correlation_key": "fp|ea7909d8bab83867a8eed9fc6d59bf259bb8015e17a38ca7a7d8d13d64fb2b78"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/treatments/TreatmentFormDialog.jsx"}, "region": {"startLine": 493}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42776, "scanner": "repobility-ai-code-hygiene", "fingerprint": "713279d315e374d23f2722dbe4cbe41f557617fd443895ed3709190dc4ad5108", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/components/accounting/ExpenseFormDialog.jsx", "duplicate_line": 190, "correlation_key": "fp|713279d315e374d23f2722dbe4cbe41f557617fd443895ed3709190dc4ad5108"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/inventory/ProductFormDialog.jsx"}, "region": {"startLine": 228}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42775, "scanner": "repobility-ai-code-hygiene", "fingerprint": "a52fbe7787b6905fb3dccbed013bb508ffc2c7e60568e71c0a162f938c588f61", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/components/clients/ClientFormDialog.jsx", "duplicate_line": 144, "correlation_key": "fp|a52fbe7787b6905fb3dccbed013bb508ffc2c7e60568e71c0a162f938c588f61"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/inventory/ProductFormDialog.jsx"}, "region": {"startLine": 227}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 42774, "scanner": "repobility-ai-code-hygiene", "fingerprint": "4260d5f52d777f8cd5a0b7456492968c3218943609dffd90796852ed7c0f2d38", "category": "quality", "severity": "low", "confidence": 0.86, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "A normalized source-code window appears in two different non-test files.", "evidence": {"lines": 12, "rule_id": "AIC003", "scanner": "repobility-ai-code-hygiene", "references": ["https://jscpd.dev/"], "duplicate_file": "frontend/src/components/accounting/ExpenseFormDialog.jsx", "duplicate_line": 190, "correlation_key": "fp|4260d5f52d777f8cd5a0b7456492968c3218943609dffd90796852ed7c0f2d38"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/clients/ClientFormDialog.jsx"}, "region": {"startLine": 145}}}]}, {"ruleId": "CORE_NO_LICENSE", "level": "note", "message": {"text": "No LICENSE file"}, "properties": {"repobilityId": 42772, "scanner": "repobility-core", "fingerprint": "9314e9238cd99885865b92490d1aaa96ca62b1390c9377878d5f3d99227e1c3c", "category": "documentation", "severity": "low", "confidence": null, "triageState": "open", "verdict": "", "isResolved": false, "reason": "", "evidence": {"rule_id": "CORE_NO_LICENSE", "scanner": "repobility-core", "correlation_key": "repo|documentation|core_no_license"}}}, {"ruleId": "MINED056", "level": "none", "message": {"text": "[MINED056] React Key As Index: key={index} in map() \u2014 re-renders the wrong elements on re-order."}, "properties": {"repobilityId": 42787, "scanner": "repobility-threat-engine", "fingerprint": "2b14b95e1ff94a011c8fb225a394300512a59e3bc6d4c92db338e6a9bd1b4783", "category": "quality", "severity": "info", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"mined": true, "mining": {"slug": "react-key-as-index", "owasp": null, "cwe_ids": ["CWE-682"], "languages": ["typescript", "tsx", "javascript", "jsx"], "precision": 1.0, "promoted_at": "2026-05-18T14:01:32.348032+00:00", "triaged_in_corpus": 12, "observations_count": 299917, "ai_coder_pattern_id": 135}, "scanner": "repobility-threat-engine", "correlation_key": "fp|2b14b95e1ff94a011c8fb225a394300512a59e3bc6d4c92db338e6a9bd1b4783"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Dashboard.jsx"}, "region": {"startLine": 114}}}]}, {"ruleId": "MINED056", "level": "none", "message": {"text": "[MINED056] React Key As Index: key={index} in map() \u2014 re-renders the wrong elements on re-order."}, "properties": {"repobilityId": 42786, "scanner": "repobility-threat-engine", "fingerprint": "394bc396ffe6db5e1c7ff32ed750a1cd6a6bd333066525e793e1e9c72088e81a", "category": "quality", "severity": "info", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"mined": true, "mining": {"slug": "react-key-as-index", "owasp": null, "cwe_ids": ["CWE-682"], "languages": ["typescript", "tsx", "javascript", "jsx"], "precision": 1.0, "promoted_at": "2026-05-18T14:01:32.348032+00:00", "triaged_in_corpus": 12, "observations_count": 299917, "ai_coder_pattern_id": 135}, "scanner": "repobility-threat-engine", "correlation_key": "fp|394bc396ffe6db5e1c7ff32ed750a1cd6a6bd333066525e793e1e9c72088e81a"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Clients.jsx"}, "region": {"startLine": 77}}}]}, {"ruleId": "MINED056", "level": "none", "message": {"text": "[MINED056] React Key As Index: key={index} in map() \u2014 re-renders the wrong elements on re-order."}, "properties": {"repobilityId": 42785, "scanner": "repobility-threat-engine", "fingerprint": "1076aed550c3341e1b01efb79a9de846b6d5d7b50db0ba2df7320de36be8adc3", "category": "quality", "severity": "info", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"mined": true, "mining": {"slug": "react-key-as-index", "owasp": null, "cwe_ids": ["CWE-682"], "languages": ["typescript", "tsx", "javascript", "jsx"], "precision": 1.0, "promoted_at": "2026-05-18T14:01:32.348032+00:00", "triaged_in_corpus": 12, "observations_count": 299917, "ai_coder_pattern_id": 135}, "scanner": "repobility-threat-engine", "correlation_key": "fp|1076aed550c3341e1b01efb79a9de846b6d5d7b50db0ba2df7320de36be8adc3"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/ClientDetail.jsx"}, "region": {"startLine": 265}}}]}, {"ruleId": "MINED058", "level": "none", "message": {"text": "[MINED058] React Dangerously Set Html: dangerouslySetInnerHTML bypasses Reacts JSX escaping. Pair with DOMPurify or never use with user data."}, "properties": {"repobilityId": 42782, "scanner": "repobility-threat-engine", "fingerprint": "4d8d9cab55eaaa3a9c1dda1ff0f26a6d9c7c3b7bc1c7107510b2290f0afd024e", "category": "quality", "severity": "info", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"mined": true, "mining": {"slug": "react-dangerously-set-html", "owasp": "A03:2021", "cwe_ids": ["CWE-79"], "languages": ["javascript", "typescript"], "precision": 1.0, "promoted_at": "2026-05-18T14:01:32.348037+00:00", "triaged_in_corpus": 12, "observations_count": 255650, "ai_coder_pattern_id": 49}, "scanner": "repobility-threat-engine", "correlation_key": "fp|4d8d9cab55eaaa3a9c1dda1ff0f26a6d9c7c3b7bc1c7107510b2290f0afd024e"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/ui/chart.jsx"}, "region": {"startLine": 61}}}]}, {"ruleId": "SEC029", "level": "error", "message": {"text": "[SEC029] Server-Side Request Forgery (SSRF) \u2014 outbound HTTP from user input: Outbound HTTP request to a user-controlled URL without allowlist validation. Attackers can probe internal services (169.254.169.254 metadata, internal Kubernetes endpoints, file:// URIs), exfiltrate data, or pivot through your network. SSRF is OWASP A10:2021 and a frequent foothold in cloud breaches."}, "properties": {"repobilityId": 42788, "scanner": "repobility-threat-engine", "fingerprint": "c52aae9357f57d7c7625a07261882b8d482be73de2cdb70c6ede0169b7e8e323", "category": "ssrf", "severity": "high", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"match": "Url(p", "reason": "Pattern matched with no mitigating context found", "rule_id": "SEC029", "scanner": "repobility-threat-engine", "confidence": 1.0, "correlation_key": "fp|c52aae9357f57d7c7625a07261882b8d482be73de2cdb70c6ede0169b7e8e323"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/utils/index.ts"}, "region": {"startLine": 1}}}]}, {"ruleId": "SEC128", "level": "error", "message": {"text": "[SEC128] Async function without await \u2014 fire-and-forget Promise (AI mistake): Async call invoked without `await` returns an unhandled Promise. The outer function resolves before the inner work completes \u2014 DB writes lost, emails not sent, race conditions. This is one of the top-3 errors AI coders make: they understand async-shape but drop the await keyword when chaining multiple ops. Surfaces as flaky tests or silently dropped data in production."}, "properties": {"repobilityId": 42783, "scanner": "repobility-threat-engine", "fingerprint": "8fe524c8137b752d6ea9d6391cfe6da05d73edfa48744b0b118f5f0201631253", "category": "quality", "severity": "high", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"match": "toastTimeouts.delete(toastId);", "reason": "Pattern matched with no mitigating context found", "rule_id": "SEC128", "scanner": "repobility-threat-engine", "confidence": 1.0, "correlation_key": "fp|8fe524c8137b752d6ea9d6391cfe6da05d73edfa48744b0b118f5f0201631253"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/ui/use-toast.jsx"}, "region": {"startLine": 29}}}]}, {"ruleId": "SEC040", "level": "error", "message": {"text": "[SEC040] innerHTML XSS \u2014 template literal with server-supplied data: Setting .innerHTML with a template literal that interpolates server-supplied or user-supplied data is the canonical stored/reflected XSS vector. The browser parses the HTML and executes any <script> or event-handler attributes in the data. CWE-79. Especially dangerous when the data comes from a CV parser, profile field, or any user-input pipeline."}, "properties": {"repobilityId": 42781, "scanner": "repobility-threat-engine", "fingerprint": "f330d127406fc2536b6236abbd7d13e3e6f615795e4126c8d5eca97b1318ec37", "category": "xss", "severity": "high", "confidence": 1.0, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Pattern matched with no mitigating context found", "evidence": {"match": "map(([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n.map(([key, itemConfig]) =>", "reason": "Pattern matched with no mitigating context found", "rule_id": "SEC040", "scanner": "repobility-threat-engine", "confidence": 1.0, "correlation_key": "fp|f330d127406fc2536b6236abbd7d13e3e6f615795e4126c8d5eca97b1318ec37"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/ui/chart.jsx"}, "region": {"startLine": 63}}}]}, {"ruleId": "CORE_NO_TESTS", "level": "error", "message": {"text": "No test files found"}, "properties": {"repobilityId": 42770, "scanner": "repobility-core", "fingerprint": "0200e9918bc2a7bf9c116d0907e50ac3df640c758b93852cf1890ec6e14d870d", "category": "testing", "severity": "high", "confidence": null, "triageState": "open", "verdict": "", "isResolved": false, "reason": "", "evidence": {"rule_id": "CORE_NO_TESTS", "scanner": "repobility-core", "correlation_key": "repo|testing|core_no_tests"}}}]}]}