fix: Codex round 9 — verify push target, plan path traversal, mirror branch
Some checks failed
CI / test (push) Failing after 3s
Some checks failed
CI / test (push) Failing after 3s
High: verify rebase push now targets Forge remote, not local origin
High/Security: planPath sanitises ID via filepath.Base to prevent
path traversal in plan read/update/delete
Medium: mirror compares and pushes local default branch, not HEAD
Findings 3-6 verified as false positives/known issues (bridge async
by design, API returns top-level memories not {data:...}, inbox uses
{messages:...} confirmed against live API).
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
6da52aa60f
commit
92b7b08113
3 changed files with 25 additions and 8 deletions
|
|
@ -87,14 +87,15 @@ func (s *PrepSubsystem) mirror(ctx context.Context, _ *mcp.CallToolRequest, inpu
|
|||
fetchCmd.Dir = repoDir
|
||||
fetchCmd.Run()
|
||||
|
||||
// Check how far ahead we are
|
||||
ahead := commitsAhead(repoDir, "github/main", "HEAD")
|
||||
// Check how far ahead local default branch is vs github
|
||||
localBase := gitDefaultBranch(repoDir)
|
||||
ahead := commitsAhead(repoDir, "github/main", localBase)
|
||||
if ahead == 0 {
|
||||
continue // Already in sync
|
||||
}
|
||||
|
||||
// Count files changed
|
||||
files := filesChanged(repoDir, "github/main", "HEAD")
|
||||
files := filesChanged(repoDir, "github/main", localBase)
|
||||
|
||||
sync := MirrorSync{
|
||||
Repo: repo,
|
||||
|
|
@ -118,8 +119,9 @@ func (s *PrepSubsystem) mirror(ctx context.Context, _ *mcp.CallToolRequest, inpu
|
|||
// Ensure dev branch exists on GitHub
|
||||
ensureDevBranch(repoDir)
|
||||
|
||||
// Push local main to github dev
|
||||
pushCmd := exec.CommandContext(ctx, "git", "push", "github", "HEAD:refs/heads/dev", "--force")
|
||||
// Push local main to github dev (explicit main, not HEAD)
|
||||
base := gitDefaultBranch(repoDir)
|
||||
pushCmd := exec.CommandContext(ctx, "git", "push", "github", base+":refs/heads/dev", "--force")
|
||||
pushCmd.Dir = repoDir
|
||||
if err := pushCmd.Run(); err != nil {
|
||||
sync.Skipped = fmt.Sprintf("push failed: %v", err)
|
||||
|
|
|
|||
|
|
@ -313,7 +313,12 @@ func (s *PrepSubsystem) planList(_ context.Context, _ *mcp.CallToolRequest, inpu
|
|||
// --- Helpers ---
|
||||
|
||||
func planPath(dir, id string) string {
|
||||
return filepath.Join(dir, id+".json")
|
||||
// Sanitise ID to prevent path traversal
|
||||
safe := filepath.Base(id)
|
||||
if safe == "." || safe == ".." || safe == "" {
|
||||
safe = "invalid"
|
||||
}
|
||||
return filepath.Join(dir, safe+".json")
|
||||
}
|
||||
|
||||
func generatePlanID(title string) string {
|
||||
|
|
|
|||
|
|
@ -132,8 +132,18 @@ func (s *PrepSubsystem) rebaseBranch(srcDir, branch string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Force-push the rebased branch
|
||||
push := exec.Command("git", "push", "--force-with-lease", "origin", branch)
|
||||
// Force-push the rebased branch to Forge (origin is local clone)
|
||||
st, _ := readStatus(filepath.Dir(srcDir))
|
||||
org := "core"
|
||||
repo := ""
|
||||
if st != nil {
|
||||
if st.Org != "" {
|
||||
org = st.Org
|
||||
}
|
||||
repo = st.Repo
|
||||
}
|
||||
forgeRemote := fmt.Sprintf("ssh://git@forge.lthn.ai:2223/%s/%s.git", org, repo)
|
||||
push := exec.Command("git", "push", "--force-with-lease", forgeRemote, branch)
|
||||
push.Dir = srcDir
|
||||
return push.Run() == nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue