{"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": "scanner-496aef5873137481", "name": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/page.tsx:71", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/page.tsx:71"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f6df017e1db0a666", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/print/file/page.tsx:149", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/print/file/page.tsx:149"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-980b4569eb58dcd2", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/TasksFilesSidebar.tsx:87", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/TasksFilesSidebar.tsx:87"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f79a950a917cac78", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/SubAgentIndicator.tsx:94", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/SubAgentIndicator.tsx:94"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a3575f95de31452f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ToolCallBox.tsx:261", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ToolCallBox.tsx:261"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-9cfaa37997f14c4f", "name": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/components/ChatInterface.tsx:114", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/components/ChatInterface.tsx:114"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6564a6f5a7a3d9a5", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ThreadList.tsx:294", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ThreadList.tsx:294"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d61ad624df675602", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/components/FileViewDialog.tsx:376", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/components/FileViewDialog.tsx:376"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4f4d7f5570b4d2e0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/workspace/SourcesSection.tsx:46", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/workspace/SourcesSection.tsx:46"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-60427b03771411b6", "name": "Dockerfile runs as root: frontend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: frontend/Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7056c551ae36a237", "name": "Docker base image is tag-pinned but not digest-pinned: node:24-alpine", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-alpine"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1f66ad88286ca30a", "name": "Dockerfile runs as root: backend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7487ec1ddb4f5e1a", "name": "Docker base image is tag-pinned but not digest-pinned: langchain/langgraph-api:3.13", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: langchain/langgraph-api:3.13"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4f15625af29db57a", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/print/file/page.tsx:149", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/print/file/page.tsx:149"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0c99d387700fd9a1", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/components/FileViewDialog.tsx:376", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/components/FileViewDialog.tsx:376"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6372cebde0220094", "name": "No auth library detected", "shortDescription": {"text": "No auth library detected"}, "fullDescription": {"text": "The scanner did not find any standard auth library (JWT, OAuth, NextAuth, Auth0, etc.). The repo has auth/admin/session surface indicators, so auth may live in custom code, in a separate service, or be missing."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-27924aa79fa4a517", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v6 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ea3b5e389d8c9c0f", "name": "Low test-to-source ratio", "shortDescription": {"text": "Low test-to-source ratio"}, "fullDescription": {"text": "7 tests / 66 src (ratio 0.11)."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 15 placeholder/mock markers across 8 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-122f91b7f2906dc4", "name": "Agent authority lacks a verifier contract: .claude/settings.json", "shortDescription": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2321101af71d3029", "name": "Agent authority lacks a verifier contract: backend/app/career_agent/AGENTS.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/AGENTS.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-3b3f0dafc292e8f4", "name": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/hiring-recon/hiring-recon/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/hiring-recon/hiring-recon/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-29a26032319e5569", "name": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/interview-coach/interview-coach/SKILL.md", "shortDescription": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/interview-coach/interview-coach/SKILL.md"}, "fullDescription": {"text": "This agent instruction grants code or shell authority but does not state the verification gate that decides promotion. The recurring safe pattern is: LLM proposes; deterministic tests/build/security checks verify; only verified code promotes."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a82e0dc822c3086b", "name": "Commented-code block (7 lines) in frontend/scripts/check-langchain-sdk-sync.mjs:2", "shortDescription": {"text": "Commented-code block (7 lines) in frontend/scripts/check-langchain-sdk-sync.mjs:2"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fb5af650f387ab63", "name": "Commented-code block (7 lines) in frontend/src/app/components/ChatInterface.tsx:104", "shortDescription": {"text": "Commented-code block (7 lines) in frontend/src/app/components/ChatInterface.tsx:104"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3e64b6b8ab981c47", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/lib/agentFiles.ts:271", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/lib/agentFiles.ts:271"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c8bd268d8e0dc60a", "name": "Commented-code block (5 lines) in frontend/src/app/hooks/useChat.ts:51", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/app/hooks/useChat.ts:51"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a80c56b0fc00f073", "name": "Legacy-named symbol `model_copy` in backend/tests/career_agent/test_middleware_model_override.py:10", "shortDescription": {"text": "Legacy-named symbol `model_copy` in backend/tests/career_agent/test_middleware_model_override.py:10"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-435b109ed67ac80a", "name": "Legacy-named symbol `page_3_image_23_v2` in backend/tests/career_agent/test_tools.py:289", "shortDescription": {"text": "Legacy-named symbol `page_3_image_23_v2` in backend/tests/career_agent/test_tools.py:289"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dd053e66ea6b431b", "name": "Commented-code block (5 lines) in backend/app/career_agent/agents.py:71", "shortDescription": {"text": "Commented-code block (5 lines) in backend/app/career_agent/agents.py:71"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a462ec3db77fab32", "name": "Legacy-named symbol `model_copy` in backend/app/career_agent/middleware.py:146", "shortDescription": {"text": "Legacy-named symbol `model_copy` in backend/app/career_agent/middleware.py:146"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b662bacb40ebf008", "name": "Commented-code block (9 lines) in backend/app/career_agent/middleware.py:124", "shortDescription": {"text": "Commented-code block (9 lines) in backend/app/career_agent/middleware.py:124"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/app/career_agent/middleware.py:wrap_model_call, backend/app/career_agent/middleware.py:wrap_model_call\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/20791"}, "properties": {"repository": "tam159/next-role", "repoUrl": "https://github.com/tam159/next-role", "branch": "main"}, "results": [{"ruleId": "scanner-496aef5873137481", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/page.tsx:71"}, "properties": {"repobilityId": "abeb20b7c7862eec", "scanner": "scanner-primary", "fingerprint": "496aef5873137481", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-f6df017e1db0a666", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/print/file/page.tsx:149"}, "properties": {"repobilityId": "e961928af27db2db", "scanner": "scanner-primary", "fingerprint": "f6df017e1db0a666", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-980b4569eb58dcd2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/TasksFilesSidebar.tsx:87"}, "properties": {"repobilityId": "44b7e046cb2c8795", "scanner": "scanner-primary", "fingerprint": "980b4569eb58dcd2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f79a950a917cac78", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/SubAgentIndicator.tsx:94"}, "properties": {"repobilityId": "c9be5914496e95df", "scanner": "scanner-primary", "fingerprint": "f79a950a917cac78", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a3575f95de31452f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ToolCallBox.tsx:261"}, "properties": {"repobilityId": "4154138a7c630ae2", "scanner": "scanner-primary", "fingerprint": "a3575f95de31452f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9cfaa37997f14c4f", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 frontend/src/app/components/ChatInterface.tsx:114"}, "properties": {"repobilityId": "98816d7e8bb787fa", "scanner": "scanner-primary", "fingerprint": "9cfaa37997f14c4f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-6564a6f5a7a3d9a5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/ThreadList.tsx:294"}, "properties": {"repobilityId": "28db24a245b55643", "scanner": "scanner-primary", "fingerprint": "6564a6f5a7a3d9a5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d61ad624df675602", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/app/components/FileViewDialog.tsx:376"}, "properties": {"repobilityId": "7c57dca04dbfcc94", "scanner": "scanner-primary", "fingerprint": "d61ad624df675602", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-4f4d7f5570b4d2e0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/app/components/workspace/SourcesSection.tsx:46"}, "properties": {"repobilityId": "67679c0ccb14f03c", "scanner": "scanner-primary", "fingerprint": "4f4d7f5570b4d2e0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-60427b03771411b6", "level": "warning", "message": {"text": "Dockerfile runs as root: frontend/Dockerfile"}, "properties": {"repobilityId": "735c01d8531dfd2c", "scanner": "scanner-primary", "fingerprint": "60427b03771411b6", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-7056c551ae36a237", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:24-alpine"}, "properties": {"repobilityId": "7c3aede5ba1ec7bb", "scanner": "scanner-primary", "fingerprint": "7056c551ae36a237", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1f66ad88286ca30a", "level": "warning", "message": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "properties": {"repobilityId": "7afd2b0e8a8c9eeb", "scanner": "scanner-primary", "fingerprint": "1f66ad88286ca30a", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-7487ec1ddb4f5e1a", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: langchain/langgraph-api:3.13"}, "properties": {"repobilityId": "712f54a193def56e", "scanner": "scanner-primary", "fingerprint": "7487ec1ddb4f5e1a", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-4f15625af29db57a", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/print/file/page.tsx:149"}, "properties": {"repobilityId": "dc954976446b4335", "scanner": "scanner-primary", "fingerprint": "4f15625af29db57a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/print/file/page.tsx"}, "region": {"startLine": 149}}}]}, {"ruleId": "scanner-0c99d387700fd9a1", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/app/components/FileViewDialog.tsx:376"}, "properties": {"repobilityId": "3470cb0518d53dc8", "scanner": "scanner-primary", "fingerprint": "0c99d387700fd9a1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/app/components/FileViewDialog.tsx"}, "region": {"startLine": 376}}}]}, {"ruleId": "scanner-6372cebde0220094", "level": "warning", "message": {"text": "No auth library detected"}, "properties": {"repobilityId": "a5b6035a5bbf8054", "scanner": "scanner-primary", "fingerprint": "6372cebde0220094", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["coverage", "auth"]}}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "97a9a5de61d82fcd", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 26}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "f6139f50639923c9", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 31}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "9e5617d449b061f6", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 40}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "4a63b1fd6887cae9", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 45}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "54c8f1b47dd62535", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 56}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "97a9a5de61d82fcd", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 76}}}]}, {"ruleId": "scanner-27924aa79fa4a517", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "f6139f50639923c9", "scanner": "scanner-primary", "fingerprint": "27924aa79fa4a517", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci.yml"}, "region": {"startLine": 79}}}]}, {"ruleId": "scanner-ea3b5e389d8c9c0f", "level": "note", "message": {"text": "Low test-to-source ratio"}, "properties": {"repobilityId": "ef7b2552cc00a375", "scanner": "scanner-primary", "fingerprint": "ea3b5e389d8c9c0f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["tests"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "09f0042d116e783e", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "45d67f47f1ac38da", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "a11750aa48edacf3", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-122f91b7f2906dc4", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: .claude/settings.json"}, "properties": {"repobilityId": "a2967269048b6a9d", "scanner": "scanner-primary", "fingerprint": "122f91b7f2906dc4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "claude_instruction"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".claude/settings.json"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2321101af71d3029", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/AGENTS.md"}, "properties": {"repobilityId": "162e0564d6fb235f", "scanner": "scanner-primary", "fingerprint": "2321101af71d3029", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "agents_md"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/career_agent/AGENTS.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3b3f0dafc292e8f4", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/hiring-recon/hiring-recon/SKILL.md"}, "properties": {"repobilityId": "9e56ea4b9fb32764", "scanner": "scanner-primary", "fingerprint": "3b3f0dafc292e8f4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/career_agent/skills/hiring-recon/hiring-recon/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-29a26032319e5569", "level": "warning", "message": {"text": "Agent authority lacks a verifier contract: backend/app/career_agent/skills/interview-coach/interview-coach/SKILL.md"}, "properties": {"repobilityId": "ac644664389988a5", "scanner": "scanner-primary", "fingerprint": "29a26032319e5569", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["agent-instructions", "verification", "skill_file"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/app/career_agent/skills/interview-coach/interview-coach/SKILL.md"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a82e0dc822c3086b", "level": "none", "message": {"text": "Commented-code block (7 lines) in frontend/scripts/check-langchain-sdk-sync.mjs:2"}, "properties": {"repobilityId": "047a7f0b30e22d21", "scanner": "scanner-primary", "fingerprint": "a82e0dc822c3086b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fb5af650f387ab63", "level": "none", "message": {"text": "Commented-code block (7 lines) in frontend/src/app/components/ChatInterface.tsx:104"}, "properties": {"repobilityId": "7c4683a358012e98", "scanner": "scanner-primary", "fingerprint": "fb5af650f387ab63", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3e64b6b8ab981c47", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/app/lib/agentFiles.ts:271"}, "properties": {"repobilityId": "9ab0ab62687ba786", "scanner": "scanner-primary", "fingerprint": "3e64b6b8ab981c47", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-c8bd268d8e0dc60a", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/app/hooks/useChat.ts:51"}, "properties": {"repobilityId": "50e7c121d6220033", "scanner": "scanner-primary", "fingerprint": "c8bd268d8e0dc60a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a80c56b0fc00f073", "level": "note", "message": {"text": "Legacy-named symbol `model_copy` in backend/tests/career_agent/test_middleware_model_override.py:10"}, "properties": {"repobilityId": "fac1eeddf098778c", "scanner": "scanner-primary", "fingerprint": "a80c56b0fc00f073", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-435b109ed67ac80a", "level": "note", "message": {"text": "Legacy-named symbol `page_3_image_23_v2` in backend/tests/career_agent/test_tools.py:289"}, "properties": {"repobilityId": "369f1e00845a7557", "scanner": "scanner-primary", "fingerprint": "435b109ed67ac80a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-dd053e66ea6b431b", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/app/career_agent/agents.py:71"}, "properties": {"repobilityId": "3f6e9e36c464ab87", "scanner": "scanner-primary", "fingerprint": "dd053e66ea6b431b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a462ec3db77fab32", "level": "note", "message": {"text": "Legacy-named symbol `model_copy` in backend/app/career_agent/middleware.py:146"}, "properties": {"repobilityId": "efe4623cdea2fba2", "scanner": "scanner-primary", "fingerprint": "a462ec3db77fab32", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-b662bacb40ebf008", "level": "none", "message": {"text": "Commented-code block (9 lines) in backend/app/career_agent/middleware.py:124"}, "properties": {"repobilityId": "3fab76b8d457a909", "scanner": "scanner-primary", "fingerprint": "b662bacb40ebf008", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "35c64d9666234603", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "458a5c1b44f4979b", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}]}]}