Skip to content

Remove start_serena_server.sh and Serena local mode (supply chain risk)#19072

Merged
pelikhan merged 6 commits intomainfrom
copilot/fix-security-supply-chain-risk
Mar 1, 2026
Merged

Remove start_serena_server.sh and Serena local mode (supply chain risk)#19072
pelikhan merged 6 commits intomainfrom
copilot/fix-security-supply-chain-risk

Conversation

Copy link
Contributor

Copilot AI commented Mar 1, 2026

actions/setup/sh/start_serena_server.sh fetched and executed code from the tip of github.com/oraios/serena at runtime with no version pin — a direct supply chain attack vector. Only Docker container mode is supported for Serena; the local/uvx mode was dead code and has been removed entirely.

Changes

  • Deleted actions/setup/sh/start_serena_server.sh — the unpinned uvx --from git+https://github.com/oraios/serena script
  • Removed generateSerenaLocalModeSteps() from mcp_serena_config.go and its call in mcp_setup_generator.go
  • Removed Mode field from SerenaToolConfig (tools_types.go, tools_parser.go) — local mode is no longer a valid option
  • Removed isSerenaInLocalMode() helper and all local-mode code paths: HTTP transport config in mcp_config_serena_renderer.go and mcp_renderer.go, GH_AW_SERENA_PORT env var injection in mcp_environment.go, uvx/language runtime detection in runtime_detection.go, and strict-mode rejection in strict_mode_validation.go
  • Simplified collectDockerImages in docker.go — always adds the Serena container image (no local-mode exception)
  • Updated JSON schema (main_workflow_schema.json) — Serena mode enum restricted to ["docker"] only
  • Updated documentation (frontmatter-full.md) — removed mention of "local" mode
  • Removed all tests covering local mode behavior
  • Added serena-local-to-docker codemod (pkg/cli/codemod_serena_local_mode.go) — automatically replaces tools.serena.mode: local with tools.serena.mode: docker in existing workflow files when gh aw fix is run; preserves inline comments and only targets the tools.serena block
Original prompt

This section details on the original issue you should resolve

<issue_title>🚨 [SECURITY] Security Red Team Findings - 2026-03-01 (Weekly Full Scan)</issue_title>
<issue_description>### Scan Overview

The weekly full security red team scan (Sunday, 2026-03-01) completed analysis of 459 files across actions/setup/js and actions/setup/sh using all 6 rotating techniques. 1 supply chain risk was identified requiring human review.

Metric Value
Scan Mode Weekly Full (Sunday)
Technique full-comprehensive (all 6)
JS files scanned 425 .cjs
SH files scanned 34 .sh
Findings 1
Run §22545588649

Finding 1: Unpinned External Supply Chain Dependency

Severity: Medium-High
Category: SUPPLY_CHAIN_RISK
File: actions/setup/sh/start_serena_server.sh:24

Code

nohup env DEBUG="*" uvx --from git+https://github.com/oraios/serena serena start-mcp-server \
  --transport streamable-http \
  --port "\$\{GH_AW_SERENA_PORT}" \
  --context copilot \
  --project "\$\{GITHUB_WORKSPACE}" \
  >> /tmp/gh-aw/serena/logs/server.log 2>&1 &
```

#### Risk Description

This line fetches and executes code **directly from the tip of the default branch** of an external repository (`oraios/serena`) at runtime, without pinning to a specific commit SHA or version tag. This creates a supply chain attack vector:

1. **No version pinning**: `git+https://github.com/oraios/serena` fetches the latest commit. Any compromise of that repo (malicious push, maintainer account takeover) would immediately execute arbitrary code on the next workflow run.
2. **Full environment access**: The spawned process has access to `GITHUB_WORKSPACE` and all environment variables in scope, which may include secrets injected by GitHub Actions.
3. **Background execution**: `nohup ... &` makes the process harder to monitor and kill.
4. **DEBUG="*" verbose logging**: All debug output (which could include secrets or sensitive data) is written to `/tmp/gh-aw/serena/logs/server.log`.

#### Forensics Analysis

| Field | Value |
|-------|-------|
| Commit | `5fa65dd` |
| Author | Copilot (`198982749+Copilot@users.noreply.github.com`) |
| Committer | GitHub |
| Date | 2026-03-01 05:17:11 -0800 |
| PR | github/gh-aw#19035 — "Warn on malformed `#aw_*` references in body text" |
| File status | **Newly added** in this commit |

The file `start_serena_server.sh` was introduced for the first time in the most recent commit (`5fa65dd`) as part of PR github/gh-aw#19035. The PR title is about malformed `#aw_*` references — the addition of this script is a side-effect change that may warrant additional review.

