Skip to content

fix(pay-slip)[backend]: add file type validation in UploadFile handler#41

Open
MohamadNazik wants to merge 1 commit intoLSFLK:mainfrom
MohamadNazik:fix/upload-file-type-validation
Open

fix(pay-slip)[backend]: add file type validation in UploadFile handler#41
MohamadNazik wants to merge 1 commit intoLSFLK:mainfrom
MohamadNazik:fix/upload-file-type-validation

Conversation

@MohamadNazik
Copy link
Contributor

@MohamadNazik MohamadNazik commented Mar 10, 2026

Summary

This PR fixes the issue #30 by adding file type validation to the upload endpoint. The API now restricts uploads to supported formats to prevent invalid file associations.

Changes

  • Validation: Restricted uploads to .pdf, .png, .jpg, and .jpeg (case-insensitive).
  • Error Handling: Non-supported types now return a 400 Bad Request.
  • Docs: Updated the OpenAPI spec to reflect supported formats.

Verification

  • Verified supported formats upload correctly.
  • Verified unsupported formats are rejected with 400 error.

Closes #30

@MohamadNazik MohamadNazik requested a review from a team March 10, 2026 07:27
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the robustness of the pay-slip upload functionality by introducing strict file type validation. It ensures that only specified document and image formats can be uploaded, preventing potential issues from invalid file associations and improving data integrity.

Highlights

  • File Type Validation: Implemented server-side validation for uploaded files, restricting them to .pdf, .png, .jpg, and .jpeg formats (case-insensitive).
  • Error Handling: Configured the API to return a 400 Bad Request status for any upload attempts with unsupported file types.
  • API Documentation Update: Updated the OpenAPI specification to accurately reflect the newly enforced supported file formats for uploads.
Changelog
  • pay-slip-app/backend/api/openapi.yaml
    • Updated the description for the file upload endpoint to list the explicitly allowed file extensions.
  • pay-slip-app/backend/internal/constants/constants.go
    • Added a new global variable AllowedExtensions containing a slice of strings for the permitted file extensions.
  • pay-slip-app/backend/internal/handlers/payslip_handlers.go
    • Imported the path/filepath package to handle file extension extraction.
    • Implemented logic within the UploadFile handler to extract the file extension and compare it against the constants.AllowedExtensions list.
    • Added an early return with an http.StatusBadRequest error if the uploaded file's extension is not among the allowed types.
Activity
  • The author verified that supported file formats can be uploaded successfully.
  • The author verified that unsupported file formats are correctly rejected with a 400 error.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully implements file type validation for uploads, addressing issue #30. The changes include updating the OpenAPI specification to reflect the supported formats, centralizing the list of allowed extensions in constants.go, and adding robust validation logic in the UploadFile handler. The validation correctly performs a case-insensitive check on file extensions and returns an appropriate 400 Bad Request for unsupported types. This is a good improvement for the application's security and data integrity.

@MohamadNazik MohamadNazik force-pushed the fix/upload-file-type-validation branch from 79f749b to c483ef6 Compare March 10, 2026 16:38
@MohamadNazik MohamadNazik requested a review from ginaxu1 March 10, 2026 16:40
- Sniff first 512 bytes for actual content type to prevent extension bypass.
- Centralize extension/MIME mapping into a new internal/utils helper.
- Ensure immutability for AllowedExtensions using a private slice and public getter.
- Improve error message formatting for better user experience.
- Refactor Storage layer to accept content type directly from the handler.
@MohamadNazik MohamadNazik force-pushed the fix/upload-file-type-validation branch from c483ef6 to b0bbf5b Compare March 10, 2026 16:42
@MohamadNazik MohamadNazik changed the title fix(pay-slip): add file type validation in UploadFile handler #30 fix(pay-slip)[backend]: add file type validation in UploadFile handler #30 Mar 10, 2026
@MohamadNazik MohamadNazik changed the title fix(pay-slip)[backend]: add file type validation in UploadFile handler #30 fix(pay-slip)[backend]: add file type validation in UploadFile handler Mar 10, 2026
)

// GetValidatedMimeType checks if the extension is allowed and returns the MIME type.
func GetValidatedMimeType(filename string) (string, bool) {
Copy link

Choose a reason for hiding this comment

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

Extension-based validation can still be spoofed. To make this more robust: use a centralized map for lookups (remove the switch/case) + add content-sniffing support. Here's how you can rewrite this mime_utils.go

// mimeMapping provides a single source of truth for allowed extensions and their canonical MIME types
var mimeMapping = map[string]string{
	".pdf":  "application/pdf",
	".png":  "image/png",
	".jpg":  "image/jpeg",
	".jpeg": "image/jpeg",
}

// Check the filename extension and actual content (magic bytes)
// Returns MIME type and a boolean indicating if the file is valid
func ValidateFile(filename string, content []byte) (string, bool) {
	ext := strings.ToLower(filepath.Ext(filename))
	
	// Validate Extension against our known allowed list
	canonicalMime, supported := mimeMapping[ext]
	if !supported {
		return "", false
	}

	// Validate actual content for security
	// http.DetectContentType uses the first 512 bytes to determine the MIME type.
	detectedMime := http.DetectContentType(content)

	// Clean detected MIME (remove charset info if present)
	if parts := strings.Split(detectedMime, ";"); len(parts) > 0 {
		detectedMime = parts[0]
	}

	// Make sure the extension matches the actual content type
	// This prevents a user from uploading a .exe renamed to .pdf
	if detectedMime != canonicalMime {
		return "", false
	}

	return canonicalMime, true
}

// GetMimeByExtension is a helper for cases where only the filename is available
func GetMimeByExtension(filename string) (string, bool) {
	ext := strings.ToLower(filepath.Ext(filename))
	mime, allowed := mimeMapping[ext]
	return mime, allowed
}

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.

fix(pay-slip): add file type validation in UploadFile handler

2 participants