{"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": "DKR001", "name": "Docker final stage has no non-root USER", "shortDescription": {"text": "Docker final stage has no non-root USER"}, "fullDescription": {"text": "Docker images run as root unless the image or Dockerfile switches to a non-root user."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "medium", "confidence": 0.82, "cwe": "", "owasp": ""}}, {"id": "DKR017", "name": "Dockerfile installs dependencies after copying the full source tree", "shortDescription": {"text": "Dockerfile installs dependencies after copying the full source tree"}, "fullDescription": {"text": "When dependency installation comes after COPY ., any source change invalidates the dependency layer and makes Docker rebuild much more slowly."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "medium", "confidence": 0.9, "cwe": "", "owasp": ""}}, {"id": "DKR007", "name": "Docker build context has no .dockerignore", "shortDescription": {"text": "Docker build context has no .dockerignore"}, "fullDescription": {"text": "Without .dockerignore, build context can include source history, local env files, dependencies, and generated artifacts."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "medium", "confidence": 0.9, "cwe": "", "owasp": ""}}, {"id": "DKC015", "name": "Database service has no healthcheck", "shortDescription": {"text": "Database service has no healthcheck"}, "fullDescription": {"text": "Compose starts dependent containers in dependency order, but it does not wait for a database to be ready unless a healthcheck is defined and dependents use service_healthy."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "low", "confidence": 0.72, "cwe": "", "owasp": ""}}, {"id": "DKC010", "name": "Compose service lacks no-new-privileges hardening", "shortDescription": {"text": "Compose service lacks no-new-privileges hardening"}, "fullDescription": {"text": "no-new-privileges prevents processes from gaining additional privileges through setuid binaries or file capabilities."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "low", "confidence": 0.62, "cwe": "", "owasp": ""}}, {"id": "DKC006", "name": "Compose service does not declare a runtime user", "shortDescription": {"text": "Compose service does not declare a runtime user"}, "fullDescription": {"text": "If the image does not define USER internally, this service may run as root."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "low", "confidence": 0.56, "cwe": "", "owasp": ""}}, {"id": "DKC017", "name": "Database password is wired through an environment variable placeholder", "shortDescription": {"text": "Database password is wired through an environment variable placeholder"}, "fullDescription": {"text": "Environment placeholders are not committed secrets, but database official images often support *_FILE variables so Compose secrets can provide narrower filesystem-based access."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "low", "confidence": 0.58, "cwe": "", "owasp": ""}}, {"id": "DKR011", "name": "Dockerfile installs recommended OS packages", "shortDescription": {"text": "Dockerfile installs recommended OS packages"}, "fullDescription": {"text": "Installing recommended packages often pulls in unnecessary runtime surface area."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "low", "confidence": 0.72, "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": "DKC011", "name": "Database service publishes a host port", "shortDescription": {"text": "Database service publishes a host port"}, "fullDescription": {"text": "Publishing database ports to the host increases exposure. Internal Compose networking usually only needs expose, not ports."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "high", "confidence": 0.84, "cwe": "", "owasp": ""}}, {"id": "DKR014", "name": "Dockerfile copies the entire context without .dockerignore", "shortDescription": {"text": "Dockerfile copies the entire context without .dockerignore"}, "fullDescription": {"text": "COPY . or ADD . sends the full build context to Docker. Without .dockerignore this can include secrets, git history, and local artifacts."}, "properties": {"scanner": "repobility-docker", "category": "docker", "severity": "high", "confidence": 0.92, "cwe": "", "owasp": ""}}]}}, "automationDetails": {"id": "repobility/499"}, "properties": {"repository": "ethteck/coddog", "repoUrl": "https://github.com/ethteck/coddog.git", "branch": "main"}, "results": [{"ruleId": "DKR001", "level": "warning", "message": {"text": "Docker final stage has no non-root USER"}, "properties": {"repobilityId": 29313, "scanner": "repobility-docker", "fingerprint": "281171bae37e6aa350a30ef155c590a3adfb200c0efec05ab5456f38e47f9455", "category": "docker", "severity": "medium", "confidence": 0.82, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "No USER directive was found in the final runtime stage.", "evidence": {"rule_id": "DKR001", "scanner": "repobility-docker", "final_base": "nginx:alpine", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", "https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html", "https://github.com/hadolint/hadolint"], "correlation_key": "fp|281171bae37e6aa350a30ef155c590a3adfb200c0efec05ab5456f38e47f9455"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.frontend"}, "region": {"startLine": 32}}}]}, {"ruleId": "DKR017", "level": "warning", "message": {"text": "Dockerfile installs dependencies after copying the full source tree"}, "properties": {"repobilityId": 29312, "scanner": "repobility-docker", "fingerprint": "49e907f312ec6b07e2c55e015da96fd180c334b219f46749720b0c81d911f56c", "category": "docker", "severity": "medium", "confidence": 0.9, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Broad context copy at line 15 appears before dependency installation.", "evidence": {"rule_id": "DKR017", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"], "broad_copy_line": 15, "correlation_key": "fp|49e907f312ec6b07e2c55e015da96fd180c334b219f46749720b0c81d911f56c", "dependency_install_line": 16}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.db-cli"}, "region": {"startLine": 16}}}]}, {"ruleId": "DKR007", "level": "warning", "message": {"text": "Docker build context has no .dockerignore"}, "properties": {"repobilityId": 29308, "scanner": "repobility-docker", "fingerprint": "c98378cf8c37e4866e89d6ca06a24b7e8c44654aa34e6e4bf1367c4a4c0c5b44", "category": "docker", "severity": "medium", "confidence": 0.9, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Dockerfile exists but repository root has no .dockerignore.", "evidence": {"rule_id": "DKR007", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"], "correlation_key": "fp|c98378cf8c37e4866e89d6ca06a24b7e8c44654aa34e6e4bf1367c4a4c0c5b44"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".dockerignore"}, "region": {"startLine": 1}}}]}, {"ruleId": "DKR017", "level": "warning", "message": {"text": "Dockerfile installs dependencies after copying the full source tree"}, "properties": {"repobilityId": 29307, "scanner": "repobility-docker", "fingerprint": "084633808fb5327ebe20283feb5a89a63988d7d0acc5a02fec41455db560c619", "category": "docker", "severity": "medium", "confidence": 0.9, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Broad context copy at line 13 appears before dependency installation.", "evidence": {"rule_id": "DKR017", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"], "broad_copy_line": 13, "correlation_key": "fp|084633808fb5327ebe20283feb5a89a63988d7d0acc5a02fec41455db560c619", "dependency_install_line": 14}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.api"}, "region": {"startLine": 14}}}]}, {"ruleId": "DKC015", "level": "note", "message": {"text": "Database service has no healthcheck"}, "properties": {"repobilityId": 29319, "scanner": "repobility-docker", "fingerprint": "8403a7c6c68c2757b320cde952328f8a6faa5a58ee7077dbd438079472087929", "category": "docker", "severity": "low", "confidence": 0.72, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "Database-like service has no Compose healthcheck.", "evidence": {"rule_id": "DKC015", "scanner": "repobility-docker", "service": "db", "references": ["https://docs.docker.com/compose/how-tos/startup-order/"], "correlation_key": "fp|8403a7c6c68c2757b320cde952328f8a6faa5a58ee7077dbd438079472087929"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 84}}}]}, {"ruleId": "DKC010", "level": "note", "message": {"text": "Compose service lacks no-new-privileges hardening"}, "properties": {"repobilityId": 29318, "scanner": "repobility-docker", "fingerprint": "316eca5fe477b667dab15edfeceb25b40d6d3ad56c74f2e3926c9546af3eef6a", "category": "docker", "severity": "low", "confidence": 0.62, "triageState": "open", "verdict": "needs_review", "isResolved": false, "reason": "App-like service has no security_opt no-new-privileges setting.", "evidence": {"rule_id": "DKC010", "scanner": "repobility-docker", "service": "frontend", "references": ["https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"], "correlation_key": "fp|316eca5fe477b667dab15edfeceb25b40d6d3ad56c74f2e3926c9546af3eef6a"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 60}}}]}, {"ruleId": "DKC006", "level": "note", "message": {"text": "Compose service does not declare a runtime user"}, "properties": {"repobilityId": 29317, "scanner": "repobility-docker", "fingerprint": "3ffe09bc786350d114121c79186a2f167951e1ed24a7f474e6c81406fdb81dd9", "category": "docker", "severity": "low", "confidence": 0.56, "triageState": "open", "verdict": "needs_review", "isResolved": false, "reason": "Service has no user setting and Repobility could not prove the image runs non-root.", "evidence": {"rule_id": "DKC006", "scanner": "repobility-docker", "service": "frontend", "references": ["https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"], "correlation_key": "fp|3ffe09bc786350d114121c79186a2f167951e1ed24a7f474e6c81406fdb81dd9"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 60}}}]}, {"ruleId": "DKC010", "level": "note", "message": {"text": "Compose service lacks no-new-privileges hardening"}, "properties": {"repobilityId": 29316, "scanner": "repobility-docker", "fingerprint": "d105f699290f21df292554643e176c482afbfe875732fc56fcb302037e3e4401", "category": "docker", "severity": "low", "confidence": 0.62, "triageState": "open", "verdict": "needs_review", "isResolved": false, "reason": "App-like service has no security_opt no-new-privileges setting.", "evidence": {"rule_id": "DKC010", "scanner": "repobility-docker", "service": "api", "references": ["https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"], "correlation_key": "fp|d105f699290f21df292554643e176c482afbfe875732fc56fcb302037e3e4401"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 31}}}]}, {"ruleId": "DKC017", "level": "note", "message": {"text": "Database password is wired through an environment variable placeholder"}, "properties": {"repobilityId": 29315, "scanner": "repobility-docker", "fingerprint": "18e2fc9a3b6cabf3942b52c53b39876ad1a6e42970e473a68a19cd764178c23b", "category": "docker", "severity": "low", "confidence": 0.58, "triageState": "open", "verdict": "needs_review", "isResolved": false, "reason": "Database image supports file-based secret variables, but only placeholder environment variables were found.", "evidence": {"rule_id": "DKC017", "scanner": "repobility-docker", "service": "postgres", "variables": ["POSTGRES_PASSWORD"], "references": ["https://docs.docker.com/compose/how-tos/use-secrets/"], "correlation_key": "fp|18e2fc9a3b6cabf3942b52c53b39876ad1a6e42970e473a68a19cd764178c23b"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 2}}}]}, {"ruleId": "DKR011", "level": "note", "message": {"text": "Dockerfile installs recommended OS packages"}, "properties": {"repobilityId": 29311, "scanner": "repobility-docker", "fingerprint": "1dcfa2261a6bb6949b2997825052f73be89dc5877da6a50579a34c9fdef23a9c", "category": "docker", "severity": "low", "confidence": 0.72, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "apt install appears without --no-install-recommends.", "evidence": {"rule_id": "DKR011", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", "https://github.com/hadolint/hadolint"], "correlation_key": "fp|1dcfa2261a6bb6949b2997825052f73be89dc5877da6a50579a34c9fdef23a9c"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.db-cli"}, "region": {"startLine": 20}}}]}, {"ruleId": "DKR011", "level": "note", "message": {"text": "Dockerfile installs recommended OS packages"}, "properties": {"repobilityId": 29309, "scanner": "repobility-docker", "fingerprint": "530b567c5e2d9c85d32967b0c5c8e17cbde4f693af66f2a9307800425132d5a7", "category": "docker", "severity": "low", "confidence": 0.72, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "apt install appears without --no-install-recommends.", "evidence": {"rule_id": "DKR011", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", "https://github.com/hadolint/hadolint"], "correlation_key": "fp|530b567c5e2d9c85d32967b0c5c8e17cbde4f693af66f2a9307800425132d5a7"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.db-cli"}, "region": {"startLine": 7}}}]}, {"ruleId": "DKR011", "level": "note", "message": {"text": "Dockerfile installs recommended OS packages"}, "properties": {"repobilityId": 29306, "scanner": "repobility-docker", "fingerprint": "e2a0facba2e37a5aef9989d12bc904489fead5067c3a18bc227376995c442ada", "category": "docker", "severity": "low", "confidence": 0.72, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "apt install appears without --no-install-recommends.", "evidence": {"rule_id": "DKR011", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", "https://github.com/hadolint/hadolint"], "correlation_key": "fp|e2a0facba2e37a5aef9989d12bc904489fead5067c3a18bc227376995c442ada"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.api"}, "region": {"startLine": 18}}}]}, {"ruleId": "DKR011", "level": "note", "message": {"text": "Dockerfile installs recommended OS packages"}, "properties": {"repobilityId": 29304, "scanner": "repobility-docker", "fingerprint": "020c2b6584c1f86c853b72527dadcaadcbd0361ab6039f4679abc4d32949eae4", "category": "docker", "severity": "low", "confidence": 0.72, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "apt install appears without --no-install-recommends.", "evidence": {"rule_id": "DKR011", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", "https://github.com/hadolint/hadolint"], "correlation_key": "fp|020c2b6584c1f86c853b72527dadcaadcbd0361ab6039f4679abc4d32949eae4"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.api"}, "region": {"startLine": 7}}}]}, {"ruleId": "AIC003", "level": "note", "message": {"text": "Duplicated implementation block across source files"}, "properties": {"repobilityId": 29303, "scanner": "repobility-ai-code-hygiene", "fingerprint": "ef69ef62c9ae1f11dda0f032e5ec0246251183f79f79fa29d6af8f07224a68c1", "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": "website/src/components/SymbolLabel.tsx", "duplicate_line": 53, "correlation_key": "fp|ef69ef62c9ae1f11dda0f032e5ec0246251183f79f79fa29d6af8f07224a68c1"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "website/src/components/SymbolLabelOther.tsx"}, "region": {"startLine": 24}}}]}, {"ruleId": "DKC011", "level": "error", "message": {"text": "Database service publishes a host port"}, "properties": {"repobilityId": 29314, "scanner": "repobility-docker", "fingerprint": "048aedd7e977b7a23cc97eedf936566b54b38c0d1a9f7a071a04437933366902", "category": "docker", "severity": "high", "confidence": 0.84, "triageState": "open", "verdict": "likely", "isResolved": false, "reason": "Database-like image publishes host ports without a loopback-only bind.", "evidence": {"ports": [{"raw": "5432:5432", "target": "5432", "host_ip": "", "published": "5432"}], "rule_id": "DKC011", "scanner": "repobility-docker", "service": "postgres", "references": ["https://docs.docker.com/compose/how-tos/environment-variables/best-practices/", "https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"], "exposure_scope": "public", "correlation_key": "fp|048aedd7e977b7a23cc97eedf936566b54b38c0d1a9f7a071a04437933366902"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/docker-compose.yml"}, "region": {"startLine": 2}}}]}, {"ruleId": "DKR014", "level": "error", "message": {"text": "Dockerfile copies the entire context without .dockerignore"}, "properties": {"repobilityId": 29310, "scanner": "repobility-docker", "fingerprint": "f73e3bdf20b6e1b4761001a172c0d6ea7b9a1205718e628db0a43fadcb0111d3", "category": "docker", "severity": "high", "confidence": 0.92, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Broad context copy and missing .dockerignore were found together.", "evidence": {"rule_id": "DKR014", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"], "correlation_key": "fp|f73e3bdf20b6e1b4761001a172c0d6ea7b9a1205718e628db0a43fadcb0111d3"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.db-cli"}, "region": {"startLine": 15}}}]}, {"ruleId": "DKR014", "level": "error", "message": {"text": "Dockerfile copies the entire context without .dockerignore"}, "properties": {"repobilityId": 29305, "scanner": "repobility-docker", "fingerprint": "0ca04e85f0b85b699c310fbd6afa0bda263d1933d983b00c14063ad701e29389", "category": "docker", "severity": "high", "confidence": 0.92, "triageState": "open", "verdict": "confirmed", "isResolved": false, "reason": "Broad context copy and missing .dockerignore were found together.", "evidence": {"rule_id": "DKR014", "scanner": "repobility-docker", "references": ["https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"], "correlation_key": "fp|0ca04e85f0b85b699c310fbd6afa0bda263d1933d983b00c14063ad701e29389"}}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "deployment/Dockerfile.api"}, "region": {"startLine": 13}}}]}]}]}