<details>
<summary><b>View Full git blame Output</b></summary>

```
5fa65dd15a71cec00f2d14c664467154d343d875 24 24 1
author Copilot
author-mail <198982749+Copilot@users.noreply.github.com>
author-time 1772371031
author-tz -0800
committer GitHub
committer-mail (noreply@github.com)
committer-time 1772371031
committer-tz -0800
summary Warn on malformed `#aw_*` references in body text (#19035)
boundary
filename actions/setup/sh/start_serena_server.sh
        nohup env DEBUG="*" uvx --from git+https://github.com/oraios/serena serena start-mcp-server \

Remediation Tasks

@pelikhan Please review and act on the following:

  • Task 1: Verify that github.com/oraios/serena is an intentionally chosen and trusted third-party dependency

    • Confirm the oraios organization and repository are trusted for use in CI/CD workflows
    • Review the repository's security posture, ownership, and maintenance status
  • Task 2: Pin to a specific version tag or commit SHA

    • Replace git+https://github.com/oraios/serena with a pinned reference such as git+https://github.com/oraios/serena@v1.2.3 or a specific commit SHA
    • Example: uvx --from git+https://github.com/oraios/serena@(SHA) serena start-mcp-server
  • Task 3: Assess whether the DEBUG="*" environment variable is safe to use in CI

    • Confirm debug output in /tmp/gh-aw/serena/logs/server.log does not expose secrets or tokens
    • Consider removing DEBUG="*" in production or scoping it to specific debug namespaces
  • Task 4: Review PR Warn on malformed #aw_* references in body text #19035 to confirm the addition of start_serena_server.sh was intentional

    • The script was added in a commit whose title describes a different feature (#aw_* reference warnings)
    • Confirm this is expected scope for that PR

All-Clear Items

View Passing Checks (Pattern Analysis)
Check Status
Secret exfiltration patterns ✅ None found
eval/exec with external input ✅ Test files only (sandboxed)
Obfuscated code (base64/hex) ✅ Only legitimate API encoding
Dangerous file ops with dynamic paths ✅ All paths are controlled
Suspicious network domains ✅ None found
...

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.



✨ PR Review Safe Output Test - Run 22547662764

💥 [THE END] — Illustrated by Smoke Claude


Changeset

  • Type: patch
  • Description: Removed the insecure Serena local-mode option and script, and added a codemod that switches tools.serena.mode: local to docker so existing workflows continue to work.

Generated by Changeset Generator for issue #19072

Warning

⚠️ Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • codeload.github.com
  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "codeload.github.com"
    - "github.com"

See Network Configuration for more information.

…isk)

The script used unpinned uvx from git+https://github.com/oraios/serena
without version pinning. As confirmed by @pelikhan, only Docker container
mode is supported for Serena - the local mode using uvx is dead code.

- Delete actions/setup/sh/start_serena_server.sh
- Remove generateSerenaLocalModeSteps() from mcp_serena_config.go
- Remove the call to it in mcp_setup_generator.go
- Update test assertions in importable_tools_test.go

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix supply chain risk identified in security scan Remove dead start_serena_server.sh (supply chain risk) Mar 1, 2026
@pelikhan
Copy link
Contributor

pelikhan commented Mar 1, 2026

@copilot review front matter and remove option to start Serena locally

Remove all support for the 'local' mode in the Serena tool configuration.
Only Docker container mode is supported for starting Serena.

- Remove Mode field from SerenaToolConfig (tools_types.go, tools_parser.go)
- Delete mcp_serena_config.go (was empty after removing isSerenaInLocalMode)
- Simplify renderSerenaMCPConfigWithOptions to always use docker (mcp_config_serena_renderer.go)
- Simplify renderSerenaTOML to always use docker (mcp_renderer.go)
- Simplify collectDockerImages - always add Serena container image (docker.go)
- Remove GH_AW_SERENA_PORT env var injection (mcp_environment.go)
- Remove detectSerenaLanguageRuntimes and local mode detection (runtime_detection.go)
- Remove Serena local mode strict validation (strict_mode_validation.go)
- Update JSON schema to only allow 'docker' mode enum
- Update docs to remove mention of 'local' mode
- Remove all tests for local mode behavior

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 1, 2026

@copilot review front matter and remove option to start Serena locally

