mirror of
https://github.com/FalconOpsLLC/goexec
synced 2026-06-06 15:44:27 +00:00
feat: auto-remove uploaded file after execution (upload+execute mode)
When --upload is combined with --exec/--command, the uploaded file is automatically deleted from the remote filesystem after execution completes. This supports the upload-execute-cleanup workflow (e.g., upload a.bat, execute cmd.exe /c a.bat, then delete a.bat — safe because cmd.exe already loaded the script). Upload-only mode (--upload without --exec) does NOT delete the file. - Add UploadRemover optional interface in io.go - Add RemoveUploadedFile method on FileStager (deletes via SMB) - In ExecuteCleanMethod, call RemoveUploadedFile after execution if both upload and execution were performed Co-authored-by: Carter <carter-falconops@users.noreply.github.com>
This commit is contained in:
@@ -47,6 +47,12 @@ type UploadConfirmer interface {
|
||||
ConfirmUpload(ctx context.Context) error
|
||||
}
|
||||
|
||||
// UploadRemover is an optional interface that InputProvider implementations
|
||||
// can satisfy to remove a previously uploaded file from the remote filesystem.
|
||||
type UploadRemover interface {
|
||||
RemoveUploadedFile(ctx context.Context) error
|
||||
}
|
||||
|
||||
type ExecutionInput struct {
|
||||
StageFile io.ReadCloser
|
||||
Executable string
|
||||
|
||||
@@ -138,11 +138,22 @@ func ExecuteCleanMethod(ctx context.Context, module CleanExecutionMethod, execIO
|
||||
}
|
||||
|
||||
// Execute (only if a command/executable was provided)
|
||||
executed := false
|
||||
if execIO.Input != nil && (execIO.Input.Executable != "" || execIO.Input.Command != "" || execIO.Input.ExecutablePath != "") {
|
||||
if err = module.Execute(ctx, execIO); err != nil {
|
||||
log.Error().Err(err).Msg("Execution failed")
|
||||
return fmt.Errorf("execute: %w", err)
|
||||
}
|
||||
executed = true
|
||||
}
|
||||
|
||||
// Remove uploaded file after execution (upload+execute mode only)
|
||||
if executed && execIO.Upload != nil && execIO.Upload.Provider != nil {
|
||||
if remover, ok := execIO.Upload.Provider.(UploadRemover); ok {
|
||||
if removeErr := remover.RemoveUploadedFile(ctx); removeErr != nil {
|
||||
log.Warn().Err(removeErr).Msg("Failed to remove uploaded file")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Module cleanup
|
||||
|
||||
@@ -63,6 +63,23 @@ func (o *FileStager) Upload(ctx context.Context, reader io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveUploadedFile deletes the uploaded file from the remote filesystem.
|
||||
// The share must already be mounted from a prior Upload call.
|
||||
func (o *FileStager) RemoveUploadedFile(ctx context.Context) error {
|
||||
log := zerolog.Ctx(ctx)
|
||||
|
||||
if o.Client.mount == nil {
|
||||
return fmt.Errorf("share not mounted")
|
||||
}
|
||||
|
||||
if err := o.Client.mount.Remove(o.relativePath); err != nil {
|
||||
return fmt.Errorf("remove remote file: %w", err)
|
||||
}
|
||||
|
||||
log.Info().Str("path", o.File).Msg("Removed uploaded file")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfirmUpload checks that the uploaded file exists on the remote filesystem
|
||||
// and logs the file path and size. The share must already be mounted from a
|
||||
// prior Upload call.
|
||||
|
||||
Reference in New Issue
Block a user