fix(sec): web route update and delete runner variables

The web route to update and delete variables of runners did not check if
the ID that was given belonged to the context it was requested in, this
made it possible to update and delete every existing runner variable of
a instance for any authenticated user.

The code has been reworked to always take into account the context of
the request (owner and repository ID).
This commit is contained in:
Gusted 2025-01-25 09:26:50 +01:00 committed by Earl Warren
parent f359ebeea5
commit 0b17346cff
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
5 changed files with 31 additions and 25 deletions

View file

@ -86,7 +86,7 @@ func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariab
} }
func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) { func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) {
count, err := db.GetEngine(ctx).ID(variable.ID).Cols("name", "data"). count, err := db.GetEngine(ctx).ID(variable.ID).Where("owner_id = ? AND repo_id = ?", variable.OwnerID, variable.RepoID).Cols("name", "data").
Update(&ActionVariable{ Update(&ActionVariable{
Name: variable.Name, Name: variable.Name,
Data: variable.Data, Data: variable.Data,
@ -94,11 +94,9 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error)
return count != 0, err return count != 0, err
} }
func DeleteVariable(ctx context.Context, id int64) error { func DeleteVariable(ctx context.Context, variableID, ownerID, repoID int64) (bool, error) {
if _, err := db.DeleteByID[ActionVariable](ctx, id); err != nil { count, err := db.GetEngine(ctx).Table("action_variable").Where("id = ? AND owner_id = ? AND repo_id = ?", variableID, ownerID, repoID).Delete()
return err return count != 0, err
}
return nil
} }
func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) { func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) {

View file

@ -3903,6 +3903,7 @@ variables.deletion.description = Removing a variable is permanent and cannot be
variables.description = Variables will be passed to certain actions and cannot be read otherwise. variables.description = Variables will be passed to certain actions and cannot be read otherwise.
variables.id_not_exist = Variable with ID %d does not exist. variables.id_not_exist = Variable with ID %d does not exist.
variables.edit = Edit Variable variables.edit = Edit Variable
variables.not_found = Failed to find the variable.
variables.deletion.failed = Failed to remove variable. variables.deletion.failed = Failed to remove variable.
variables.deletion.success = The variable has been removed. variables.deletion.success = The variable has been removed.
variables.creation.failed = Failed to add variable. variables.creation.failed = Failed to add variable.

View file

@ -127,7 +127,7 @@ func VariableUpdate(ctx *context.Context) {
return return
} }
shared.UpdateVariable(ctx, vCtx.RedirectLink) shared.UpdateVariable(ctx, vCtx.OwnerID, vCtx.RepoID, vCtx.RedirectLink)
} }
func VariableDelete(ctx *context.Context) { func VariableDelete(ctx *context.Context) {
@ -136,5 +136,5 @@ func VariableDelete(ctx *context.Context) {
ctx.ServerError("getVariablesCtx", err) ctx.ServerError("getVariablesCtx", err)
return return
} }
shared.DeleteVariable(ctx, vCtx.RedirectLink) shared.DeleteVariable(ctx, vCtx.OwnerID, vCtx.RepoID, vCtx.RedirectLink)
} }

View file

@ -39,25 +39,33 @@ func CreateVariable(ctx *context.Context, ownerID, repoID int64, redirectURL str
ctx.JSONRedirect(redirectURL) ctx.JSONRedirect(redirectURL)
} }
func UpdateVariable(ctx *context.Context, redirectURL string) { func UpdateVariable(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
id := ctx.ParamsInt64(":variable_id") id := ctx.ParamsInt64(":variable_id")
form := web.GetForm(ctx).(*forms.EditVariableForm) form := web.GetForm(ctx).(*forms.EditVariableForm)
if ok, err := actions_service.UpdateVariable(ctx, id, form.Name, form.Data); err != nil || !ok { if ok, err := actions_service.UpdateVariable(ctx, id, ownerID, repoID, form.Name, form.Data); err != nil || !ok {
if !ok {
ctx.JSONError(ctx.Tr("actions.variables.not_found"))
} else {
log.Error("UpdateVariable: %v", err) log.Error("UpdateVariable: %v", err)
ctx.JSONError(ctx.Tr("actions.variables.update.failed")) ctx.JSONError(ctx.Tr("actions.variables.update.failed"))
}
return return
} }
ctx.Flash.Success(ctx.Tr("actions.variables.update.success")) ctx.Flash.Success(ctx.Tr("actions.variables.update.success"))
ctx.JSONRedirect(redirectURL) ctx.JSONRedirect(redirectURL)
} }
func DeleteVariable(ctx *context.Context, redirectURL string) { func DeleteVariable(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
id := ctx.ParamsInt64(":variable_id") id := ctx.ParamsInt64(":variable_id")
if err := actions_service.DeleteVariableByID(ctx, id); err != nil { if ok, err := actions_model.DeleteVariable(ctx, id, ownerID, repoID); err != nil || !ok {
if !ok {
ctx.JSONError(ctx.Tr("actions.variables.not_found"))
} else {
log.Error("Delete variable [%d] failed: %v", id, err) log.Error("Delete variable [%d] failed: %v", id, err)
ctx.JSONError(ctx.Tr("actions.variables.deletion.failed")) ctx.JSONError(ctx.Tr("actions.variables.deletion.failed"))
}
return return
} }
ctx.Flash.Success(ctx.Tr("actions.variables.deletion.success")) ctx.Flash.Success(ctx.Tr("actions.variables.deletion.success"))

View file

@ -31,7 +31,7 @@ func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data strin
return v, nil return v, nil
} }
func UpdateVariable(ctx context.Context, variableID int64, name, data string) (bool, error) { func UpdateVariable(ctx context.Context, variableID, ownerID, repoID int64, name, data string) (bool, error) {
if err := secret_service.ValidateName(name); err != nil { if err := secret_service.ValidateName(name); err != nil {
return false, err return false, err
} }
@ -44,13 +44,11 @@ func UpdateVariable(ctx context.Context, variableID int64, name, data string) (b
ID: variableID, ID: variableID,
Name: strings.ToUpper(name), Name: strings.ToUpper(name),
Data: util.ReserveLineBreakForTextarea(data), Data: util.ReserveLineBreakForTextarea(data),
OwnerID: ownerID,
RepoID: repoID,
}) })
} }
func DeleteVariableByID(ctx context.Context, variableID int64) error {
return actions_model.DeleteVariable(ctx, variableID)
}
func DeleteVariableByName(ctx context.Context, ownerID, repoID int64, name string) error { func DeleteVariableByName(ctx context.Context, ownerID, repoID int64, name string) error {
if err := secret_service.ValidateName(name); err != nil { if err := secret_service.ValidateName(name); err != nil {
return err return err
@ -69,7 +67,8 @@ func DeleteVariableByName(ctx context.Context, ownerID, repoID int64, name strin
return err return err
} }
return actions_model.DeleteVariable(ctx, v.ID) _, err = actions_model.DeleteVariable(ctx, v.ID, ownerID, repoID)
return err
} }
func GetVariable(ctx context.Context, opts actions_model.FindVariablesOpts) (*actions_model.ActionVariable, error) { func GetVariable(ctx context.Context, opts actions_model.FindVariablesOpts) (*actions_model.ActionVariable, error) {