Done in 3eae720. Removed the mode field (and "local" option) from the Serena frontmatter configuration entirely:

  • SerenaToolConfig.Mode field removed from the struct and parser
  • JSON schema updated to only allow "docker" in the enum
  • All runtime code paths for local mode removed (renderSerenaMCPConfigWithOptions, renderSerenaTOML, collectDockerImages, mcp_environment.go, runtime_detection.go, strict_mode_validation.go)
  • All tests for local mode removed; Docker mode tests remain

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw -ifaceassert -nilfunc git rev-�� --show-toplevel -tests /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE git rev-�� --show-toplevel GOPROXY /usr/bin/git GOSUMDB GOWORK 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw go /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha se 4729525/b199/vet.cfg ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -nxv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha 73e99ca425eaccc184465d34:pkg/workflow/mcp_serena_config.go git bin/bash --show-toplevel go /usr/bin/git /opt/hostedtoolcache/node/24.13.1/x64/bin/node /tmp�� secrets.TOKEN git /home/REDACTED/.local/bin/git --show-toplevel node /usr/bin/git git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha Z-uSHE5y4 --global 64/pkg/tool/linux_amd64/vet http.https://gitgit (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha 84465d34:pkg/parser/schemas/main_workflow_schema.json git ache/node/24.13.1/x64/bin/node --show-toplevel go /usr/bin/git git _out�� 84465d34:pkg/workflow/mcp_renderer.go git ache/node/24.13.1/x64/bin/node --show-toplevel go /usr/bin/git ache/node/24.13.1/x64/bin/node (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -unreachable=false /tmp/go-build1924729525/b040/vet.cfg 4729525/b294/vet.cfg .json...&#34; (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha 4729525/b075/_pkg_.a (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha se 4729525/b058/vet.cfg ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha se 4729525/b052/vet.cfg .cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha se 4729525/b139/vet.cfg .cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --show-toplevel (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha se 4729525/b060/vet.cfg .cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha 73e99ca425eaccc184465d34:docs/src/content/docs/reference/frontmatter-full.md git /opt/hostedtoolcache/node/24.13.1/x64/bin/node --show-toplevel go /usr/bin/git node js/f�� 73e99ca425eaccc184465d34:pkg/workflow/mcp_environment.go git ache/uv/0.10.7/x86_64/git --show-toplevel go /usr/bin/git node (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha se 4729525/b010/vet.cfg .cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha 73e99ca425eaccc184465d34:docs/src/content/docs/reference/frontmatter-full.md git it --show-toplevel go 86_64/node node js/f�� 73e99ca425eaccc184465d34:pkg/workflow/mcp_environment.go git /opt/hostedtoolcache/node/24.13.1/x64/bin/node --show-toplevel go /usr/bin/git node (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha prettier --check 64/bin/go --ignore-path .prettierignore 64/bin/go go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha kflow/tools_parser.go go de/node/bin/git -json GO111MODULE /usr/bin/git git _har�� --show-toplevel 84465d34 ache/node/24.13.1/x64/bin/node --show-toplevel GOPROXY /usr/bin/git git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE 1; \ fi env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha ster.patch go /usr/bin/git -json GO111MODULE ache/go/1.25.0/xacdee63f5855b19e73e99ca425eaccc184465d34:pkg/workflow/mcp_environment.go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE ache/go/1.25.0/xacdee63f5855b19e73e99ca425eaccc184465d34:pkg/workflow/tools_types.go git (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha --show-toplevel (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Remove dead start_serena_server.sh (supply chain risk) Remove start_serena_server.sh and Serena local mode (supply chain risk) Mar 1, 2026
@pelikhan
Copy link
Contributor

pelikhan commented Mar 1, 2026

@copilot add codemod that updates local to docker

Adds `serena-local-to-docker` codemod that replaces `mode: local` with
`mode: docker` in tools.serena frontmatter configurations. The local mode
executed serena from an unpinned git repository (supply chain risk) and
has been removed; this codemod allows `gh aw fix` to automatically update
existing workflow files.

- New codemod in codemod_serena_local_mode.go with 7 test cases
- Registered in GetAllCodemods() and fix_codemods_test.go counts updated

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 1, 2026

@copilot add codemod that updates local to docker

Done in 0159ec1. Added serena-local-to-docker codemod in pkg/cli/codemod_serena_local_mode.go that replaces tools.serena.mode: local with tools.serena.mode: docker in workflow frontmatter. Running gh aw fix will automatically migrate affected workflows. The codemod preserves inline comments and only touches the mode field inside tools.serena (not other tools like github).

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation...

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

Agent Container Tool Check

Tool Status Version
bash 5.2.21
sh available
git 2.53.0
jq 1.7
yq v4.52.4
curl 8.5.0
gh 2.87.3
node v20.20.0
python3 3.12.3
go 1.24.13
java 21.0.10 (Temurin)
dotnet 10.0.102

