{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-5+qual-2+sec-2","generated_at":"2026-11-14T14:52:02.826466Z","repo":{"ref":{"host":"github.com","owner":"asmuth","name":"recommendify"},"default_branch":"master","clone_url":"https://github.com/asmuth/recommendify.git","html_url":"https://github.com/asmuth/recommendify","description":"Generate recommendations using collaborative filtering","stars":1649,"forks":143,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":1910,"primary_language":"Ruby","license_spdx":null,"created_at":"2012-01-29T03:56:10Z","pushed_at":"2014-05-08T21:18:47Z","security_policy_url":null,"distribution":{"owner_created_at":"2011-01-14T03:50:22Z","owner_type":"User","release_assets":[]}},"commit_sha":"15ad976b703695ecc4f24b08d3a7b86ef01180fe","profile":{"lines_by_language":{"Ruby":1218,"C":324},"files_by_category":{"source":20,"test":10,"other":3,"config":2,"docs":1,"binary":1,"oversized":1},"source_lines":855,"test_lines":687},"pillars":{"ai_provenance":{"score":0.0,"confidence":0.65,"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":59.7,"confidence":0.9,"coverage":1.0,"label":"weak","breakdown":{"complexity":43.5,"duplication":100.0,"lint":36.8,"testing":70.0,"docs":40.0,"type_safety":null,"process":null},"summary":"Code quality is weak: test-to-source ratio 0.80, no CI test run detected; 28% of function code in complex or long functions; 0% duplicated lines. Weakest area: lint."},"security":{"score":59.3,"confidence":0.85,"coverage":1.0,"label":"weak","breakdown":{"secrets":100.0,"sast":38.2,"dependencies":null,"ci_actions":null,"posture":0.0,"scorecard":null},"summary":"Security posture is weak: 1 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":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":"no registry dependencies declared"},{"analyzer":"ai-attribution","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"commits":154.0,"attributed_commits":0.0,"attributed_commit_share":0.0,"effective_loc":2495.0,"attributed_loc":0.0,"attributed_loc_share":0.0,"tools_detected":0.0},"findings":[],"evidence":[],"data":{"attributed_loc_by_commit":{},"tools":{},"monthly":{"2012-01":{"loc":1492,"attributed_loc":0},"2012-02":{"loc":879,"attributed_loc":0},"2012-03":{"loc":124,"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":26.0,"flagged_units":0.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":2495.0,"pre_ai_era_burst_loc":0.0,"measured_loc":2495.0,"flagged_loc":0.0,"flagged_loc_share":0.0,"max_loc_per_hour":90.09722722362261,"median_loc_per_hour":78.12805289638321,"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":855.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":9.0,"findings_high":1.0,"findings_medium":8.0,"findings_low":0.0,"weighted_findings":2.75,"scanned_lines":855.0,"parse_errors":0.0},"findings":[{"rule_id":"opengrep/ruby.lang.security.model-attributes-attr-accessible","severity":"high","message":"Checks for models that do not use attr_accessible. This means there is no limiting of which variables can be manipulated through mass assignment. For newer Rails applications, parameters should be allowlisted using strong parameters. For older Rails versions, they should be allowlisted using strong_ [confidence low]","path":"doc/example.rb","line":9,"fingerprint":"ruby.lang.security.model-attributes-attr-accessible:doc/example.rb:9"},{"rule_id":"opengrep/c.lang.security.insecure-use-printf-fn","severity":"medium","message":"Avoid using user-controlled format strings passed into 'sprintf', 'printf' and 'vsprintf'. These functions put you at risk of buffer overflow vulnerabilities through the use of format string exploits. Instead, use 'snprintf' and 'vsnprintf'. [confidence low]","path":"ext/recommendify.c","line":49,"fingerprint":"c.lang.security.insecure-use-printf-fn:ext/recommendify.c:49"},{"rule_id":"opengrep/c.lang.security.insecure-use-string-copy-fn","severity":"medium","message":"Finding triggers whenever there is a strcpy or strncpy used. This is an issue because strcpy does not affirm the size of the destination array and strncpy will not automatically NULL-terminate strings. This can lead to buffer overflows, which can cause program crashes and potentially let an attacker [confidence low]","path":"ext/recommendify.c","line":66,"fingerprint":"c.lang.security.insecure-use-string-copy-fn:ext/recommendify.c:66"},{"rule_id":"opengrep/c.lang.security.insecure-use-string-copy-fn","severity":"medium","message":"Finding triggers whenever there is a strcpy or strncpy used. This is an issue because strcpy does not affirm the size of the destination array and strncpy will not automatically NULL-terminate strings. This can lead to buffer overflows, which can cause program crashes and potentially let an attacker [confidence low]","path":"ext/recommendify.c","line":70,"fingerprint":"c.lang.security.insecure-use-string-copy-fn:ext/recommendify.c:70"},{"rule_id":"opengrep/c.lang.security.insecure-use-string-copy-fn","severity":"medium","message":"Finding triggers whenever there is a strcpy or strncpy used. This is an issue because strcpy does not affirm the size of the destination array and strncpy will not automatically NULL-terminate strings. This can lead to buffer overflows, which can cause program crashes and potentially let an attacker [confidence low]","path":"ext/recommendify.c","line":76,"fingerprint":"c.lang.security.insecure-use-string-copy-fn:ext/recommendify.c:76"},{"rule_id":"opengrep/c.lang.security.insecure-use-string-copy-fn","severity":"medium","message":"Finding triggers whenever there is a strcpy or strncpy used. This is an issue because strcpy does not affirm the size of the destination array and strncpy will not automatically NULL-terminate strings. This can lead to buffer overflows, which can cause program crashes and potentially let an attacker [confidence low]","path":"ext/recommendify.c","line":129,"fingerprint":"c.lang.security.insecure-use-string-copy-fn:ext/recommendify.c:129"},{"rule_id":"opengrep/c.lang.security.insecure-use-strcat-fn","severity":"medium","message":"Finding triggers whenever there is a strcat or strncat used. This is an issue because strcat or strncat can lead to buffer overflow vulns. Fix this by using strcat_s instead. [confidence low]","path":"ext/recommendify.c","line":154,"fingerprint":"c.lang.security.insecure-use-strcat-fn:ext/recommendify.c:154"},{"rule_id":"opengrep/c.lang.security.insecure-use-strcat-fn","severity":"medium","message":"Finding triggers whenever there is a strcat or strncat used. This is an issue because strcat or strncat can lead to buffer overflow vulns. Fix this by using strcat_s instead. [confidence low]","path":"ext/recommendify.c","line":155,"fingerprint":"c.lang.security.insecure-use-strcat-fn:ext/recommendify.c:155"},{"rule_id":"opengrep/ruby.lang.security.dangerous-subshell","severity":"medium","message":"Detected non-static command inside `...`. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code. [confidence low]","path":"lib/recommendify/jaccard_input_matrix.rb","line":37,"fingerprint":"ruby.lang.security.dangerous-subshell:lib/recommendify/jaccard_input_matrix.rb:37"}],"evidence":[],"data":{"rulesets":["ruby","c"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"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":0.0,"signed_commit_share":0.0,"unpinned_manifests":1.0},"findings":[],"evidence":[{"kind":"posture","description":"Gemfile has no lockfile alongside it (unpinned dependencies)","ref":"Gemfile","url":null,"weight":0.3}],"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":78.0,"function_nloc":505.0,"mean_ccn":1.78,"p90_ccn":2.0,"complex_functions":1.0,"long_functions":1.0,"many_param_functions":0.0,"risky_nloc_share":0.2772},"findings":[],"evidence":[{"kind":"complex-function","description":"main in ext/recommendify.c: complexity 34, 140 lines","ref":"ext/recommendify.c","url":"https://github.com/asmuth/recommendify/blob/15ad976b703695ecc4f24b08d3a7b86ef01180fe/ext/recommendify.c#L15","weight":0.5666666666666667}],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":529.0,"duplicated_lines":0.0,"duplicated_share":0.0,"files":20.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":4.0,"weighted_findings":4.0,"scanned_lines":855.0,"category:correctness":4.0},"findings":[{"rule_id":"opengrep/c.lang.correctness.incorrect-use-ato-fn","severity":"medium","message":"Avoid the 'ato*()' family of functions. Their use can lead to undefined behavior, integer overflows, and lack of appropriate error handling. Instead prefer the 'strtol*()' family of functions.","path":"ext/recommendify.c","line":68,"fingerprint":"c.lang.correctness.incorrect-use-ato-fn:ext/recommendify.c:68"},{"rule_id":"opengrep/c.lang.correctness.incorrect-use-ato-fn","severity":"medium","message":"Avoid the 'ato*()' family of functions. Their use can lead to undefined behavior, integer overflows, and lack of appropriate error handling. Instead prefer the 'strtol*()' family of functions.","path":"ext/recommendify.c","line":95,"fingerprint":"c.lang.correctness.incorrect-use-ato-fn:ext/recommendify.c:95"},{"rule_id":"opengrep/c.lang.correctness.incorrect-use-ato-fn","severity":"medium","message":"Avoid the 'ato*()' family of functions. Their use can lead to undefined behavior, integer overflows, and lack of appropriate error handling. Instead prefer the 'strtol*()' family of functions.","path":"ext/recommendify.c","line":130,"fingerprint":"c.lang.correctness.incorrect-use-ato-fn:ext/recommendify.c:130"},{"rule_id":"opengrep/c.lang.correctness.incorrect-use-ato-fn","severity":"medium","message":"Avoid the 'ato*()' family of functions. Their use can lead to undefined behavior, integer overflows, and lack of appropriate error handling. Instead prefer the 'strtol*()' family of functions.","path":"ext/recommendify.c","line":166,"fingerprint":"c.lang.correctness.incorrect-use-ato-fn:ext/recommendify.c:166"}],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":1.0,"check:test_ratio":1.0,"check:ci_present":1.0,"check:ci_runs_tests":0.0,"check:ci_runs_lint":0.0,"check:tests_cochange":1.0,"test_lines":687.0,"source_lines":855.0,"test_ratio":0.8035,"ci_files":1.0,"cochange_share":0.3523,"cochange_commits":88.0},"findings":[],"evidence":[{"kind":"ci","description":"CI config: .travis.yml","ref":".travis.yml","url":null,"weight":0.0}],"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":98.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":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null}],"flags":[]}