{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-5+qual-2+sec-2","generated_at":"2026-11-14T14:52:05.046094Z","repo":{"ref":{"host":"github.com","owner":"hemadri-labs","name":"sonic-route-checker"},"default_branch":"main","clone_url":"https://github.com/hemadri-labs/sonic-route-checker.git","html_url":"https://github.com/hemadri-labs/sonic-route-checker","description":"SONiC Route Consistency Checker + AI Agent","stars":2,"forks":0,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":350,"primary_language":"Python","license_spdx":null,"created_at":"2026-03-26T03:42:01Z","pushed_at":"2026-03-30T04:46:50Z","security_policy_url":null,"distribution":{"owner_created_at":"2012-08-17T16:48:54Z","owner_type":"User","release_assets":[]}},"commit_sha":"cbefa90c2492f6e179821deb77ac752469710c9c","profile":{"lines_by_language":{"Python":3367,"Shell":164},"files_by_category":{"source":12,"docs":3,"test":2,"binary":1,"other":1,"config":1},"source_lines":2941,"test_lines":590},"pillars":{"ai_provenance":{"score":0.0,"confidence":0.41,"coverage":1.0,"label":"possible","breakdown":{"attributed_share":0.0,"suspected_share":0.0,"estimated_share":0.0,"ai_artifacts":1.0,"flagged_work_units":0.0,"flagged_releases":null,"style_index":2.55},"summary":"Weak signals consistent with AI-assisted development. Comments and strings use phrasing typical of LLM-written code (see the coding style evidence)."},"quality":{"score":59.8,"confidence":0.9,"coverage":1.0,"label":"weak","breakdown":{"complexity":72.8,"duplication":85.4,"lint":69.7,"testing":40.0,"docs":40.0,"type_safety":40.0,"process":null},"summary":"Code quality is weak: test-to-source ratio 0.20, no CI test run detected; 11% of function code in complex or long functions; 3% duplicated lines. Weakest area: testing."},"security":{"score":62.1,"confidence":0.85,"coverage":1.0,"label":"weak","breakdown":{"secrets":100.0,"sast":54.5,"dependencies":43.5,"ci_actions":null,"posture":20.0,"scorecard":null},"summary":"Security posture is weak: 21 known vulnerabilities in 7 dependencies; 4 high-severity SAST findings. Weakest area: posture."}},"analyzer_results":[{"analyzer":"sec-scorecard","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":"no published OpenSSF Scorecard result for this repo"},{"analyzer":"sec-registry","pillar":"security","status":"ok","tool_version":null,"metrics":{"declared":14.0,"checked":14.0,"missing":0.0,"recent":0.0,"lookup_errors":0.0},"findings":[],"evidence":[],"data":{"phantom":false},"error":null},{"analyzer":"ai-attribution","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"commits":4.0,"attributed_commits":0.0,"attributed_commit_share":0.0,"effective_loc":3588.0,"attributed_loc":0.0,"attributed_loc_share":0.0,"tools_detected":0.0},"findings":[],"evidence":[],"data":{"attributed_loc_by_commit":{},"tools":{},"monthly":{"2026-03":{"loc":3588,"attributed_loc":0}}},"error":null},{"analyzer":"ai-artifacts","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"artifacts":1.0,"workflow_agents":0.0,"tools_configured":1.0,"earliest_adoption":1774496663.0},"findings":[],"evidence":[{"kind":"ai-artifact","description":"CLAUDE.md (claude-code configuration)","ref":"CLAUDE.md","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/CLAUDE.md","weight":0.5}],"data":{"artifacts":[{"tool":"claude-code","path":"CLAUDE.md","added_at":1774496663}],"workflows":[],"tools":["claude-code"]},"error":null},{"analyzer":"ai-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"work_units":1.0,"flagged_units":0.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":0.0,"pre_ai_era_burst_loc":0.0,"measured_loc":443.0,"flagged_loc":0.0,"flagged_loc_share":0.0,"max_loc_per_hour":110.75,"median_loc_per_hour":110.75,"pr_timed_units":0.0,"excluded_import_loc":3145.0},"findings":[],"evidence":[],"data":{"flagged_loc_by_commit":{},"excluded_import_commits":["83e19bc5d07f43c8e71cc376644271d5ab947b58"]},"error":null},{"analyzer":"ai-release-velocity","pillar":"ai_provenance","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"ai-stylometry","pillar":"ai_provenance","status":"ok","tool_version":null,"metrics":{"lines_scanned":2941.0,"index":2.55,"count:narrated_steps":0.0,"per_kloc:narrated_steps":0.0,"files:narrated_steps":0.0,"count:placeholder":2.0,"per_kloc:placeholder":0.68,"files:placeholder":2.0,"count:emoji_in_code":7.0,"per_kloc:emoji_in_code":2.38,"files:emoji_in_code":1.0,"count:assistant_voice":0.0,"per_kloc:assistant_voice":0.0,"files:assistant_voice":0.0},"findings":[],"evidence":[{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: Inject a fault scenario into the running SONiC environment for demo purposes.","ref":"agent/mcp_server.py:205","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/agent/mcp_server.py#L205","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: #     Inject a fault scenario into the running SONiC environment for demo purposes.","ref":"agent/tools.py:249","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/agent/tools.py#L249","weight":0.0}],"data":{},"error":null},{"analyzer":"sec-secrets","pillar":"security","status":"ok","tool_version":"gitleaks 8.30.1","metrics":{"secrets_current":0.0,"secrets_history":0.0,"secrets_nonprod":0.0,"secrets_low_confidence":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-sast","pillar":"security","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":4.0,"findings_high":4.0,"findings_medium":0.0,"findings_low":0.0,"weighted_findings":5.1,"scanned_lines":2941.0,"parse_errors":0.0},"findings":[{"rule_id":"opengrep/python.lang.security.audit.dangerous-subprocess-use-audit","severity":"high","message":"Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. [confidence low]","path":"agent/tools.py","line":50,"fingerprint":"python.lang.security.audit.dangerous-subprocess-use-audit:agent/tools.py:50"},{"rule_id":"opengrep/python.lang.security.audit.subprocess-shell-true","severity":"high","message":"Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn the command using a shell process. Doing so propagates current shell settings and variables, which makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead. [confidence medium]","path":"agent/tools.py","line":51,"fingerprint":"python.lang.security.audit.subprocess-shell-true:agent/tools.py:51"},{"rule_id":"opengrep/python.lang.security.audit.dangerous-subprocess-use-audit","severity":"high","message":"Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. [confidence low]","path":"checker/collector.py","line":266,"fingerprint":"python.lang.security.audit.dangerous-subprocess-use-audit:checker/collector.py:266"},{"rule_id":"opengrep/python.lang.security.audit.subprocess-shell-true","severity":"high","message":"Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn the command using a shell process. Doing so propagates current shell settings and variables, which makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead. [confidence medium]","path":"checker/collector.py","line":266,"fingerprint":"python.lang.security.audit.subprocess-shell-true:checker/collector.py:266"}],"evidence":[],"data":{"rulesets":["python","bash"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"ok","tool_version":"osv-scanner version: 2.7.1","metrics":{"vulnerable_packages":7.0,"vulnerabilities":21.0,"vulns_critical":2.0,"vulns_high":9.0,"vulns_medium":8.0,"vulns_low":2.0,"vulns_unknown":0.0,"penalty":50.0},"findings":[{"rule_id":"osv/GHSA-c67j-w6g6-q2cm","severity":"critical","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-373, GHSA-c67j-w6g6-q2cm","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-c67j-w6g6-q2cm"},{"rule_id":"osv/PYSEC-2026-2194","severity":"critical","message":"langgraph@0.1.0 (PyPI) is affected by PYSEC-2026-2194","path":"requirements.txt","line":null,"fingerprint":"langgraph@0.1.0 (PyPI):PYSEC-2026-2194"},{"rule_id":"osv/GHSA-6qv9-48xg-fc7f","severity":"high","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-1518, GHSA-6qv9-48xg-fc7f","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-6qv9-48xg-fc7f"},{"rule_id":"osv/GHSA-qh6h-p6c9-ff54","severity":"high","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-2193, GHSA-qh6h-p6c9-ff54","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-qh6h-p6c9-ff54"},{"rule_id":"osv/GHSA-pjwx-r37v-7724","severity":"high","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-2564, GHSA-pjwx-r37v-7724","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-pjwx-r37v-7724"},{"rule_id":"osv/GHSA-g48c-2wqr-h844","severity":"high","message":"langgraph@0.1.0 (PyPI) is affected by PYSEC-2026-83, GHSA-g48c-2wqr-h844","path":"requirements.txt","line":null,"fingerprint":"langgraph@0.1.0 (PyPI):GHSA-g48c-2wqr-h844"},{"rule_id":"osv/GHSA-3qhf-m339-9g5v","severity":"high","message":"mcp@1.0.0 (PyPI) is affected by PYSEC-2026-1616, GHSA-3qhf-m339-9g5v","path":"requirements.txt","line":null,"fingerprint":"mcp@1.0.0 (PyPI):GHSA-3qhf-m339-9g5v"},{"rule_id":"osv/GHSA-9h52-p55h-vw2f","severity":"high","message":"mcp@1.0.0 (PyPI) is affected by PYSEC-2026-1617, GHSA-9h52-p55h-vw2f","path":"requirements.txt","line":null,"fingerprint":"mcp@1.0.0 (PyPI):GHSA-9h52-p55h-vw2f"},{"rule_id":"osv/GHSA-j975-95f5-7wqh","severity":"high","message":"mcp@1.0.0 (PyPI) is affected by PYSEC-2026-1618, GHSA-j975-95f5-7wqh","path":"requirements.txt","line":null,"fingerprint":"mcp@1.0.0 (PyPI):GHSA-j975-95f5-7wqh"},{"rule_id":"osv/GHSA-jpw9-pfvf-9f58","severity":"high","message":"mcp@1.0.0 (PyPI) is affected by PYSEC-2026-3482, GHSA-jpw9-pfvf-9f58","path":"requirements.txt","line":null,"fingerprint":"mcp@1.0.0 (PyPI):GHSA-jpw9-pfvf-9f58"},{"rule_id":"osv/GHSA-vj7q-gjh5-988w","severity":"high","message":"mcp@1.0.0 (PyPI) is affected by PYSEC-2026-3483, GHSA-vj7q-gjh5-988w","path":"requirements.txt","line":null,"fingerprint":"mcp@1.0.0 (PyPI):GHSA-vj7q-gjh5-988w"},{"rule_id":"osv/GHSA-gr75-jv2w-4656","severity":"medium","message":"langchain-anthropic@0.1.0 (PyPI) is affected by PYSEC-2026-2556, GHSA-gr75-jv2w-4656","path":"requirements.txt","line":null,"fingerprint":"langchain-anthropic@0.1.0 (PyPI):GHSA-gr75-jv2w-4656"},{"rule_id":"osv/GHSA-5chr-fjjv-38qv","severity":"medium","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-1517, GHSA-5chr-fjjv-38qv","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-5chr-fjjv-38qv"},{"rule_id":"osv/GHSA-926x-3r5x-gfhw","severity":"medium","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-2563, GHSA-926x-3r5x-gfhw","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-926x-3r5x-gfhw"},{"rule_id":"osv/GHSA-45x7-px36-x8w8","severity":"medium","message":"paramiko@3.0.0 (PyPI) is affected by PYSEC-2026-1758, GHSA-45x7-px36-x8w8","path":"requirements.txt","line":null,"fingerprint":"paramiko@3.0.0 (PyPI):GHSA-45x7-px36-x8w8"},{"rule_id":"osv/GHSA-mr82-8j83-vxmv","severity":"medium","message":"pydantic@2.0.0 (PyPI) is affected by PYSEC-2026-1812, GHSA-mr82-8j83-vxmv","path":"requirements.txt","line":null,"fingerprint":"pydantic@2.0.0 (PyPI):GHSA-mr82-8j83-vxmv"},{"rule_id":"osv/GHSA-rxff-vr5r-8cj5","severity":"medium","message":"streamlit@1.35.0 (PyPI) is affected by PYSEC-2024-153, GHSA-rxff-vr5r-8cj5","path":"requirements.txt","line":null,"fingerprint":"streamlit@1.35.0 (PyPI):GHSA-rxff-vr5r-8cj5"},{"rule_id":"osv/GHSA-vqwp-45wm-r9r5","severity":"medium","message":"streamlit@1.35.0 (PyPI) is affected by PYSEC-2026-212, GHSA-vqwp-45wm-r9r5","path":"requirements.txt","line":null,"fingerprint":"streamlit@1.35.0 (PyPI):GHSA-vqwp-45wm-r9r5"},{"rule_id":"osv/GHSA-7p48-42j8-8846","severity":"medium","message":"streamlit@1.35.0 (PyPI) is affected by PYSEC-2026-2285, GHSA-7p48-42j8-8846","path":"requirements.txt","line":null,"fingerprint":"streamlit@1.35.0 (PyPI):GHSA-7p48-42j8-8846"},{"rule_id":"osv/GHSA-2g6r-c272-w58r","severity":"low","message":"langchain-core@0.2.0 (PyPI) is affected by PYSEC-2026-2562, GHSA-2g6r-c272-w58r","path":"requirements.txt","line":null,"fingerprint":"langchain-core@0.2.0 (PyPI):GHSA-2g6r-c272-w58r"},{"rule_id":"osv/GHSA-r374-rxx8-8654","severity":"low","message":"paramiko@3.0.0 (PyPI) is affected by PYSEC-2026-2858, GHSA-r374-rxx8-8654","path":"requirements.txt","line":null,"fingerprint":"paramiko@3.0.0 (PyPI):GHSA-r374-rxx8-8654"}],"evidence":[],"data":{"ecosystems":["PyPI"]},"error":null},{"analyzer":"sec-actions","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-posture","pillar":"security","status":"ok","tool_version":null,"metrics":{"check:security_policy":0.0,"check:dependency_updates":0.0,"check:signed_commits":1.0,"check:lockfiles":1.0,"signed_commit_share":0.5,"unpinned_manifests":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-distribution","pillar":"security","status":"ok","tool_version":null,"metrics":{"signals":0.0,"binary_assets":0.0,"suspicious":0.0},"findings":[],"evidence":[],"data":{"signals":[],"suspicious":false,"unusual_traction":false,"metadata":true},"error":null},{"analyzer":"qual-complexity","pillar":"quality","status":"ok","tool_version":"lizard 1.25.1","metrics":{"functions":71.0,"function_nloc":908.0,"mean_ccn":4.01,"p90_ccn":11.0,"complex_functions":2.0,"long_functions":0.0,"many_param_functions":0.0,"risky_nloc_share":0.1057},"findings":[],"evidence":[{"kind":"complex-function","description":"diff in checker/diff_engine.py: complexity 29, 70 lines","ref":"checker/diff_engine.py","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/checker/diff_engine.py#L228","weight":0.48333333333333334},{"kind":"complex-function","description":"stream_agent_response._run in agent/agent.py: complexity 16, 26 lines","ref":"agent/agent.py","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/agent/agent.py#L288","weight":0.26666666666666666}],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":2126.0,"duplicated_lines":56.0,"duplicated_share":0.0263,"files":12.0},"findings":[],"evidence":[{"kind":"duplicate-code","description":"6+ duplicated lines: agent/agent.py:215 and agent/agent.py:271","ref":"agent/agent.py","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/agent/agent.py#L215","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: checker/collector.py:132 and checker/collector.py:199","ref":"checker/collector.py","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/checker/collector.py#L132","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: checker/diff_engine.py:272 and checker/diff_engine.py:299","ref":"checker/diff_engine.py","url":"https://github.com/hemadri-labs/sonic-route-checker/blob/cbefa90c2492f6e179821deb77ac752469710c9c/checker/diff_engine.py#L272","weight":0.3}],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":3.0,"weighted_findings":4.25,"scanned_lines":2941.0,"category:best-practice":2.0,"category:correctness":1.0},"findings":[{"rule_id":"opengrep/python.lang.best-practice.arbitrary-sleep","severity":"high","message":"time.sleep() call; did you mean to leave this in?","path":"infra/routes.py","line":34,"fingerprint":"python.lang.best-practice.arbitrary-sleep:infra/routes.py:34"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"dashboard/app.py","line":37,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:dashboard/app.py:37"},{"rule_id":"opengrep/bash.lang.correctness.unquoted-variable-expansion-in-command","severity":"low","message":"Variable expansions must be double-quoted so as to prevent being split into multiple pieces according to whitespace or whichever separator is specified by the IFS variable. If you really wish to split the variable's contents, you may use a variable that starts with an underscore e.g. $_X instead of ","path":"start.sh","line":112,"fingerprint":"bash.lang.correctness.unquoted-variable-expansion-in-command:start.sh:112"}],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":1.0,"check:test_ratio":0.4012,"check:ci_present":0.0,"check:ci_runs_tests":0.0,"check:ci_runs_lint":0.0,"check:tests_cochange":1.0,"test_lines":590.0,"source_lines":2941.0,"test_ratio":0.2006,"ci_files":0.0,"cochange_share":0.5,"cochange_commits":2.0},"findings":[],"evidence":[],"data":{"test_commands":[],"lint_commands":[]},"error":null},{"analyzer":"qual-docs","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:readme":1.0,"check:license":0.0,"check:contributing":0.0,"check:changelog":0.0,"readme_lines":118.0},"findings":[],"evidence":[{"kind":"docs","description":"README.md","ref":"README.md","url":null,"weight":0.0}],"data":{},"error":null},{"analyzer":"qual-type-safety","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:strict_config":0.0,"check:low_escape_density":1.0,"escapes":1.0,"escapes_per_kloc":0.36},"findings":[],"evidence":[],"data":{},"error":null}],"flags":[]}