Skip to content

feat: [CODE-4993] refactor the upload flow of Git LFS#2

Open
sanket-deepsource wants to merge 2 commits into
mainfrom
atmsn/CODE-4993_b
Open

feat: [CODE-4993] refactor the upload flow of Git LFS#2
sanket-deepsource wants to merge 2 commits into
mainfrom
atmsn/CODE-4993_b

Conversation

@sanket-deepsource

Copy link
Copy Markdown

No description provided.

@deepsource-io

deepsource-io Bot commented Jun 20, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in b4c0308...c279b6b on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade  

Focus Area: Security
Security  

Reliability  

Complexity  

Hygiene  

Feedback

Path handling consistency

  • Two of the security issues come from how paths are constructed, leading to traversal and arbitrary deletion risks.
  • Given how careful the upload lifecycle is, it’s worth holding path joining to the same standard so the integrity guarantees apply both to where data lives and how it’s reached.

Receiver semantics vs. abstraction cleanliness

  • The mixed pointer/value receivers and the Delete “warning only” behavior both create subtle differences in how storage backends behave.
  • Your abstraction is nicely disciplined; aligning method semantics (receivers and delete behavior) will help keep that contract predictable across implementations.

Code Review Summary

Analyzer Status Updated (UTC) Details
Go Jun 20, 2026 5:38p.m. Review ↗

Comment thread blob/filesystem.go
return io.ReadCloser(file), nil
}

func (c *FileSystemStore) Move(_ context.Context, srcPath, dstPath string) error {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Type "FileSystemStore" has both value and pointer receivers


(Go's FAQ)[https://go.dev/doc/faq#methods_on_values_or_pointers] recommends
that method receivers should be consistent. If some of the methods of the type
must have pointer receivers, the rest should too, so the method set is
consistent regardless of how the type is used. This is because value and
pointer receivers have different
method sets.

Comment thread blob/filesystem.go
return nil
}

func (c *FileSystemStore) Delete(_ context.Context, filePath string) error {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Type "FileSystemStore" has both value and pointer receivers


(Go's FAQ)[https://go.dev/doc/faq#methods_on_values_or_pointers] recommends
that method receivers should be consistent. If some of the methods of the type
must have pointer receivers, the rest should too, so the method set is
consistent regardless of how the type is used. This is because value and
pointer receivers have different
method sets.

Comment thread blob/filesystem_test.go
if test.content != "" {
fullPath := filepath.Join(tempDir, test.filePath)
dir := filepath.Dir(fullPath)
if err := os.MkdirAll(dir, 0755); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expect directory permissions to be 0750 or less


Excessive permissions granted when creating a directory. This warning is
triggered whenever permission greater than 0750 is given.

@sanket-deepsource

Copy link
Copy Markdown
Author

@deepsourcebot review

@sanket-deepsource sanket-deepsource changed the title dummy pr 2 feat: [CODE-4993] refactor the upload flow of Git LFS Jun 20, 2026
Comment thread blob/filesystem.go
Comment on lines +107 to +108
srcDiskPath := fmt.Sprintf(fileDiskPathFmt, c.basePath, srcPath)
dstDiskPath := fmt.Sprintf(fileDiskPathFmt, c.basePath, dstPath)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

`fmt.Sprintf` path join enables filesystem traversal


Unvalidated srcPath/dstPath can resolve outside c.basePath. If any caller passes attacker-influenced values, arbitrary file relocation or overwrite becomes possible.
Use filepath.Clean, reject absolute and .. segments, then verify resolved paths keep the c.basePath prefix before renaming

Comment thread blob/filesystem.go
}

func (c *FileSystemStore) Delete(_ context.Context, filePath string) error {
fileDiskPath := fmt.Sprintf(fileDiskPathFmt, c.basePath, filePath)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

`fmt.Sprintf` path join enables arbitrary file deletion


filePath is not normalized or constrained to the blob root before deletion. A crafted traversal path could delete unintended host files when upstream validation is bypassed.
Use filepath.Clean, reject absolute/.. paths, and ensure the resolved target remains under c.basePath before deletion

Comment thread blob/filesystem_test.go
Comment on lines +428 to +432
if test.expectError {
if err == nil {
t.Error("expected error but got none")
}
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

`expectError` branch skips `errorType` validation


The expectError path only verifies err != nil. A wrong failure reason still passes, weakening regression detection for move error contracts.

Add errorType to negative cases and assert errors.Is(err, test.errorType) before returning

Comment thread blob/gcs.go
Comment on lines +183 to +186
if err := srcObj.Delete(ctx); err != nil {
log.Ctx(ctx).Warn().Err(err).Msgf(
"failed to delete source file %q after successful copy to %q", srcPath, dstPath)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

`srcObj.Delete` warning-only handling leaves duplicate objects


Move logs srcObj.Delete errors but still returns success. That breaks move semantics and can leave both source and destination objects present, causing stale temporary blobs and inconsistent state for downstream workflows.

Return a wrapped error when srcObj.Delete fails, or implement compensating rollback by deleting dstObj before returning an error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants