{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-5+qual-2+sec-2","generated_at":"2026-11-14T14:52:05.934050Z","repo":{"ref":{"host":"github.com","owner":"kotartemiy","name":"newscatcher"},"default_branch":"master","clone_url":"https://github.com/kotartemiy/newscatcher.git","html_url":"https://github.com/kotartemiy/newscatcher","description":"Programmatically collect normalized news from (almost) any website.","stars":2988,"forks":281,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":14079,"primary_language":"Python","license_spdx":"MIT","created_at":"2020-02-24T18:49:18Z","pushed_at":"2020-10-30T19:09:31Z","security_policy_url":null,"distribution":{"owner_created_at":"2016-04-06T16:28:39Z","owner_type":"User","release_assets":[]}},"commit_sha":"b86b1a650241be4e82941319698e01a33c0c01ac","profile":{"lines_by_language":{"Python":291},"files_by_category":{"docs":3,"binary":3,"config":2,"vendored":2,"test":2,"source":1,"generated":1},"source_lines":286,"test_lines":5},"pillars":{"ai_provenance":{"score":0.0,"confidence":0.44,"coverage":1.0,"label":"none-detected","breakdown":{"attributed_share":0.0,"suspected_share":0.0,"estimated_share":0.0,"ai_artifacts":0.0,"flagged_work_units":0.0,"flagged_releases":null,"style_index":0.0},"summary":"No AI attribution or AI-consistent velocity signals detected."},"quality":{"score":60.0,"confidence":0.9,"coverage":1.0,"label":"weak","breakdown":{"complexity":100.0,"duplication":21.7,"lint":100.0,"testing":28.9,"docs":65.0,"type_safety":40.0,"process":null},"summary":"Code quality is weak: test-to-source ratio 0.02, no CI test run detected; 0% of function code in complex or long functions; 25% duplicated lines. Weakest area: duplication."},"security":{"score":51.9,"confidence":0.85,"coverage":1.0,"label":"weak","breakdown":{"secrets":100.0,"sast":24.7,"dependencies":44.9,"ci_actions":null,"posture":0.0,"scorecard":null},"summary":"Security posture is weak: 22 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":4.0,"checked":4.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":17.0,"attributed_commits":0.0,"attributed_commit_share":0.0,"effective_loc":419.0,"attributed_loc":0.0,"attributed_loc_share":0.0,"tools_detected":0.0},"findings":[],"evidence":[],"data":{"attributed_loc_by_commit":{},"tools":{},"monthly":{"2020-02":{"loc":75,"attributed_loc":0},"2020-05":{"loc":344,"attributed_loc":0}}},"error":null},{"analyzer":"ai-artifacts","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"artifacts":0.0,"workflow_agents":0.0,"tools_configured":0.0},"findings":[],"evidence":[],"data":{"artifacts":[],"workflows":[],"tools":[]},"error":null},{"analyzer":"ai-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"work_units":4.0,"flagged_units":0.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":419.0,"pre_ai_era_burst_loc":0.0,"measured_loc":419.0,"flagged_loc":0.0,"flagged_loc_share":0.0,"max_loc_per_hour":64.5,"median_loc_per_hour":64.5,"pr_timed_units":0.0,"excluded_import_loc":0.0},"findings":[],"evidence":[],"data":{"flagged_loc_by_commit":{},"excluded_import_commits":[]},"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":286.0,"index":0.0,"count:narrated_steps":0.0,"per_kloc:narrated_steps":0.0,"files:narrated_steps":0.0,"count:placeholder":0.0,"per_kloc:placeholder":0.0,"files:placeholder":0.0,"count:emoji_in_code":0.0,"per_kloc:emoji_in_code":0.0,"files:emoji_in_code":0.0,"count:assistant_voice":0.0,"per_kloc:assistant_voice":0.0,"files:assistant_voice":0.0},"findings":[],"evidence":[],"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":8.0,"findings_high":4.0,"findings_medium":4.0,"findings_low":0.0,"weighted_findings":4.0,"scanned_lines":286.0,"parse_errors":0.0},"findings":[{"rule_id":"opengrep/python.sqlalchemy.security.sqlalchemy-execute-raw-query","severity":"high","message":"Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition [confidence low]","path":"newscatcher/__init__.py","line":103,"fingerprint":"python.sqlalchemy.security.sqlalchemy-execute-raw-query:newscatcher/__init__.py:103"},{"rule_id":"opengrep/python.sqlalchemy.security.sqlalchemy-execute-raw-query","severity":"high","message":"Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition [confidence low]","path":"newscatcher/__init__.py","line":168,"fingerprint":"python.sqlalchemy.security.sqlalchemy-execute-raw-query:newscatcher/__init__.py:168"},{"rule_id":"opengrep/python.sqlalchemy.security.sqlalchemy-execute-raw-query","severity":"high","message":"Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition [confidence low]","path":"newscatcher/__init__.py","line":208,"fingerprint":"python.sqlalchemy.security.sqlalchemy-execute-raw-query:newscatcher/__init__.py:208"},{"rule_id":"opengrep/python.sqlalchemy.security.sqlalchemy-execute-raw-query","severity":"high","message":"Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition [confidence low]","path":"newscatcher/__init__.py","line":222,"fingerprint":"python.sqlalchemy.security.sqlalchemy-execute-raw-query:newscatcher/__init__.py:222"},{"rule_id":"opengrep/python.lang.security.audit.formatted-sql-query","severity":"medium","message":"Detected possible formatted SQL query. Use parameterized queries instead. [confidence low]","path":"newscatcher/__init__.py","line":103,"fingerprint":"python.lang.security.audit.formatted-sql-query:newscatcher/__init__.py:103"},{"rule_id":"opengrep/python.lang.security.audit.formatted-sql-query","severity":"medium","message":"Detected possible formatted SQL query. Use parameterized queries instead. [confidence low]","path":"newscatcher/__init__.py","line":168,"fingerprint":"python.lang.security.audit.formatted-sql-query:newscatcher/__init__.py:168"},{"rule_id":"opengrep/python.lang.security.audit.formatted-sql-query","severity":"medium","message":"Detected possible formatted SQL query. Use parameterized queries instead. [confidence low]","path":"newscatcher/__init__.py","line":208,"fingerprint":"python.lang.security.audit.formatted-sql-query:newscatcher/__init__.py:208"},{"rule_id":"opengrep/python.lang.security.audit.formatted-sql-query","severity":"medium","message":"Detected possible formatted SQL query. Use parameterized queries instead. [confidence low]","path":"newscatcher/__init__.py","line":222,"fingerprint":"python.lang.security.audit.formatted-sql-query:newscatcher/__init__.py:222"}],"evidence":[],"data":{"rulesets":["python"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"ok","tool_version":"osv-scanner version: 2.7.1","metrics":{"vulnerable_packages":7.0,"vulnerabilities":22.0,"vulns_critical":1.0,"vulns_high":10.0,"vulns_medium":11.0,"vulns_low":0.0,"vulns_unknown":0.0,"penalty":48.0},"findings":[{"rule_id":"osv/GHSA-6q48-6c7w-9gw2","severity":"critical","message":"certifi@2020.4.5.1 (PyPI) is affected by PYSEC-2026-4320, GHSA-6q48-6c7w-9gw2","path":"poetry.lock","line":null,"fingerprint":"certifi@2020.4.5.1 (PyPI):GHSA-6q48-6c7w-9gw2"},{"rule_id":"osv/GHSA-xqr8-7jwr-rhp7","severity":"high","message":"certifi@2020.4.5.1 (PyPI) is affected by PYSEC-2023-135, GHSA-xqr8-7jwr-rhp7","path":"poetry.lock","line":null,"fingerprint":"certifi@2020.4.5.1 (PyPI):GHSA-xqr8-7jwr-rhp7"},{"rule_id":"osv/GHSA-jjg7-2v4v-x38h","severity":"high","message":"idna@2.9 (PyPI) is affected by PYSEC-2024-60, GHSA-jjg7-2v4v-x38h","path":"poetry.lock","line":null,"fingerprint":"idna@2.9 (PyPI):GHSA-jjg7-2v4v-x38h"},{"rule_id":"osv/GHSA-hj5v-574p-mj7c","severity":"high","message":"py@1.8.1 (PyPI) is affected by PYSEC-2020-92, GHSA-hj5v-574p-mj7c","path":"poetry.lock","line":null,"fingerprint":"py@1.8.1 (PyPI):GHSA-hj5v-574p-mj7c"},{"rule_id":"osv/GHSA-q2q7-5pp4-w6pg","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2021-108, GHSA-q2q7-5pp4-w6pg","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-q2q7-5pp4-w6pg"},{"rule_id":"osv/GHSA-v845-jxx5-vc9f","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2023-192, GHSA-v845-jxx5-vc9f","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-v845-jxx5-vc9f"},{"rule_id":"osv/GHSA-qccp-gfcp-xxvc","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-141, GHSA-qccp-gfcp-xxvc","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-qccp-gfcp-xxvc"},{"rule_id":"osv/GHSA-2xpw-w6gg-jr37","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-1994, GHSA-2xpw-w6gg-jr37","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-2xpw-w6gg-jr37"},{"rule_id":"osv/GHSA-38jv-5279-wg99","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-1996, GHSA-38jv-5279-wg99","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-38jv-5279-wg99"},{"rule_id":"osv/GHSA-gm62-xv2j-4w53","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-1998, GHSA-gm62-xv2j-4w53","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-gm62-xv2j-4w53"},{"rule_id":"osv/GHSA-vxq7-64xx-v4gw","severity":"high","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-4177, GHSA-vxq7-64xx-v4gw","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-vxq7-64xx-v4gw"},{"rule_id":"osv/GHSA-43fp-rhv2-5gv8","severity":"medium","message":"certifi@2020.4.5.1 (PyPI) is affected by PYSEC-2022-42986, GHSA-43fp-rhv2-5gv8","path":"poetry.lock","line":null,"fingerprint":"certifi@2020.4.5.1 (PyPI):GHSA-43fp-rhv2-5gv8"},{"rule_id":"osv/GHSA-65pc-fj4g-8rjx","severity":"medium","message":"idna@2.9 (PyPI) is affected by PYSEC-2026-215, GHSA-65pc-fj4g-8rjx","path":"poetry.lock","line":null,"fingerprint":"idna@2.9 (PyPI):GHSA-65pc-fj4g-8rjx"},{"rule_id":"osv/GHSA-6w46-j5rx-g56g","severity":"medium","message":"pytest@5.4.2 (PyPI) is affected by PYSEC-2026-1845, GHSA-6w46-j5rx-g56g","path":"poetry.lock","line":null,"fingerprint":"pytest@5.4.2 (PyPI):GHSA-6w46-j5rx-g56g"},{"rule_id":"osv/GHSA-j8r2-6x86-q33q","severity":"medium","message":"requests@2.23.0 (PyPI) is affected by PYSEC-2023-74, GHSA-j8r2-6x86-q33q","path":"poetry.lock","line":null,"fingerprint":"requests@2.23.0 (PyPI):GHSA-j8r2-6x86-q33q"},{"rule_id":"osv/GHSA-9hjg-9r4m-mvj7","severity":"medium","message":"requests@2.23.0 (PyPI) is affected by PYSEC-2026-1872, GHSA-9hjg-9r4m-mvj7","path":"poetry.lock","line":null,"fingerprint":"requests@2.23.0 (PyPI):GHSA-9hjg-9r4m-mvj7"},{"rule_id":"osv/GHSA-9wx4-h78v-vm56","severity":"medium","message":"requests@2.23.0 (PyPI) is affected by PYSEC-2026-1873, GHSA-9wx4-h78v-vm56","path":"poetry.lock","line":null,"fingerprint":"requests@2.23.0 (PyPI):GHSA-9wx4-h78v-vm56"},{"rule_id":"osv/GHSA-gc5v-m9x4-r6x2","severity":"medium","message":"requests@2.23.0 (PyPI) is affected by PYSEC-2026-2275, GHSA-gc5v-m9x4-r6x2","path":"poetry.lock","line":null,"fingerprint":"requests@2.23.0 (PyPI):GHSA-gc5v-m9x4-r6x2"},{"rule_id":"osv/GHSA-g4mx-q9vg-27p4","severity":"medium","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2023-212, GHSA-g4mx-q9vg-27p4","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-g4mx-q9vg-27p4"},{"rule_id":"osv/GHSA-34jh-p97f-mpxf","severity":"medium","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-1995, GHSA-34jh-p97f-mpxf","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-34jh-p97f-mpxf"},{"rule_id":"osv/GHSA-pq67-6m6q-mj2v","severity":"medium","message":"urllib3@1.25.9 (PyPI) is affected by PYSEC-2026-1999, GHSA-pq67-6m6q-mj2v","path":"poetry.lock","line":null,"fingerprint":"urllib3@1.25.9 (PyPI):GHSA-pq67-6m6q-mj2v"},{"rule_id":"osv/GHSA-jfmj-5v4g-7637","severity":"medium","message":"zipp@3.1.0 (PyPI) is affected by PYSEC-2026-2074, GHSA-jfmj-5v4g-7637","path":"poetry.lock","line":null,"fingerprint":"zipp@3.1.0 (PyPI):GHSA-jfmj-5v4g-7637"}],"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":0.0,"check:lockfiles":1.0,"signed_commit_share":0.4706,"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":12.0,"function_nloc":208.0,"mean_ccn":4.25,"p90_ccn":10.0,"complex_functions":0.0,"long_functions":0.0,"many_param_functions":0.0,"risky_nloc_share":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":220.0,"duplicated_lines":56.0,"duplicated_share":0.2545,"files":1.0},"findings":[],"evidence":[{"kind":"duplicate-code","description":"6+ duplicated lines: newscatcher/__init__.py:83 and newscatcher/__init__.py:148","ref":"newscatcher/__init__.py","url":"https://github.com/kotartemiy/newscatcher/blob/b86b1a650241be4e82941319698e01a33c0c01ac/newscatcher/__init__.py#L83","weight":0.3}],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":0.0,"weighted_findings":0.0,"scanned_lines":286.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":1.0,"check:test_ratio":0.035,"check:ci_present":0.0,"check:ci_runs_tests":0.0,"check:ci_runs_lint":0.0,"check:tests_cochange":0.8,"test_lines":5.0,"source_lines":286.0,"test_ratio":0.0175,"ci_files":0.0,"cochange_share":0.2,"cochange_commits":5.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":1.0,"check:contributing":0.0,"check:changelog":0.0,"readme_lines":136.0},"findings":[],"evidence":[{"kind":"docs","description":"README.md","ref":"README.md","url":null,"weight":0.0},{"kind":"docs","description":"LICENSE","ref":"LICENSE","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":0.0,"escapes_per_kloc":0.0},"findings":[],"evidence":[],"data":{},"error":null}],"flags":[]}