Result: 12/12 tools available ✅

Overall Status: PASS

🔧 Tool validation by Agent Container Smoke Test

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

#19072 · ✅ #19079 · ❌ Serena MCP · ✅ Playwright · ✅ Web Fetch · ✅ File Write · ✅ Bash · ✅ Discussion · ✅ Build · ✅ Create Discussion · ✅ Workflow Dispatch · ✅ PR Review

Overall: ⚠️ PARTIAL PASS (11/12) — Serena MCP tools not available

cc @pelikhan

📰 BREAKING: Report filed by Smoke Copilot

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR removes Serena local mode (supply chain risk mitigation). The codemod for migrating mode: local to mode: docker is well-structured. Minor concern about string-based replacement precision noted inline.

📰 BREAKING: Report filed by Smoke Copilot


modeValue, hasMode := serenaMap["mode"]
if !hasMode {
return content, false, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content-based string replacement approach is straightforward and effective for this migration. One consideration: if a workflow has multiple serena: blocks or if mode: local appears in a comment or string value unrelated to serena config, the regex could match false positives. The frontmatter check above helps guard against this, but the actual replacement relies solely on string matching. Consider adding a more precise regex that requires the mode: line to be within a serena configuration context (e.g., checking indentation).

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

Commit pushed: d4305c4

Generated by Changeset Generator

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2026

Smoke Test Results — Run §22547662764

Overall: PARTIAL (1 failed, 1 skipped)

Core tests #1–10:
✅ GitHub MCP | ✅ GH CLI | ❌ Serena find_symbol (EOF) | ✅ Make build | ✅ Playwright | ✅ Tavily | ✅ File write | ✅ Bash | ✅ Discussion | ✅ AW status

PR review tests #11–17:
✅ Update PR | ✅ Review comments (2) | ✅ Submit review | ✅ Resolve thread | ✅ Add reviewer | ✅ Push branch | ⚠️ Close PR (skipped)

💥 [THE END] — Illustrated by Smoke Claude

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 Automated smoke test review - all systems nominal! The supply chain security improvements in this PR look solid — removing start_serena_server.sh and the local mode eliminates the unpinned uvx-from-git risk. The new codemod cleanly migrates any existing mode: local configurations to mode: docker.

💥 [THE END] — Illustrated by Smoke Claude

@pelikhan pelikhan marked this pull request as ready for review March 1, 2026 17:10
Copilot AI review requested due to automatic review settings March 1, 2026 17:10
@pelikhan pelikhan merged commit afc697e into main Mar 1, 2026
49 checks passed
@pelikhan pelikhan deleted the copilot/fix-security-supply-chain-risk branch March 1, 2026 17:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the insecure Serena “local/uvx” execution path (which executed unpinned code at runtime) and standardizes Serena support on container-only (“docker”) mode, with schema/docs updates and an automatic migration codemod.

Changes:

  • Removed Serena local mode support across workflow compilation/rendering (including deleting the start_serena_server.sh script and local-mode code paths).
  • Updated schema + documentation so Serena mode only allows "docker", and removed tests that exercised local-mode behavior.
  • Added a serena-local-to-docker codemod so gh aw fix can migrate existing workflows from mode: local to mode: docker.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/workflow/tools_types.go Removes SerenaToolConfig.Mode field so local mode can’t be represented in typed config.
pkg/workflow/tools_parser.go Stops parsing tools.serena.mode, aligning parser with container-only support.
pkg/workflow/strict_mode_validation.go Removes strict-mode rejection logic for mode: local (schema now enforces docker-only).
pkg/workflow/strict_mode_serena_test.go Deletes strict-mode test coverage for rejecting Serena local mode.
pkg/workflow/runtime_detection.go Removes uv/language runtime detection for Serena local mode.
pkg/workflow/mcp_setup_generator.go Removes generation of Serena local startup steps.
pkg/workflow/mcp_serena_config.go Deletes local-mode helper/step generator code entirely.
pkg/workflow/mcp_renderer.go Removes local-mode branching in Serena TOML rendering (always container config).
pkg/workflow/mcp_environment.go Removes injection of Serena local-mode port env var.
pkg/workflow/mcp_config_serena_renderer.go Updates Serena MCP config rendering docs/logic to docker-only behavior.
pkg/workflow/mcp_config_comprehensive_test.go Removes local-mode Serena MCP config expectations; keeps docker-mode coverage.
pkg/workflow/importable_tools_test.go Removes import/compile tests that depended on Serena local-mode behavior.
pkg/workflow/docker_predownload_test.go Removes docker-image collection test case for Serena local mode.
pkg/workflow/docker.go Always includes Serena container image when Serena tool is present.
pkg/parser/schemas/main_workflow_schema.json Restricts tools.serena.mode enum to ["docker"] and updates description.
pkg/cli/fix_codemods_test.go Updates codemod count/order expectations to include the new Serena codemod.
pkg/cli/fix_codemods.go Registers the new serena-local-to-docker codemod in GetAllCodemods().
pkg/cli/codemod_serena_local_mode_test.go Adds unit tests for Serena local→docker migration behavior.
pkg/cli/codemod_serena_local_mode.go Implements the serena-local-to-docker codemod.
docs/src/content/docs/reference/frontmatter-full.md Removes documentation implying Serena “local” mode is supported.
actions/setup/sh/start_serena_server.sh Deletes the unpinned uvx --from git+https://... startup script (supply-chain vector).
.changeset/patch-remove-serena-local-mode.md Adds changeset entry documenting the security-driven removal + migration codemod.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// Supports two modes:
// - "docker" (default): Uses Docker container with stdio transport (ghcr.io/github/serena-mcp-server:latest)
// - "local": Uses local uvx with HTTP transport on fixed port
// Uses Docker container with stdio transport (ghcr.io/github/serena-mcp-server:latest)
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This updated function docstring hard-codes the example image to ghcr.io/github/serena-mcp-server:latest, but the implementation selects a container dynamically via selectSerenaContainer() (which can return other images). Please revise the comment to reflect the actual behavior (e.g., "uses a Serena MCP server container selected based on languages").

Suggested change
// Uses Docker container with stdio transport (ghcr.io/github/serena-mcp-server:latest)
// Uses a Serena MCP server container (selected based on requested languages) with stdio transport

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +157
trimmedValue := strings.TrimSpace(valueSection)
if trimmedValue != oldValue {
return line, false
}

// Preserve the whitespace between the colon and the value
spaceBeforeValue := valueSection[:strings.Index(valueSection, trimmedValue)]
newLine := leadingSpace + key + ":" + spaceBeforeValue + newValue
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The codemod only replaces unquoted mode: local. If a workflow uses quoted YAML like mode: "local" / mode: 'local' (common given docs show quoted strings), findAndReplaceValueInLine() won't match and the migration silently won't apply, leaving the workflow failing schema validation. Consider normalizing the value by stripping optional quotes before comparing, and preserve the original quoting style when writing the replacement.

Suggested change
trimmedValue := strings.TrimSpace(valueSection)
if trimmedValue != oldValue {
return line, false
}
// Preserve the whitespace between the colon and the value
spaceBeforeValue := valueSection[:strings.Index(valueSection, trimmedValue)]
newLine := leadingSpace + key + ":" + spaceBeforeValue + newValue
rawValue := strings.TrimSpace(valueSection)
// Detect optional surrounding quotes and normalize value for comparison.
normalizedValue := rawValue
var quoteChar byte
if len(rawValue) >= 2 {
first := rawValue[0]
last := rawValue[len(rawValue)-1]
if (first == '"' || first == '\'') && first == last {
quoteChar = first
normalizedValue = rawValue[1 : len(rawValue)-1]
}
}
if normalizedValue != oldValue {
return line, false
}
// Preserve the whitespace between the colon and the value by finding
// the index of the first non-space character in the value section.
spaceIdx := 0
for spaceIdx < len(valueSection) && (valueSection[spaceIdx] == ' ' || valueSection[spaceIdx] == '\t') {
spaceIdx++
}
spaceBeforeValue := valueSection[:spaceIdx]
// Preserve original quoting style, if any, when writing the new value.
replacementValue := newValue
if quoteChar != 0 {
replacementValue = string(quoteChar) + newValue + string(quoteChar)
}
newLine := leadingSpace + key + ":" + spaceBeforeValue + replacementValue

Copilot uses AI. Check for mistakes.
@@ -276,58 +276,44 @@ func (r *MCPConfigRendererUnified) RenderSerenaMCP(yaml *strings.Builder, serena
func (r *MCPConfigRendererUnified) renderSerenaTOML(yaml *strings.Builder, serenaTool any) {
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment for renderSerenaTOML (immediately above this function) still describes a "local" mode, but the implementation now always renders the Docker/container configuration. Please update/remove the stale local-mode documentation so comments match behavior.

See below for a potential fix:

// using a Docker container with stdio transport. It selects an appropriate
// Serena container image based on the requested languages and configures
// workspace mounts using GITHUB_WORKSPACE.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚨 [SECURITY] Security Red Team Findings - 2026-03-01 (Weekly Full Scan)

3 participants