Public scan — anyone with this URL can view this analysis. Sign up to track your own repos privately, run scheduled re-scans, and get AI fix prompts via your dashboard.
39 of your 111 findings came from Repobility's proprietary detections. ✓ Repobility tags below mark them.

Scan timing: clone 4.66s · analysis 7.28s · 10.5 MB · GitHub API rate-limit (preflight)

sibidharan/zealphp

https://github.com/sibidharan/zealphp · scanned 2026-06-05 15:05 UTC (5 days, 1 hour ago) · 10 languages

202 raw signals (100 security + 102 graph) 43rd percentile · Php · large (100-500K LoC) System graph score 76 (lower by 4)

UNIFIED Repobility · multi-layer engine · AI coders

Complete repo analysis

Last scanned 5 days, 1 hour ago · v2 · 93 actionable findings from 2 signal sources. 58 repeated signals grouped for readability. Security checks, system graph analysis, and verified AI-agent feedback are merged into one review queue.

JSON
Score breakdown â 2026-05-18-v5
Component Sub-score Weight Contribution
structure_score 65.0 0.15 9.75
security_score 44.3 0.25 11.07
testing_score 85.0 0.20 17.00
documentation_score 97.8 0.15 14.67
practices_score 91.0 0.15 13.65
code_quality 56.5 0.10 5.65
Overall 1.00 71.8
Severity distribution — click a segment to filter
Active filters: excluding tests × Reset all
Scan summary Quality grade B (72/100). Dimensions: security 44, maintainability 65. 100 findings (13 security). 138,035 lines analyzed.

Showing 63 of 93 actionable findings. 151 raw detector signals were grouped into reader-sized issues. Click TP / FP to vote on a finding's accuracy — votes adjust the confidence weighting and improve detection across the platform.

