Chore/sign backend images#1
Conversation
Close a trust gap where a registry compromise or MITM could silently replace a backend image: the gallery YAML tells LocalAI which image to pull, but until now nothing verified the bytes came from our CI. Consumer (pkg/oci/cosignverify): - New package using sigstore-go to verify keyless-cosign signatures. - OCI 1.1 referrers API + new bundle format (no legacy :tag.sig). - Policy fields: Issuer / IssuerRegex / Identity / IdentityRegex / NotBefore. NotBefore is the revocation lever — keyless Fulcio certs are ephemeral so revocation is policy-side; advancing not_before in the gallery YAML invalidates every signature predating the cutoff. - TUF trusted root cached process-wide so N backends from one gallery do 1 fetch, not N. Plumbing: - pkg/downloader: ImageVerifier interface + WithImageVerifier option threaded through DownloadFileWithContext. Verification runs between oci.GetImage and oci.ExtractOCIImage, with digest pinning via pinnedImageRef to close the TOCTOU window. Skips the verifier's HEAD when the ref is already digest-pinned. - core/config: Gallery.Verification YAML block. - core/gallery: backendDownloadOptions builds the verifier from the policy; applied on initial URI, mirrors, and tag fallbacks. - core/gallery/upgrade: the upgrade path now routes through the same options builder. A regression Ginkgo spec pins this contract — without it, UpgradeBackend silently bypassed verification. - core/cli: --require-backend-integrity (LOCALAI_REQUIRE_BACKEND_INTEGRITY) escalates missing policy / empty SHA256 from warn to hard-fail. Producer (.github/workflows/backend_merge.yml): - id-token: write at job scope (PR-fork-safe via existing event gate). - sigstore/cosign-installer@v3 pinned to v2.4.1. - After each docker buildx imagetools create, resolve the manifest list digest and run cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1 against repo@digest. --recursive signs the index and every per-arch entry, matching how the consumer resolves a tag to a platform-specific manifest before verifying. Rollout: backend/index.yaml has no `verification:` block yet, so this PR is backward-compatible — installs proceed with a warning until the gallery is populated. Strict mode is opt-in. Assisted-by: claude-code:claude-opus-4-7 [Bash] [Edit] [Read] [Write] [WebSearch] [WebFetch] Signed-off-by: Richard Palethorpe <io@richiejp.com>
…ad of env The previous implementation re-exported the --require-backend-integrity CLI flag into LOCALAI_REQUIRE_BACKEND_INTEGRITY via os.Setenv, then re-read it in core/gallery via os.Getenv. This leaked process state into the gallery package and made the flag impossible to override per-call or test without touching the env. Add RequireBackendIntegrity to ApplicationConfig (with a matching WithRequireBackendIntegrity AppOption) and thread the bool through every install/upgrade path: InstallBackend, InstallBackendFromGallery, UpgradeBackend, InstallModelFromGallery, InstallExternalBackend, ApplyGalleryFromString/File, startup.InstallModels. Worker subcommands gain the same env-bound flag on WorkerFlags so distributed-worker installs honor it consistently with the worker daemon path. Add a forbidigo lint rule against os.Getenv / os.LookupEnv / os.Environ to keep the env-leak pattern from creeping back. Existing offenders (p2p, config loaders, etc.) are baseline-grandfathered by the existing new-from-merge-base: origin/master setting; targeted path exclusions cover the legitimate cases — kong CLI entry points, backend subprocesses, system capability probes, gRPC AUTH_TOKEN inheritance, test gating env vars. Assisted-by: claude-code:claude-opus-4-7 Signed-off-by: Richard Palethorpe <io@richiejp.com>
PR SummaryWhat Changed
Key Changes by AreaSecurity & Verification
CLI & Configuration
Backend Installation
CI/CD
Files Changed
Review Focus Areas
ArchitectureDesign Decisions
Scalability & Extensibility
Risks
|
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. ## Backend OCI Image Signing & Verification Workflow
Complex complexity • Components: backend_merge.yml workflow, cosign signing integration, OCI image verification sequenceDiagram
title Backend OCI Image Signing and Verification Workflow
participant CI as GitHub_Actions_CI
participant Fulcio as Fulcio_CA
participant Registry as OCI_Registry
participant LocalAI as LocalAI_Runtime
participant CosignVerify as Cosign_Verifier
participant Gallery as Gallery_YAML
Note over CI,Gallery: Producer Side - Image Build and Sign
CI->>CI: Build multi-arch manifest list<br/>docker buildx imagetools create
CI->>Fulcio: Request signing certificate<br/>Exchange OIDC token for ephemeral cert
Fulcio-->>CI: Return 10-minute validity certificate<br/>bound to workflow identity
CI->>CI: Resolve digest<br/>docker buildx imagetools inspect
CI->>Registry: cosign sign --recursive --new-bundle-format<br/>Sign manifest list and per-arch entries
Note right of CI: OCI 1.1 referrers storagebr/Sigstore bundle format
Registry-->>CI: Confirm signature stored
Note over CI,Gallery: Consumer Side - Backend Installation
LocalAI->>Gallery: Fetch backend gallery index.yaml
Gallery-->>LocalAI: Return backend entry with verification block<br/>issuer, identity_regex, optional not_before
LocalAI->>Registry: Pull OCI image by tag
Registry-->>LocalAI: Return manifest for target architecture
LocalAI->>CosignVerify: Verify image with Gallery.Verification policy
CosignVerify->>Registry: Discover signature via OCI referrers API
Registry-->>CosignVerify: Return Sigstore bundle
CosignVerify->>CosignVerify: Verify certificate against Fulcio
CosignVerify->>CosignVerify: Match identity_regex against OIDC subject
CosignVerify->>CosignVerify: Check not_before timestamp if set
alt Verification passes
CosignVerify-->>LocalAI: Verification success
LocalAI->>LocalAI: Extract and install backend
else Verification fails or missing
alt LOCALAI_REQUIRE_BACKEND_INTEGRITY is set
CosignVerify-->>LocalAI: Verification failure
LocalAI->>LocalAI: Block installation with error
else Default warning mode
CosignVerify-->>LocalAI: Verification warning
LocalAI->>LocalAI: Log warning and install anyway
end
end
Note over CI,Gallery: Revocation Playbook - Incident Response
alt Compromise detected
Gallery->>Gallery: Advance not_before timestamp<br/>to invalidate pre-compromise signatures
LocalAI->>Gallery: Refresh gallery cache
Gallery-->>LocalAI: Updated policy with new not_before
LocalAI->>CosignVerify: Verify subsequent installs
CosignVerify->>CosignVerify: Reject signatures with IntegratedTime before not_before
end
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
| # 2.2+ is required for --new-bundle-format. | ||
| - name: Install cosign | ||
| if: github.event_name != 'pull_request' | ||
| uses: sigstore/cosign-installer@v3 |
There was a problem hiding this comment.
The new sigstore/cosign-installer step is pinned to the mutable major-version ref @v3 rather than a commit SHA. This action installs the binary that produces every backend image signature; it is the trust root of the entire supply-chain integrity feature being introduced in this PR. A malicious push to the sigstore/cosign-installer repository at the v3 tag would cause CI to install an attacker-controlled cosign binary, which could (a) silently skip signing so no signature is ever produced, (b) sign with a different OIDC identity that passes a permissive consumer policy, or (c) exfiltrate OIDC tokens and registry credentials. All other actions in the file also use floating refs, but the cosign installer is uniquely load-bearing here. Fix: pin to the full commit SHA (e.g. sigstore/cosign-installer@11086d25041f77fe8fe7470324ad114c4a329dd9).
Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: .github/workflows/backend_merge.yml
Lines: 72-72
Issue Type: security-high
Severity: high
Issue Description:
The new `sigstore/cosign-installer` step is pinned to the mutable major-version ref `@v3` rather than a commit SHA. This action installs the binary that produces every backend image signature; it is the trust root of the entire supply-chain integrity feature being introduced in this PR. A malicious push to the `sigstore/cosign-installer` repository at the `v3` tag would cause CI to install an attacker-controlled cosign binary, which could (a) silently skip signing so no signature is ever produced, (b) sign with a different OIDC identity that passes a permissive consumer policy, or (c) exfiltrate OIDC tokens and registry credentials. All other actions in the file also use floating refs, but the cosign installer is uniquely load-bearing here. Fix: pin to the full commit SHA (e.g. `sigstore/cosign-installer@11086d25041f77fe8fe7470324ad114c4a329dd9`).
Current Code:
uses: sigstore/cosign-installer@v3
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
| if requireIntegrity { | ||
| return nil, fmt.Errorf("strict integrity: gallery %q has no verification policy for OCI backend %q (set verification: in the gallery YAML or disable --require-backend-integrity)", | ||
| config.Gallery.Name, config.Name) |
There was a problem hiding this comment.
The strict-integrity error message for OCI backends: 'set verification: in the gallery YAML': is inapplicable and misleading when the install originates from InstallExternalBackend (i.e. local-ai backends install <oci-uri>, --external-backends, or startup ExternalBackends). In that path the GalleryBackend is constructed without any Gallery set (Gallery.Name=="", Gallery.Verification==nil), so strict mode unconditionally returns this error for every external OCI install. The fix hint ('set verification: in the gallery YAML') cannot be followed because there is no gallery entry to edit. Operators who enable LOCALAI_REQUIRE_BACKEND_INTEGRITY=1 and rely on external OCI backends will hit this error with no actionable guidance; the message should distinguish the external-install case and explain that ad-hoc OCI installs must be migrated to a gallery entry with a verification: block.
Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: core/gallery/backends.go
Lines: 129-131
Issue Type: robustness-medium
Severity: medium
Issue Description:
The strict-integrity error message for OCI backends: 'set verification: in the gallery YAML': is inapplicable and misleading when the install originates from `InstallExternalBackend` (i.e. `local-ai backends install <oci-uri>`, `--external-backends`, or startup `ExternalBackends`). In that path the `GalleryBackend` is constructed without any `Gallery` set (Gallery.Name=="", Gallery.Verification==nil), so strict mode unconditionally returns this error for every external OCI install. The fix hint ('set verification: in the gallery YAML') cannot be followed because there is no gallery entry to edit. Operators who enable `LOCALAI_REQUIRE_BACKEND_INTEGRITY=1` and rely on external OCI backends will hit this error with no actionable guidance; the message should distinguish the external-install case and explain that ad-hoc OCI installs must be migrated to a gallery entry with a `verification:` block.
Current Code:
if requireIntegrity {
return nil, fmt.Errorf("strict integrity: gallery %q has no verification policy for OCI backend %q (set verification: in the gallery YAML or disable --require-backend-integrity)",
config.Gallery.Name, config.Name)
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
There was a problem hiding this comment.
After InstallBackendFromGallery succeeds, the code falls through to line 52 still holding the zero-value backend from the failed backends.Get call (the !ok branch installs but never re-fetches). backend.RunFile is the empty string, so filepath.Dir("") returns ".": not "". The guard if backendPath == "" therefore never fires, and the function returns "./llama-cpp-rpc-server" as the binary path. Depending on the working directory when the syscall.Exec runs, this either silently resolves to a wrong binary or fails with a confusing 'no such file' error. The parallel function findBackendPath in worker_backend_common.go correctly calls gallery.ListSystemBackends again after install; findLLamaCPPBackend should do the same.
Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: core/cli/worker/worker_llamacpp.go
Lines: 52-55
Issue Type: functional-medium
Severity: medium
Issue Description:
After `InstallBackendFromGallery` succeeds, the code falls through to line 52 still holding the zero-value `backend` from the failed `backends.Get` call (the `!ok` branch installs but never re-fetches). `backend.RunFile` is the empty string, so `filepath.Dir("")` returns `"."`: not `""`. The guard `if backendPath == ""` therefore never fires, and the function returns `"./llama-cpp-rpc-server"` as the binary path. Depending on the working directory when the syscall.Exec runs, this either silently resolves to a wrong binary or fails with a confusing 'no such file' error. The parallel function `findBackendPath` in `worker_backend_common.go` correctly calls `gallery.ListSystemBackends` again after install; `findLLamaCPPBackend` should do the same.
Current Code:
backendPath := filepath.Dir(backend.RunFile)
if backendPath == "" {
return "", errors.New("llama-cpp backend not found, install it first")
}
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
Security ScanSecurity scan in progress... Analyzing code for:
Results will be posted shortly... |
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity/Verification:
CLI/Config:
Backend Installation:
CI/CD:
Linting:
Files Changed
Review Focus Areas
ArchitectureDesign Decisions:
Scalability & Extensibility:
Risks:
|
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend OCI Image Signing & Verification PipelineComplex complexity • Components: backend_merge.yml workflow, cosign signing integration, sigstore-go verification sequenceDiagram
title Backend OCI Image Signing and Verification Workflow
participant GitHubActions as GitHub Actions CI
participant Fulcio as Fulcio CA
participant OCIRegistry as OCI Registry
participant LocalAI as LocalAI Runtime
participant GalleryYAML as Gallery YAML
participant SigstoreGo as sigstore-go
Note over GitHubActions: Workflow backend_merge.yml triggers on merge to master
GitHubActions->>GitHubActions: Build per-arch images with docker buildx
GitHubActions->>GitHubActions: Create multi-arch manifest list with imagetools create
GitHubActions->>GitHubActions: Resolve digest with imagetools inspect
GitHubActions->>Fulcio: Exchange OIDC token for ephemeral signing certificate
Fulcio-->>GitHubActions: Return 10-minute validity certificate bound to workflow identity
GitHubActions->>OCIRegistry: cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1
Note right of GitHubActions: Signs both manifest list and each per-arch manifest by digest
OCIRegistry-->>GitHubActions: Store signature as OCI 1.1 referrer with Sigstore bundle
LocalAI->>GalleryYAML: Fetch backend gallery index on startup or refresh
GalleryYAML-->>LocalAI: Return backend entries with verification policy block
LocalAI->>LocalAI: Check LOCALAI_REQUIRE_BACKEND_INTEGRITY flag
alt Strict mode enabled
LocalAI->>LocalAI: Fail if verification block missing or verification fails
else Default mode
LocalAI->>LocalAI: Warn if verification block missing but allow install
end
LocalAI->>OCIRegistry: Request backend image by tag
OCIRegistry-->>LocalAI: Return per-arch manifest for current platform
LocalAI->>OCIRegistry: Query OCI referrers API for signature bundle
OCIRegistry-->>LocalAI: Return Sigstore bundle attached to manifest digest
LocalAI->>SigstoreGo: Verify bundle with policy from Gallery YAML
Note right of LocalAI: Policy includes issuer, identity regex, optional not_before timestamp
SigstoreGo-->>LocalAI: Return verification result
alt Verification succeeds
LocalAI->>LocalAI: Extract and install backend image
else Verification fails
alt Strict mode
LocalAI->>LocalAI: Abort installation with error
else Default mode
LocalAI->>LocalAI: Log warning and abort installation
end
end
Note over GalleryYAML: Incident response: advance not_before timestamp to revoke compromised signatures
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
Security ScanSecurity scan in progress... Analyzing code for:
Results will be posted shortly... |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend OCI Image Signing & Verification WorkflowComplex complexity • Components: backend_merge.yml workflow, cosign signing integration, OCI image verification sequenceDiagram
title Backend OCI Image Signing and Verification Workflow
participant GitHubActions as GitHub Actions CI
participant Fulcio as Fulcio CA
participant OCIRegistry as OCI Registry
participant LocalAI as LocalAI Runtime
participant CosignVerifier as Cosign Verifier
participant SigstoreGo as Sigstore Go
Note over GitHubActions,OCIRegistry: Producer Side - Image Signing
GitHubActions->>Fulcio: Request signing certificate via OIDC token exchange
Fulcio-->>GitHubActions: Return ephemeral certificate bound to workflow identity
GitHubActions->>OCIRegistry: Push multi-arch manifest list
GitHubActions->>OCIRegistry: Sign manifest list and per-arch entries recursively with cosign
Note right of GitHubActions: Uses digest not tag to prevent signature orphaning
OCIRegistry-->>GitHubActions: Store signatures as OCI 1.1 referrers in Sigstore bundle format
Note over LocalAI,SigstoreGo: Consumer Side - Image Verification
LocalAI->>LocalAI: Parse gallery YAML with verification block
Note right of LocalAI: Contains issuer, identity regex, optional not_before timestamp
LocalAI->>OCIRegistry: Request backend image by tag
OCIRegistry-->>LocalAI: Return per-arch manifest digest
LocalAI->>CosignVerifier: Verify image with gallery policy
CosignVerifier->>OCIRegistry: Fetch signature bundle via OCI 1.1 referrers API
OCIRegistry-->>CosignVerifier: Return Sigstore bundle
CosignVerifier->>SigstoreGo: Verify signature against policy
SigstoreGo-->>CosignVerifier: Validation result with integrated timestamp
alt Signature valid and within not_before window
CosignVerifier-->>LocalAI: Verification success
LocalAI->>LocalAI: Extract and install backend
else Signature invalid or before not_before cutoff
CosignVerifier-->>LocalAI: Verification failure
alt Strict mode enabled
LocalAI->>LocalAI: Hard error - refuse installation
else Strict mode disabled
LocalAI->>LocalAI: Warning log - install anyway
end
end
Note over LocalAI: Revocation Playbook
Note right of LocalAI: Advance not_before in gallery YAML to invalidate compromised signatures
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend OCI Image Signing & Verification FlowComplex complexity • Components: backend_merge.yml workflow, cosign signing integration, sigstore-go verification sequenceDiagram
title Backend Image Signing and Verification Workflow
participant GHA as GitHub Actions
participant Fulcio as Fulcio CA
participant OCI as OCI Registry
participant LocalAI as LocalAI Instance
participant Gallery as Gallery YAML
participant Sigstore as Sigstore Go
Note over GHA,Fulcio: Producer Side - Image Signing
GHA->>Fulcio: Exchange OIDC token for ephemeral signing certificate
Fulcio-->>GHA: Return 10-minute validity certificate bound to workflow identity
GHA->>OCI: Build and push multi-arch manifest list
GHA->>OCI: cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1 digest
Note over OCI: Signatures stored as OCI 1.1 referrers in Sigstore bundle format
Note over LocalAI,Sigstore: Consumer Side - Image Verification
LocalAI->>Gallery: Fetch backend gallery with verification policy
Gallery-->>LocalAI: Return verification block with issuer, identity_regex, optional not_before
LocalAI->>OCI: Request backend image by tag
OCI-->>LocalAI: Return per-arch manifest digest
LocalAI->>OCI: Query referrers API for Sigstore bundle
OCI-->>LocalAI: Return signature bundle
LocalAI->>Sigstore: Verify bundle against gallery policy
Sigstore->>Sigstore: Check issuer matches token.actions.githubusercontent.com
Sigstore->>Sigstore: Check identity matches workflow regex pattern
Sigstore->>Sigstore: Check signature timestamp against not_before if set
alt Verification passes
Sigstore-->>LocalAI: Verification success
LocalAI->>LocalAI: Extract and install backend
else Verification fails or missing
alt LOCALAI_REQUIRE_BACKEND_INTEGRITY enabled
LocalAI->>LocalAI: Block installation with error
else Default mode
LocalAI->>LocalAI: Install with warning logged
end
end
Note over GHA,LocalAI: Revocation Playbook - Compromise Response
alt Workflow compromise detected
Gallery->>Gallery: Advance not_before timestamp to after compromise window
LocalAI->>Gallery: Refresh gallery on next poll
LocalAI->>LocalAI: Reject signatures with IntegratedTime before not_before
end
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity & Verification
Configuration
CI/CD
CLI & Workers
Files Changed
Review Focus Areas
ArchitectureDesign Decisions
Scalability & Extensibility
Risks
Merge StatusNOT MERGEABLE — PR Score 43/100, below threshold (50)
|
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend OCI Image Signing & Verification WorkflowComplex complexity • Components: backend_merge.yml workflow, cosign signing integration, OCI image verification sequenceDiagram
title: Backend OCI Image Signing and Verification Flow
participant GitHubActions as GitHub Actions CI
participant Fulcio as Fulcio CA
participant OCIRegistry as OCI Registry
participant LocalAI as LocalAI Runtime
participant GalleryYAML as Gallery YAML Policy
participant SigstoreGo as sigstore-go Verifier
Note over GitHubActions: Workflow backend_merge.yml triggers on merge to master
GitHubActions->>GitHubActions: Build per-arch images and create multi-arch manifest list
GitHubActions->>GitHubActions: Resolve manifest list digest with docker buildx imagetools inspect
GitHubActions->>Fulcio: Exchange OIDC token for ephemeral signing certificate
Fulcio-->>GitHubActions: Return Fulcio certificate bound to workflow identity
GitHubActions->>OCIRegistry: cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1 registry/repo@digest
Note over GitHubActions: Signs both manifest list and each per-arch entry
OCIRegistry-->>GitHubActions: Store Sigstore bundle as OCI 1.1 referrer
Note over LocalAI: User runs local-ai backends install or local-ai run
LocalAI->>GalleryYAML: Load backend gallery with verification block
GalleryYAML-->>LocalAI: Return policy: issuer, identity_regex, optional not_before
LocalAI->>OCIRegistry: Pull backend image by tag
OCIRegistry-->>LocalAI: Return per-arch manifest
LocalAI->>OCIRegistry: Discover signature via OCI 1.1 referrers API
OCIRegistry-->>LocalAI: Return Sigstore bundle
LocalAI->>SigstoreGo: Verify bundle against policy
SigstoreGo->>SigstoreGo: Check certificate issuer matches policy
SigstoreGo->>SigstoreGo: Check OIDC identity matches identity_regex
SigstoreGo->>SigstoreGo: Check signature timestamp against not_before if set
SigstoreGo-->>LocalAI: Verification result
alt Verification succeeds
LocalAI->>LocalAI: Extract and install backend image
else Verification fails or missing
alt LOCALAI_REQUIRE_BACKEND_INTEGRITY is set
LocalAI->>LocalAI: Hard error, refuse installation
else Default mode
LocalAI->>LocalAI: Log warning, proceed with installation
end
end
Note over GitHubActions,LocalAI: Revocation scenario: compromise detected
GitHubActions->>GalleryYAML: Advance not_before timestamp to invalidate old signatures
LocalAI->>GalleryYAML: Refresh gallery on next poll
GalleryYAML-->>LocalAI: Updated policy with new not_before
LocalAI->>SigstoreGo: Re-verify existing signatures against new policy
SigstoreGo->>SigstoreGo: Old signatures now fail timestamp check
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
Security Scan Summary
No critical security issues detected Scan completed in 36.6sSecurity scan powered by Codity.ai |
License Compliance Scan
Weak copyleft licenses found - verify compatibility Some packages have unknown licenses - manual review required Medium Risk Licenses - 6 packages(MPL-2.0 OR Apache-2.0) (1 packages):
MPL-2.0 (5 packages):
Unknown Licenses - 117 packages
...and 97 more Powered by Codity.ai · Docs |
Code Quality Report — utkxrsh26/LocalAI · PR #1Scanned: 2026-06-02 19:08 UTC | Score: 21/100 | Provider: github Executive Summary
Top Findings[CQ-LLM-003]
|
| File | Critical | High | Medium | Low | Total |
|---|---|---|---|---|---|
.agents/adding-backends.md |
0 | 0 | 0 | 1 | 1 |
.agents/backend-signing.md |
0 | 0 | 0 | 3 | 3 |
.github/workflows/backend_merge.yml |
0 | 1 | 3 | 0 | 4 |
.golangci.yml |
0 | 0 | 0 | 1 | 1 |
AGENTS.md |
0 | 0 | 0 | 1 | 1 |
core/application/startup.go |
0 | 0 | 0 | 4 | 4 |
core/backend/llm.go |
0 | 0 | 0 | 1 | 1 |
core/cli/backends.go |
0 | 0 | 0 | 6 | 6 |
core/cli/models.go |
0 | 0 | 0 | 2 | 2 |
core/cli/run.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker.go |
0 | 0 | 0 | 5 | 5 |
core/cli/worker/worker_backend_common.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_llamacpp.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_mlx_common.go |
0 | 0 | 0 | 1 | 1 |
core/config/gallery.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/backends.go |
0 | 0 | 0 | 7 | 7 |
core/gallery/backends_test.go |
0 | 0 | 0 | 3 | 3 |
core/gallery/models.go |
0 | 0 | 0 | 2 | 2 |
core/gallery/models_test.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/upgrade.go |
0 | 0 | 0 | 3 | 3 |
core/services/galleryop/backends.go |
0 | 0 | 0 | 2 | 2 |
core/services/galleryop/managers_local.go |
0 | 0 | 0 | 1 | 1 |
core/services/galleryop/models.go |
0 | 0 | 0 | 9 | 9 |
core/services/worker/config.go |
0 | 0 | 0 | 5 | 5 |
core/services/worker/install.go |
0 | 0 | 0 | 2 | 2 |
core/startup/model_preload.go |
0 | 0 | 0 | 4 | 4 |
core/startup/model_preload_test.go |
0 | 0 | 0 | 2 | 2 |
go.mod |
0 | 0 | 0 | 6 | 6 |
go.sum |
0 | 0 | 0 | 41 | 41 |
pkg/downloader/pinned_ref_internal_test.go |
0 | 0 | 0 | 2 | 2 |
pkg/downloader/uri.go |
0 | 0 | 0 | 2 | 2 |
pkg/oci/cosignverify/bundle.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/notbefore_internal_test.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/verify_test.go |
0 | 0 | 0 | 2 | 2 |
Recommendations
- Resolve High severity issues, especially error handling gaps and performance bottlenecks.
- Run automated tests after applying fixes to verify no regressions.
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend Image Signing & Verification WorkflowComplex complexity • Components: backend_merge.yml workflow, cosign signing integration, OCI image verification sequenceDiagram
title Backend OCI Image Signing and Verification Workflow
participant CI as GitHub_Actions_CI
participant Fulcio as Fulcio_CA
participant Registry as OCI_Registry
participant LocalAI as LocalAI_Instance
participant Verifier as Cosign_Verifier
participant Gallery as Gallery_YAML
CI->>CI: Build per-arch images
CI->>CI: Create multi-arch manifest list
CI->>CI: Resolve digest from tag
CI->>Fulcio: Exchange OIDC token for signing cert
Fulcio-->>CI: Return ephemeral certificate
CI->>Registry: Push image manifest
CI->>Registry: cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1 digest
Registry-->>CI: Store signature as OCI 1.1 referrer
LocalAI->>Gallery: Fetch backend/index.yaml
Gallery-->>LocalAI: Return verification policy with issuer, identity_regex, not_before
LocalAI->>Registry: Request backend image by tag
Registry-->>LocalAI: Return per-arch manifest
LocalAI->>Verifier: Verify image with policy
Verifier->>Registry: Discover signature via referrers API
Registry-->>Verifier: Return Sigstore bundle
Verifier->>Verifier: Validate signature with sigstore-go
alt Signature valid and matches policy
Verifier-->>LocalAI: Verification success
LocalAI->>Registry: Pull and extract image
Registry-->>LocalAI: Image layers
else Signature invalid or policy mismatch
Verifier-->>LocalAI: Verification failed
alt LOCALAI_REQUIRE_BACKEND_INTEGRITY enabled
LocalAI->>LocalAI: Hard error, refuse installation
else Default mode
LocalAI->>LocalAI: Log warning, allow installation
end
end
note over CI,Registry: Producer side: Keyless signing with cosign in backend_merge.yml
note over LocalAI,Gallery: Consumer side: Policy-driven verification with optional strict mode
note over Gallery: Revocation via not_before timestamp advances to invalidate compromised signatures
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity & Verification: New Configuration: Backend Installation: All install/upgrade paths now pass Build & Registry: Makefile adds new Golang backends. Code Quality: Files Changed
Review Focus Areas
ArchitectureDesign Decisions: Keyless signing chosen over static keys to eliminate key management burden. OCI 1.1 referrers API used instead of tag-based discovery to avoid race conditions and enable multi-arch verification. Scalability & Extensibility: Verification is pluggable via Risks:
Merge StatusNOT MERGEABLE — PR Score 41/100, below threshold (50)
|
Workflow DiagramsAutomatically generated sequence diagrams showing the workflows in this PR 1. Backend OCI Image Signing & Verification WorkflowComplex complexity • Components: backend_merge.yml workflow, cosign keyless signing, OCI image verification sequenceDiagram
title Backend OCI Image Signing and Verification Workflow
participant GitHubActions as GitHub Actions CI
participant Fulcio as Fulcio CA
participant OCIRegistry as OCI Registry
participant LocalAI as LocalAI Runtime
participant SigstoreGo as Sigstore Go Verifier
participant GalleryYAML as Gallery YAML Policy
Note over GitHubActions,OCIRegistry: Producer Side - Image Signing
GitHubActions->>Fulcio: Request signing certificate with OIDC token
Fulcio-->>GitHubActions: Return ephemeral certificate bound to workflow identity
GitHubActions->>OCIRegistry: Push multi-arch manifest list
GitHubActions->>OCIRegistry: cosign sign --recursive --new-bundle-format --registry-referrers-mode=oci-1-1
Note right of GitHubActions: Signs both manifest list and per-arch entries by digest
OCIRegistry-->>GitHubActions: Store signatures as OCI 1.1 referrers
Note over LocalAI,GalleryYAML: Consumer Side - Image Verification
LocalAI->>GalleryYAML: Load backend gallery with verification block
GalleryYAML-->>LocalAI: Return policy issuer identity_regex not_before
LocalAI->>OCIRegistry: Request backend image by tag
OCIRegistry-->>LocalAI: Return per-arch manifest digest
LocalAI->>OCIRegistry: Query OCI referrers API for signature bundle
OCIRegistry-->>LocalAI: Return Sigstore bundle
LocalAI->>SigstoreGo: Verify signature with gallery policy
SigstoreGo->>SigstoreGo: Check certificate issuer matches policy issuer
SigstoreGo->>SigstoreGo: Check identity matches identity_regex
SigstoreGo->>SigstoreGo: Check signature timestamp against not_before
alt Verification succeeds
SigstoreGo-->>LocalAI: Verification passed
LocalAI->>LocalAI: Extract and install backend
else Verification fails or missing
alt Strict mode enabled LOCALAI_REQUIRE_BACKEND_INTEGRITY equals 1
SigstoreGo-->>LocalAI: Verification failed
LocalAI->>LocalAI: Hard error refuse installation
else Strict mode disabled
SigstoreGo-->>LocalAI: Verification warning
LocalAI->>LocalAI: Log warning install anyway
end
end
Note over GitHubActions,GalleryYAML: Revocation Playbook
alt Compromise detected
GalleryYAML->>GalleryYAML: Advance not_before timestamp
LocalAI->>GalleryYAML: Refresh gallery policy
GalleryYAML-->>LocalAI: Updated not_before
LocalAI->>SigstoreGo: Verify old signature
SigstoreGo->>SigstoreGo: Signature timestamp before not_before
SigstoreGo-->>LocalAI: Verification failed signature revoked
end
Note: Diagrams show detected patterns only. Complex workflows may require manual review. |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity & Verification:
Configuration:
CLI:
CI/CD:
Code Quality:
Files Changed
Review Focus Areas
ArchitectureDesign Decisions:
Scalability & Extensibility:
Risks:
Merge StatusNOT MERGEABLE — PR Score 23/100, below threshold (50)
|
| return "", err | ||
| } | ||
| err := gallery.InstallBackendFromGallery(context.Background(), gals, systemState, ml, llamaCPPGalleryName, nil, true) | ||
| err := gallery.InstallBackendFromGallery(context.Background(), gals, systemState, ml, llamaCPPGalleryName, nil, true, requireIntegrity) |
There was a problem hiding this comment.
After InstallBackendFromGallery succeeds, findLLamaCPPBackend continues to use the stale backend variable that was captured before installation: at the point where backends.Get(llamaCPPGalleryName) returned ok == false. The zero-value struct has RunFile == "", so filepath.Dir("") returns "." and the gRPC server binary is looked up in the current working directory, causing the worker to fail to start.
The sibling helper findBackendPath in worker_backend_common.go handles this correctly by calling gallery.ListSystemBackends again and re-calling backends.Get after a successful install. findLLamaCPPBackend must do the same: after the error-free return from InstallBackendFromGallery, re-list the system backends and re-fetch the entry before reading backend.RunFile.
Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: core/cli/worker/worker_llamacpp.go
Lines: 46-46
Issue Type: functional-high
Severity: high
Issue Description:
After `InstallBackendFromGallery` succeeds, `findLLamaCPPBackend` continues to use the stale `backend` variable that was captured *before* installation: at the point where `backends.Get(llamaCPPGalleryName)` returned `ok == false`. The zero-value struct has `RunFile == ""`, so `filepath.Dir("")` returns `"."` and the gRPC server binary is looked up in the current working directory, causing the worker to fail to start.
The sibling helper `findBackendPath` in `worker_backend_common.go` handles this correctly by calling `gallery.ListSystemBackends` again and re-calling `backends.Get` after a successful install. `findLLamaCPPBackend` must do the same: after the error-free return from `InstallBackendFromGallery`, re-list the system backends and re-fetch the entry before reading `backend.RunFile`.
Current Code:
err := gallery.InstallBackendFromGallery(context.Background(), gals, systemState, ml, llamaCPPGalleryName, nil, true, requireIntegrity)
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
Security Scan Summary
No critical security issues detected Scan completed in 30.9sSecurity scan powered by Codity.ai |
License Compliance Scan
Weak copyleft licenses found - verify compatibility Some packages have unknown licenses - manual review required Medium Risk Licenses - 6 packages(MPL-2.0 OR Apache-2.0) (1 packages):
MPL-2.0 (5 packages):
Unknown Licenses - 139 packages
...and 119 more Powered by Codity.ai · Docs |
Code Quality Report — utkxrsh26/LocalAI · PR #1Scanned: 2026-06-02 23:50 UTC | Score: 22/100 | Provider: github Executive Summary
Top Findings[CQ-LLM-003]
|
| File | Critical | High | Medium | Low | Total |
|---|---|---|---|---|---|
.agents/adding-backends.md |
0 | 0 | 0 | 2 | 2 |
.agents/backend-signing.md |
0 | 0 | 0 | 2 | 3 |
.github/workflows/backend_merge.yml |
0 | 0 | 3 | 0 | 3 |
.golangci.yml |
0 | 0 | 0 | 1 | 1 |
AGENTS.md |
0 | 0 | 0 | 1 | 1 |
core/application/startup.go |
0 | 0 | 0 | 4 | 4 |
core/backend/llm.go |
0 | 0 | 0 | 1 | 1 |
core/cli/backends.go |
0 | 0 | 0 | 6 | 6 |
core/cli/models.go |
0 | 0 | 0 | 2 | 2 |
core/cli/run.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker.go |
0 | 0 | 0 | 5 | 5 |
core/cli/worker/worker_backend_common.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_llamacpp.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_mlx_common.go |
0 | 0 | 0 | 1 | 1 |
core/config/gallery.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/backends.go |
0 | 0 | 0 | 7 | 7 |
core/gallery/backends_test.go |
0 | 0 | 0 | 3 | 3 |
core/gallery/models.go |
0 | 0 | 0 | 2 | 2 |
core/gallery/models_test.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/upgrade.go |
0 | 0 | 0 | 3 | 3 |
core/services/galleryop/backends.go |
0 | 0 | 0 | 2 | 2 |
core/services/galleryop/managers_local.go |
0 | 0 | 0 | 1 | 1 |
core/services/galleryop/models.go |
0 | 0 | 0 | 9 | 9 |
core/services/worker/config.go |
0 | 0 | 0 | 5 | 5 |
core/services/worker/install.go |
0 | 0 | 0 | 2 | 2 |
core/startup/model_preload.go |
0 | 0 | 0 | 4 | 4 |
core/startup/model_preload_test.go |
0 | 0 | 0 | 2 | 2 |
go.mod |
0 | 0 | 0 | 6 | 6 |
go.sum |
0 | 0 | 0 | 41 | 41 |
pkg/downloader/pinned_ref_internal_test.go |
0 | 0 | 0 | 2 | 2 |
pkg/downloader/uri.go |
0 | 0 | 0 | 2 | 2 |
pkg/oci/cosignverify/bundle.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/notbefore_internal_test.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/verify_test.go |
0 | 0 | 0 | 2 | 2 |
Recommendations
- Run automated tests after applying fixes to verify no regressions.
|
@codity review |
|
PR review started! Estimated time: 5-10 minutes. Custom Review Instructions Detectedsource: context file (CLAUDE.md / .cursorrules)
# LocalAI Agent Instructions
This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the `.agents/` directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.
Human contributors: see [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.
## Policy for AI-Assisted Contributions
LocalAI follows the Linux kernel project's [guidelines for
...
Learn MoreAsk Codity questions: Mention Trigger a manual review: Comment Generate unit tests: Comment Run security scan again: Comment |
| ' <<< "$DOCKER_METADATA_OUTPUT_JSON") | ||
| digest=$(docker buildx imagetools inspect "$first_tag" --format '{{.Manifest.Digest}}') | ||
| # --recursive walks the list and signs every per-arch entry | ||
| # too — clients that resolve a tag to a platform-specific | ||
| # manifest before checking signatures need the per-arch | ||
| # signatures, not just the list-level one. | ||
| cosign sign --yes --recursive \ | ||
| --new-bundle-format \ |
There was a problem hiding this comment.
The quay.io signing block assigns digest from docker buildx imagetools inspect but never validates that the result is non-empty before handing it to cosign sign. If the inspect call fails silently (e.g., a transient registry error, an empty format template result, or a race where the pushed tag is momentarily unresolvable), the shell assignment succeeds with an empty string and the subsequent command becomes cosign sign ... "quay.io/go-skynet/local-ai-backends@". Cosign will reject the malformed reference with an opaque error rather than a clear 'digest is empty' message, making the failure hard to diagnose in CI. Worse, if cosign were to interpret an empty digest as 'sign whatever the tag currently resolves to', the wrong manifest could be signed. A one-line guard makes the intent explicit and surfaces the root cause immediately.
Also reported at: .github/workflows/backend_merge.yml L179–L188
Suggested fix
digest=$(docker buildx imagetools inspect "$first_tag" --format '{{.Manifest.Digest}}')
if [ -z "$digest" ]; then
echo "ERROR: failed to resolve manifest-list digest for ${first_tag}; cannot sign" >&2
exit 1
fi
# --recursive walks the list and signs every per-arch entry
# too — clients that resolve a tag to a per-arch manifest before
# checking signatures need the per-arch signatures, not just the list-level one.
cosign sign --yes --recursive \
--new-bundle-format \
--registry-referrers-mode=oci-1-1 \
"quay.io/go-skynet/local-ai-backends@${digest}"Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: .github/workflows/backend_merge.yml
Lines: 149-156
Issue Type: robustness-high
Severity: high
Issue Description:
The quay.io signing block assigns `digest` from `docker buildx imagetools inspect` but never validates that the result is non-empty before handing it to `cosign sign`. If the inspect call fails silently (e.g., a transient registry error, an empty format template result, or a race where the pushed tag is momentarily unresolvable), the shell assignment succeeds with an empty string and the subsequent command becomes `cosign sign ... "quay.io/go-skynet/local-ai-backends@"`. Cosign will reject the malformed reference with an opaque error rather than a clear 'digest is empty' message, making the failure hard to diagnose in CI. Worse, if cosign were to interpret an empty digest as 'sign whatever the tag currently resolves to', the wrong manifest could be signed. A one-line guard makes the intent explicit and surfaces the root cause immediately.
_Also reported at: `.github/workflows/backend_merge.yml` L179–L188_
Current Code:
digest=$(docker buildx imagetools inspect "$first_tag" --format '{{.Manifest.Digest}}')
# --recursive walks the list and signs every per-arch entry
# too — clients that resolve a tag to a per-arch manifest before
# checking signatures need the per-arch signatures, not just the list-level one.
cosign sign --yes --recursive \
--new-bundle-format \
--registry-referrers-mode=oci-1-1 \
"quay.io/go-skynet/local-ai-backends@${digest}"
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
| // newGalleryVerifier constructs a cosignverify.Verifier from the gallery | ||
| // policy. Parses NotBefore (RFC3339) here so YAML errors surface at install | ||
| // time rather than during signature verification. | ||
| func newGalleryVerifier(p *config.GalleryVerification) (*cosignverify.Verifier, error) { | ||
| pol := cosignverify.Policy{ | ||
| Issuer: p.Issuer, | ||
| IssuerRegex: p.IssuerRegex, | ||
| Identity: p.Identity, | ||
| IdentityRegex: p.IdentityRegex, | ||
| } | ||
| if p.NotBefore != "" { | ||
| t, err := time.Parse(time.RFC3339, p.NotBefore) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("not_before %q: %w", p.NotBefore, err) | ||
| } | ||
| pol.NotBefore = t | ||
| } | ||
| return cosignverify.NewVerifier(pol, nil, nil) | ||
| } | ||
|
|
There was a problem hiding this comment.
newGalleryVerifier constructs a cosignverify.Policy from the gallery YAML fields without validating that the policy contains at least one non-empty identity constraint. The backend-signing.md documentation explicitly warns: "Without this, any image signed by anyone with a Fulcio cert would pass: the regex is what makes a signature mean 'produced by our CI'." A gallery operator who writes verification: {} (empty block, e.g. to enable the non-nil check that gates verification) or verification:\n not_before: "2026-01-01T00:00:00Z" (only a revocation cutoff, no identity pin) will get a verifier that accepts any valid Fulcio-signed OCI image as a legitimate LocalAI backend. The nil-pointer guard in backendDownloadOptions (config.Gallery.Verification != nil) considers such a block as "has a policy" and proceeds to build the verifier, giving a false sense of security. Validate that at least one of Issuer/IssuerRegex AND at least one of Identity/IdentityRegex are non-empty before calling cosignverify.NewVerifier.
Suggested fix
func newGalleryVerifier(p *config.GalleryVerification) (*cosignverify.Verifier, error) {
if p.Issuer == "" && p.IssuerRegex == "" {
return nil, fmt.Errorf("gallery verification policy must specify at least one of issuer or issuer_regex")
}
if p.Identity == "" && p.IdentityRegex == "" {
return nil, fmt.Errorf("gallery verification policy must specify at least one of identity or identity_regex")
}
pol := cosignverify.Policy{
Issuer: p.Issuer,
IssuerRegex: p.IssuerRegex,
Identity: p.Identity,
IdentityRegex: p.IdentityRegex,
}Prompt for AI assistance
Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:
You are an expert bash developer with deep knowledge of security, performance, and best practices.
### Context
File: core/gallery/backends.go
Lines: 157-176
Issue Type: security-high
Severity: high
Issue Description:
newGalleryVerifier constructs a cosignverify.Policy from the gallery YAML fields without validating that the policy contains at least one non-empty identity constraint. The backend-signing.md documentation explicitly warns: "Without this, any image signed by *anyone* with a Fulcio cert would pass: the regex is what makes a signature mean 'produced by our CI'." A gallery operator who writes `verification: {}` (empty block, e.g. to enable the non-nil check that gates verification) or `verification:\n not_before: "2026-01-01T00:00:00Z"` (only a revocation cutoff, no identity pin) will get a verifier that accepts any valid Fulcio-signed OCI image as a legitimate LocalAI backend. The nil-pointer guard in backendDownloadOptions (`config.Gallery.Verification != nil`) considers such a block as "has a policy" and proceeds to build the verifier, giving a false sense of security. Validate that at least one of Issuer/IssuerRegex AND at least one of Identity/IdentityRegex are non-empty before calling cosignverify.NewVerifier.
Current Code:
func newGalleryVerifier(p *config.GalleryVerification) (*cosignverify.Verifier, error) {
pol := cosignverify.Policy{
Issuer: p.Issuer,
IssuerRegex: p.IssuerRegex,
Identity: p.Identity,
IdentityRegex: p.IdentityRegex,
}
---
### Instructions
1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed
### Constraints
- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready
---
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity/Verification: New CLI/Config: New Gallery/Installation: CI/CD: Backend merge workflow now signs multi-arch manifests with Files Changed
Review Focus Areas
ArchitectureDesign Decisions: Verification runs before any disk writes to prevent tampered bytes from reaching storage. The Scalability & Extensibility: Out of scope for this PR. The verification policy struct can extend to support additional signature schemes beyond cosign. Risks:
|
Security ScanSecurity scan in progress... Analyzing code for:
Results will be posted shortly... |
|
@codity review |
PR SummaryWhat Changed
Key Changes by AreaSecurity/Verification: New CLI/Config: CI/CD: Gallery: New Files Changed
Review Focus Areas
ArchitectureDesign Decisions: Keyless signing chosen over key-based to eliminate key management burden; OCI 1.1 referrers avoid tag clutter. Digest pinning prevents race conditions between manifest verification and layer download. Scalability & Extensibility: Cloud KMS providers (AWS, Azure, GCP, Vault) added to dependencies but not yet wired to verification logic. Out of scope for this PR. Risks:
Merge StatusNOT MERGEABLE — PR Score 14/100, below threshold (50)
|
Security Scan Summary
No critical security issues detected Scan completed in 34.3sSecurity scan powered by Codity.ai |
License Compliance Scan
Weak copyleft licenses found - verify compatibility Some packages have unknown licenses - manual review required Medium Risk Licenses - 6 packages(MPL-2.0 OR Apache-2.0) (1 packages):
MPL-2.0 (5 packages):
Unknown Licenses - 104 packages
...and 84 more Powered by Codity.ai · Docs |
Code Quality Report — utkxrsh26/LocalAI · PR #1Scanned: 2026-06-04 12:44 UTC | Score: 23/100 | Provider: github Executive Summary
Top Findings[CQ-LLM-002]
|
| File | Critical | High | Medium | Low | Total |
|---|---|---|---|---|---|
.agents/adding-backends.md |
0 | 0 | 0 | 2 | 2 |
.agents/backend-signing.md |
0 | 0 | 1 | 2 | 3 |
.github/workflows/backend_merge.yml |
0 | 0 | 2 | 0 | 2 |
.golangci.yml |
0 | 0 | 0 | 1 | 1 |
AGENTS.md |
0 | 0 | 0 | 1 | 1 |
core/application/startup.go |
0 | 0 | 0 | 4 | 4 |
core/backend/llm.go |
0 | 0 | 0 | 1 | 1 |
core/cli/backends.go |
0 | 0 | 0 | 6 | 6 |
core/cli/models.go |
0 | 0 | 0 | 2 | 2 |
core/cli/run.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker.go |
0 | 0 | 0 | 5 | 5 |
core/cli/worker/worker_backend_common.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_llamacpp.go |
0 | 0 | 0 | 1 | 1 |
core/cli/worker/worker_mlx_common.go |
0 | 0 | 0 | 1 | 1 |
core/config/gallery.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/backends.go |
0 | 0 | 0 | 7 | 7 |
core/gallery/backends_test.go |
0 | 0 | 0 | 3 | 3 |
core/gallery/models.go |
0 | 0 | 0 | 2 | 2 |
core/gallery/models_test.go |
0 | 0 | 0 | 1 | 1 |
core/gallery/upgrade.go |
0 | 0 | 0 | 3 | 3 |
core/services/galleryop/backends.go |
0 | 0 | 0 | 2 | 2 |
core/services/galleryop/managers_local.go |
0 | 0 | 0 | 1 | 1 |
core/services/galleryop/models.go |
0 | 0 | 0 | 9 | 9 |
core/services/worker/config.go |
0 | 0 | 0 | 5 | 5 |
core/services/worker/install.go |
0 | 0 | 0 | 2 | 2 |
core/startup/model_preload.go |
0 | 0 | 0 | 4 | 4 |
core/startup/model_preload_test.go |
0 | 0 | 0 | 2 | 2 |
go.mod |
0 | 0 | 0 | 6 | 6 |
go.sum |
0 | 0 | 0 | 41 | 41 |
pkg/downloader/pinned_ref_internal_test.go |
0 | 0 | 0 | 2 | 2 |
pkg/downloader/uri.go |
0 | 0 | 0 | 2 | 2 |
pkg/oci/cosignverify/bundle.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/notbefore_internal_test.go |
0 | 0 | 0 | 1 | 1 |
pkg/oci/cosignverify/verify_test.go |
0 | 0 | 0 | 2 | 2 |
Recommendations
- Run automated tests after applying fixes to verify no regressions.
Description
This PR fixes #
Notes for Reviewers
Signed commits