critical Security checks security Crypto conf 1.00 [SEC039] Plaintext-equivalent password hash — unsalted single-pass digest: Single-pass digest of a password is cryptographically strong as a hash, but is rainbow-table-attackable when used for passwords: there's no salt and no key-stretching. Attackers with the hash database can crack 90%+ of common passwords offline in hours. CWE-916 (use of password hash without computational effort).
Use a purpose-built password hash: - Python: passlib.hash.argon2.hash(password) - Python: bcrypt.hashpw(password.encode(), bcrypt.gensalt()) - Python: hashlib.pbkdf2_hmac('sha256', password, salt, 600000) - PHP: password_hash($password, PASSWORD_ARGON2ID) - Node.js: argon2.hash(password) …
src/Middleware/BasicAuthMiddleware.php:234
critical Security checks security Crypto conf 1.00 [SEC039] Plaintext-equivalent password hash — unsalted single-pass digest: Single-pass digest of a password is cryptographically strong as a hash, but is rainbow-table-attackable when used for passwords: there's no salt and no key-stretching. Attackers with the hash database can crack 90%+ of common passwords offline in hours. CWE-916 (use of password hash without computational effort).
Use a purpose-built password hash: - Python: passlib.hash.argon2.hash(password) - Python: bcrypt.hashpw(password.encode(), bcrypt.gensalt()) - Python: hashlib.pbkdf2_hmac('sha256', password, salt, 600000) - PHP: password_hash($password, PASSWORD_ARGON2ID) - Node.js: argon2.hash(password) …
src/Learn/Auth.php:24
critical Security checks security secrets conf 0.95 Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Gitleaks detected a committed secret or credential pattern.
docs/superpowers/plans/2026-05-14-learn-section.md:2929
low Security checks quality Quality conf 1.00 ✓ Repobility [MINED006] Overcatch Baseexception: except BaseException: ... — prevents Ctrl+C and SystemExit from working.
Review and fix per the pattern semantics. See CWE-705 / for context.
labs-bench/tail_bench.py:256
low Security checks quality Quality conf 1.00 ✓ Repobility [MINED006] Overcatch Baseexception: except BaseException: ... — prevents Ctrl+C and SystemExit from working.
Review and fix per the pattern semantics. See CWE-705 / for context.
bench/tail/tail_bench.py:256
high Security checks quality Quality conf 1.00 ✓ Repobility Blocking call `input` inside async function `main`
`input` is a synchronous (blocking) call. When invoked inside an `async def` it stalls the event loop, preventing every other coroutine in the process from making progress.
examples/agents/streaming_agent.py:83
high Security checks quality Quality conf 1.00 ✓ Repobility Blocking call `input` inside async function `main`
`input` is a synchronous (blocking) call. When invoked inside an `async def` it stalls the event loop, preventing every other coroutine in the process from making progress.
examples/agents/config_converter.py:2951
high Security checks software dependencies conf 0.90 ✓ Repobility Dockerfile FROM `zealphp:local` not pinned by digest
`FROM zealphp:local` resolves the tag at build time. The registry CAN re-push a different image for the same tag, so every build is potentially different. Production images should pin to `image@sha256:...` for reproducibility + supply-chain integrity.
bench/compare-3way/Dockerfile.bench:1
high Security checks software dependencies conf 0.90 ✓ Repobility 5 occurrences Workflow container/services image `valkey/valkey:7-alpine` unpinned
`container/services image: valkey/valkey:7-alpine` without `@sha256:...` pulls a mutable tag at workflow-run time. Treat workflow container references with the same supply-chain discipline as Dockerfile FROM lines.
2 files, 5 locations
.github/workflows/tests.yml:110, 124, 138 (3 hits)
.github/workflows/mutation.yml:25, 34 (2 hits)
high System graph api Wiring conf 1.00 Dangling fetch: GET /api/chat/status (public/js/pages/home.js:44)
`public/js/pages/home.js:44` calls `GET /api/chat/status` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/chat/status` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: GET /api/learn/chat_status (public/js/learn.js:66)
`public/js/learn.js:66` calls `GET /api/learn/chat_status` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/chat_status` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: GET /api/learn/chatroom/lobby (public/js/learn-chatroom.js:146)
`public/js/learn-chatroom.js:146` calls `GET /api/learn/chatroom/lobby` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/chatroom/lobby` If this points at an external API, prefix it with `https://` so the matche…
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: GET /stream/ssr (public/js/streaming-demos.js:10)
`public/js/streaming-demos.js:10` calls `GET /stream/ssr` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/stream/ssr` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/chat (public/js/pages/home.js:84)
`public/js/pages/home.js:84` calls `POST /api/chat` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/chat` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/convert (public/js/pages/legacy-apps.js:63)
`public/js/pages/legacy-apps.js:63` calls `POST /api/convert` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/convert` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/convert (public/js/pages/migration.js:57)
`public/js/pages/migration.js:57` calls `POST /api/convert` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/convert` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/chat (public/js/learn.js:131)
`public/js/learn.js:131` calls `POST /api/learn/chat` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/chat` If this points at an external API, prefix it with `https://` so the matcher skips it.
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/demo/counter-bump (public/js/learn-demo-viewers.js:207)
`public/js/learn-demo-viewers.js:207` calls `POST /api/learn/demo/counter-bump` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/demo/counter-bump` If this points at an external API, prefix it with `https://` so…
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/demo/counter-reset (public/js/learn-demo-viewers.js:212)
`public/js/learn-demo-viewers.js:212` calls `POST /api/learn/demo/counter-reset` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/demo/counter-reset` If this points at an external API, prefix it with `https://` …
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/demo/store-bump (public/js/learn-demo-viewers.js:351)
`public/js/learn-demo-viewers.js:351` calls `POST /api/learn/demo/store-bump` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/demo/store-bump` If this points at an external API, prefix it with `https://` so the…
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/demo/store-reset (public/js/learn-demo-viewers.js:352)
`public/js/learn-demo-viewers.js:352` calls `POST /api/learn/demo/store-reset` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/demo/store-reset` If this points at an external API, prefix it with `https://` so t…
Dangling fetchFetch
high System graph api Wiring conf 1.00 Dangling fetch: POST /api/learn/demo/store-write (public/js/learn-demo-viewers.js:356)
`public/js/learn-demo-viewers.js:356` calls `POST /api/learn/demo/store-write` but no backend route matches that path. This is a runtime 404 waiting to happen. Tool: fetch Normalized path used for matching: `/learn/demo/store-write` If this points at an external API, prefix it with `https://` so t…
Dangling fetchFetch
medium Security checks quality Error handling conf 1.00 3 occurrences [ERR002] Empty Catch Block: Empty catch blocks hide errors.
Log the error or rethrow it. Use console.error() at minimum.
3 files, 3 locations
public/js/demo-shell.js:32
public/js/learn-chatroom.js:131
public/js/learn-tictactoe.js:195
low Security checks quality Error handling conf 0.55 ✓ Repobility Broad exception handler needs review
This handler catches Exception/BaseException. It is actionable when it swallows errors without logging, re-raising, or returning a structured error. Handlers that intentionally convert exceptions into typed error results should not be treated as high risk.
bench/tail/tail_bench.py:114 Error handlingquality
low Security checks quality Error handling conf 0.55 ✓ Repobility Broad exception handler needs review
This handler catches Exception/BaseException. It is actionable when it swallows errors without logging, re-raising, or returning a structured error. Handlers that intentionally convert exceptions into typed error results should not be treated as high risk.
labs-bench/tail_bench.py:114 Error handlingquality
high Security checks cicd CI/CD security conf 0.82 Docker final stage has no non-root USER
Docker images run as root unless the image or Dockerfile switches to a non-root user.
bench/compare-3way/Dockerfile.bench:1 CI/CD securitycontainers
high Security checks cicd CI/CD security conf 0.82 Docker final stage has no non-root USER
Docker images run as root unless the image or Dockerfile switches to a non-root user.
Dockerfile:4 CI/CD securitycontainers
medium Security checks cicd CI/CD security conf 0.76 Dockerfile copies broad context with incomplete .dockerignore
COPY . or ADD . is safer when .dockerignore excludes secrets, git history, keys, and generated artifacts.
Dockerfile:44 CI/CD securitycontainers
high Security checks quality Quality conf 0.80 localStorage write failures are swallowed silently
localStorage quotas are small and writes can fail. Catching storage errors without a user-visible warning causes silent data loss when notes, images, or snapshots exceed quota.
public/js/pages/home.js:104
medium Security checks quality Quality conf 0.70 Public web app has no Content Security Policy
A Content Security Policy reduces the blast radius of injected scripts if the app is ever served through preview, static hosting, or a web container outside its normal sandbox.
index.html
medium Security checks quality Quality conf 0.78 Public web service has no security.txt
security.txt gives researchers and customers a safe disclosure channel. Public web apps and APIs should publish it under /.well-known/security.txt.
.well-known/security.txt
medium System graph quality Integrity conf 1.00 `fetch()` without try/.catch or AbortSignal — public/js/learn-demo-viewers.js:105
Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout.
runtime safetyRobustness
medium System graph quality Integrity conf 1.00 `fetch()` without try/.catch or AbortSignal — public/js/learn.js:131
Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout.
runtime safetyRobustness
medium System graph quality Integrity conf 1.00 `fetch()` without try/.catch or AbortSignal — public/js/pages/home.js:84
Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout.
runtime safetyRobustness
medium System graph quality Integrity conf 1.00 `fetch()` without try/.catch or AbortSignal — public/js/pages/legacy-apps.js:63
Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout.
runtime safetyRobustness
medium System graph quality Integrity conf 1.00 `fetch()` without try/.catch or AbortSignal — public/js/pages/migration.js:57
Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout.
runtime safetyRobustness
medium System graph cicd CI/CD security conf 1.00 GitHub Actions workflow grants broad write permissions
CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions.
.github/workflows/scorecard.yml CI/CD securitySupply chainGithub actions
medium System graph cicd CI/CD security conf 1.00 GitHub Actions workflow grants broad write permissions
CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions.
.github/workflows/mutation.yml CI/CD securitySupply chainGithub actions
medium System graph network Security conf 1.00 Privileged port 30 in use
Port 30 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer.
.github/workflows/codeql.yml Ports
medium System graph network Security conf 1.00 Privileged port 37 in use
Port 37 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer.
.github/workflows/scorecard.yml Ports
medium System graph network Security conf 1.00 Privileged port 50 in use
Port 50 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer.
scripts/app-lab/perf-vm-zealphp.sh Ports
medium System graph quality Tests conf 1.00 Very low test-to-source ratio
0 test file(s) for 33 source file(s) (ratio 0.00). Consider adding integration or unit tests for critical paths.
Coverage
low Security checks cicd CI/CD security conf 0.72 .dockerignore misses sensitive defaults
.dockerignore exists but does not cover common secret or VCS patterns.
.dockerignore CI/CD securitycontainers
high Security checks cicd CI/CD security conf 0.56 3 occurrences Compose service does not declare a runtime user
If the image does not define USER internally, this service may run as root.
lines 1, 13, 31
docker-compose.yml:1, 13, 31 (3 hits)
CI/CD securitycontainers
high Security checks cicd CI/CD security conf 0.62 3 occurrences Compose service lacks no-new-privileges hardening
no-new-privileges prevents processes from gaining additional privileges through setuid binaries or file capabilities.
lines 1, 13, 31
docker-compose.yml:1, 13, 31 (3 hits)
CI/CD securitycontainers
low Security checks quality Quality conf 0.60 28 occurrences Duplicated implementation block across source files
Duplicate implementation blocks are maintenance debt. Keep them visible, but they are not a high-severity defect unless the duplicated logic is security-sensitive or drifting.
12 files, 12 locations
api/learn/register.php:11
api/zeal/coproc_test.php:7
labs-bench/tail_bench.py:1
public/js/pages/migration.js:2
public/js/pages/store.js:1
public/js/site-nav.js:5
src/HTTP/Client/RequestException.php:6
src/Session/Handler/TableSessionHandler.php:207
duplicationquality
low Security checks quality Quality conf 0.50 Public web app has no humans.txt
humans.txt is optional, but it gives operators and reviewers a simple place to find ownership, contact, and important public documentation links.
humans.txt
low System graph quality Integrity conf 1.00 6 env vars used in code but missing from .env.example
Drift between code and config docs. The first few: `NODE_PORT`, `NODE_WORKERS`, `PORT`, `REQUEST_METHOD`, `SCRIPT_FILENAME`, `WORKERS`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break.
config drift
low System graph hardware Coverage conf 1.00 Containers defined but no K8s/orchestration manifest found
Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo.
Deployment
low System graph software Dead code candidate conf 1.00 File has no detected symbols: bench/compare-3way/node_express.js
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: examples/multi-lang-cgi/public/hello.py
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: examples/spikes/cgi.py
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: public/cgi-bin/echo.py
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: public/cgi-bin/hello.py
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: public/js/demo-shell.js
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph software Dead code candidate conf 1.00 File has no detected symbols: public/notexec/hello.py
Source file with no class/function declarations — possible config, dead code, or scratch file.
low System graph quality Integrity conf 1.00 6 occurrences Near-duplicate function bodies in 2 places
Functions with the same first-5-line body hash: bench/tail/tail_bench.py:percentile, labs-bench/tail_bench.py:percentile This is *the* AI-coder failure mode (4× more duplication in vibe-coded repos — see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate.
6 occurrences
repo-level (6 hits)
duplicatesduplication
low System graph frontend Frontend quality conf 1.00 Stray `console.log` in TS/JS — bench/compare-3way/node_express.js:9
Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable. Why: Hygiene — easy to leak debug output. Rule id: fq.console-leak
Fq console leak
low System graph frontend Frontend quality conf 1.00 Stray `console.log` in TS/JS — bench/compare-3way/node_raw.js:18
Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable. Why: Hygiene — easy to leak debug output. Rule id: fq.console-leak
Fq console leak
low System graph frontend Frontend quality conf 1.00 Stray `console.log` in TS/JS — node_bench.js:22
Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable. Why: Hygiene — easy to leak debug output. Rule id: fq.console-leak
Fq console leak
low System graph api Wiring conf 1.00 Unused endpoint: GET /json
`bench/compare-3way/node_express.js` declares `GET /json` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code — consider removing or documenting who consumes it.
Unused endpoint
low System graph api Wiring conf 1.00 Unused endpoint: GET /raw/:rest
`bench/compare-3way/node_express.js` declares `GET /raw/:rest` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code — consider removing or documenting who consumes it.
Unused endpoint
low System graph quality Complexity conf 1.00 Very large file: examples/agents/config_converter.py (2976 lines)
Files with >800 lines often hide complexity hotspots and discourage tests.
For AI agents: Voting guide (TP/FP) MCP manifest Stdio wrapper SARIF Integrate Findings queue Vote TP/FP on findings to calibrate the engine.
For AI agents + API integrations
Email me when this repo regresses
Free. We re-scan periodically; new criticals → your inbox. No signup required for the scan itself.
API access

This page is publicly accessible at: https://repobility.com/scan/e4dc0a0f-1ff8-4e8d-be22-c8d2e5e3c6a1/

To check status programmatically (no auth required):

curl -s https://repobility.com/api/v1/public/scan/e4dc0a0f-1ff8-4e8d-be22-c8d2e5e3c6a1/

Important — please don't re-submit the same URL repeatedly. The submission endpoint is idempotent: re-submitting the same git URL returns this same scan_token, not a new one. To re-scan this repo, sign up free and use the dashboard.