CVE-2017-15211: Authorization Bypass Through User-Controlled Key (CWE-639)
value: In Kanboard before 1.0.47, by altering form data, an authenticated user can add an external link to a private project of another user.
CWE description: The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.
CVSS v3 base score: 4.3
Published: 2017-10-11T01:32Z
Repository: https://github.com/kanboard/kanboard
Language: PHP
Files changed: ChangeLog, app/Controller/ActionController.php, app/Controller/ActionCreationController.php, app/Controller/BaseController.php, app/Controller/CategoryController.php, app/Controller/ColumnController.php, app/Controller/CustomFilterController.php, app/Controller/ProjectEditController.php, app/Controller/ProjectTagController.php, app/Controller/SwimlaneController.php, app/Controller/TaskCreationController.php, app/Template/action_creation/create.php, app/Template/action_creation/event.php, app/Template/action_creation/params.php, app/Template/category/create.php, app/Template/category/edit.php, app/Template/column/create.php, app/Template/column/edit.php, app/Template/custom_filter/create.php, app/Template/custom_filter/edit.php, app/Template/project_edit/show.php, app/Template/project_tag/create.php, app/Template/project_tag/edit.php, app/Template/swimlane/create.php, app/Template/swimlane/edit.php, app/Template/task_creation/show.php
Commit date: 2017-09-23 18:48:45 -0700
Commit message: Avoid people to alter other projects by changing form data

Diff: diff --git a/ChangeLog b/ChangeLog
index 8ff191af3..b209dc2b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,10 +3,14 @@ Version 1.0.47 (unreleased)
 
 New features:
 
 * Vietnamese translation
 
+Security Issues:
+
+* Avoid people to alter other project resources by changing form data
+
 Version 1.0.46 (August 13, 2017)
 --------------------------------
 
 Security Issues:
 
diff --git a/app/Controller/ActionController.php b/app/Controller/ActionController.php
index c935125ae..43acf5902 100644
--- a/app/Controller/ActionController.php
+++ b/app/Controller/ActionController.php
@@ -44,13 +44,14 @@ class ActionController extends BaseController
      * @access public
      */
     public function confirm()
     {
         $project = $this->getProject();
+        $action = $this->getAction($project);
 
         $this->response->html($this->helper->layout->project('action/remove', array(
-            'action' => $this->actionModel->getById($this->request->getIntegerParam('action_id')),
+            'action' => $action,
             'available_events' => $this->eventManager->getAll(),
             'available_actions' => $this->actionManager->getAvailableActions(),
             'project' => $project,
             'title' => t('Remove an action')
         )));
@@ -63,11 +64,11 @@ class ActionController extends BaseController
      */
     public function remove()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $action = $this->actionModel->getById($this->request->getIntegerParam('action_id'));
+        $action = $this->getAction($project);
 
         if (! empty($action) && $this->actionModel->remove($action['id'])) {
             $this->flash->success(t('Action removed successfully.'));
         } else {
             $this->flash->failure(t('Unable to remove this action.'));
diff --git a/app/Controller/ActionCreationController.php b/app/Controller/ActionCreationController.php
index 7fee58d1f..abb214e64 100644
--- a/app/Controller/ActionCreationController.php
+++ b/app/Controller/ActionCreationController.php
@@ -33,12 +33,13 @@ class ActionCreationController extends BaseController
      */
     public function event()
     {
         $project = $this->getProject();
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
 
-        if (empty($values['action_name']) || empty($values['project_id'])) {
+        if (empty($values['action_name'])) {
             return $this->create();
         }
 
         return $this->response->html($this->template->render('action_creation/event', array(
             'values' => $values,
@@ -55,12 +56,13 @@ class ActionCreationController extends BaseController
      */
     public function params()
     {
         $project = $this->getProject();
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
 
-        if (empty($values['action_name']) || empty($values['project_id']) || empty($values['event_name'])) {
+        if (empty($values['action_name']) || empty($values['event_name'])) {
             $this->create();
             return;
         }
 
         $action = $this->actionManager->getAction($values['action_name']);
@@ -107,10 +109,11 @@ class ActionCreationController extends BaseController
      * @param  array     $project   Project properties
      * @param  array     $values    Form values
      */
     private function doCreation(array $project, array $values)
     {
+        $values['project_id'] = $project['id'];
         list($valid, ) = $this->actionValidator->validateCreation($values);
 
         if ($valid) {
             if ($this->actionModel->create($values) !== false) {
                 $this->flash->success(t('Your automatic action have been created successfully.'));
diff --git a/app/Controller/BaseController.php b/app/Controller/BaseController.php
index 5233e27fd..1ac7ed203 100644
--- a/app/Controller/BaseController.php
+++ b/app/Controller/BaseController.php
@@ -153,6 +153,96 @@ abstract class BaseController extends Base
             throw new PageNotFoundException();
         }
 
         return $subtask;
     }
+
+    protected function getColumn(array $project)
+    {
+        $column = $this->columnModel->getById($this->request->getIntegerParam('column_id'));
+
+        if (empty($column)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($column['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $column;
+    }
+
+    protected function getSwimlane(array $project)
+    {
+        $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));
+
+        if (empty($swimlane)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($swimlane['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $swimlane;
+    }
+
+    protected function getCategory(array $project)
+    {
+        $category = $this->categoryModel->getById($this->request->getIntegerParam('category_id'));
+
+        if (empty($category)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($category['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $category;
+    }
+
+    protected function getProjectTag(array $project)
+    {
+        $tag = $this->tagModel->getById($this->request->getIntegerParam('tag_id'));
+
+        if (empty($tag)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($tag['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $tag;
+    }
+
+    protected function getAction(array $project)
+    {
+        $action = $this->actionModel->getById($this->request->getIntegerParam('action_id'));
+
+        if (empty($action)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($action['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $action;
+    }
+
+    protected function getCustomFilter(array $project)
+    {
+        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
+
+        if (empty($filter)) {
+            throw new PageNotFoundException();
+        }
+
+        if ($filter['project_id'] != $project['id']) {
+            throw new AccessForbiddenException();
+        }
+
+        return $filter;
+    }
 }
diff --git a/app/Controller/CategoryController.php b/app/Controller/CategoryController.php
index 69bbad5aa..e3f2406b6 100644
--- a/app/Controller/CategoryController.php
+++ b/app/Controller/CategoryController.php
@@ -10,28 +10,10 @@ use Kanboard\Core\Controller\PageNotFoundException;
  * @package Kanboard\Controller
  * @author  Frederic Guillot
  */
 class CategoryController extends BaseController
 {
-    /**
-     * Get the category (common method between actions)
-     *
-     * @access private
-     * @return array
-     * @throws PageNotFoundException
-     */
-    private function getCategory()
-    {
-        $category = $this->categoryModel->getById($this->request->getIntegerParam('category_id'));
-
-        if (empty($category)) {
-            throw new PageNotFoundException();
-        }
-
-        return $category;
-    }
-
     /**
      * List of categories for a given project
      *
      * @access public
      * @throws PageNotFoundException
@@ -70,12 +52,13 @@ class CategoryController extends BaseController
      * @access public
      */
     public function save()
     {
         $project = $this->getProject();
-
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
+
         list($valid, $errors) = $this->categoryValidator->validateCreation($values);
 
         if ($valid) {
             if ($this->categoryModel->create($values) !== false) {
                 $this->flash->success(t('Your category have been created successfully.'));
@@ -98,11 +81,11 @@ class CategoryController extends BaseController
      * @throws PageNotFoundException
      */
     public function edit(array $values = array(), array $errors = array())
     {
         $project = $this->getProject();
-        $category = $this->getCategory();
+        $category = $this->getCategory($project);
 
         $this->response->html($this->template->render('category/edit', array(
             'values'  => empty($values) ? $category : $values,
             'errors'  => $errors,
             'project' => $project,
@@ -115,12 +98,16 @@ class CategoryController extends BaseController
      * @access public
      */
     public function update()
     {
         $project = $this->getProject();
+        $category = $this->getCategory($project);
 
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
+        $values['id'] = $category['id'];
+
         list($valid, $errors) = $this->categoryValidator->validateModification($values);
 
         if ($valid) {
             if ($this->categoryModel->update($values)) {
                 $this->flash->success(t('This category has been updated successfully.'));
@@ -139,11 +126,11 @@ class CategoryController extends BaseController
      * @access public
      */
     public function confirm()
     {
         $project = $this->getProject();
-        $category = $this->getCategory();
+        $category = $this->getCategory($project);
 
         $this->response->html($this->helper->layout->project('category/remove', array(
             'project'  => $project,
             'category' => $category,
         )));
@@ -156,11 +143,11 @@ class CategoryController extends BaseController
      */
     public function remove()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $category = $this->getCategory();
+        $category = $this->getCategory($project);
 
         if ($this->categoryModel->remove($category['id'])) {
             $this->flash->success(t('Category removed successfully.'));
         } else {
             $this->flash->failure(t('Unable to remove this category.'));
diff --git a/app/Controller/ColumnController.php b/app/Controller/ColumnController.php
index 7047d30e1..8e4712d97 100644
--- a/app/Controller/ColumnController.php
+++ b/app/Controller/ColumnController.php
@@ -59,10 +59,11 @@ class ColumnController extends BaseController
      */
     public function save()
     {
         $project = $this->getProject();
         $values = $this->request->getValues() + array('hide_in_dashboard' => 0);
+        $values['project_id'] = $project['id'];
 
         list($valid, $errors) = $this->columnValidator->validateCreation($values);
 
         if ($valid) {
             $result = $this->columnModel->create(
@@ -93,11 +94,11 @@ class ColumnController extends BaseController
      * @param array $errors
      */
     public function edit(array $values = array(), array $errors = array())
     {
         $project = $this->getProject();
-        $column = $this->columnModel->getById($this->request->getIntegerParam('column_id'));
+        $column = $this->getColumn($project);
 
         $this->response->html($this->helper->layout->project('column/edit', array(
             'errors' => $errors,
             'values' => $values ?: $column,
             'project' => $project,
@@ -111,11 +112,15 @@ class ColumnController extends BaseController
      * @access public
      */
     public function update()
     {
         $project = $this->getProject();
+        $column = $this->getColumn($project);
+
         $values = $this->request->getValues() + array('hide_in_dashboard' => 0);
+        $values['project_id'] = $project['id'];
+        $values['id'] = $column['id'];
 
         list($valid, $errors) = $this->columnValidator->validateModification($values);
 
         if ($valid) {
             $result = $this->columnModel->update(
@@ -162,13 +167,14 @@ class ColumnController extends BaseController
      * @access public
      */
     public function confirm()
     {
         $project = $this->getProject();
+        $column = $this->getColumn($project);
 
         $this->response->html($this->helper->layout->project('column/remove', array(
-            'column' => $this->columnModel->getById($this->request->getIntegerParam('column_id')),
+            'column' => $column,
             'project' => $project,
         )));
     }
 
     /**
@@ -176,15 +182,15 @@ class ColumnController extends BaseController
      *
      * @access public
      */
     public function remove()
     {
-        $project = $this->getProject();
         $this->checkCSRFParam();
-        $column_id = $this->request->getIntegerParam('column_id');
+        $project = $this->getProject();
+        $column = $this->getColumn($project);
 
-        if ($this->columnModel->remove($column_id)) {
+        if ($this->columnModel->remove($column['id'])) {
             $this->flash->success(t('Column removed successfully.'));
         } else {
             $this->flash->failure(t('Unable to remove this column.'));
         }
 
diff --git a/app/Controller/CustomFilterController.php b/app/Controller/CustomFilterController.php
index dfe1ffc4c..1bf1617e8 100644
--- a/app/Controller/CustomFilterController.php
+++ b/app/Controller/CustomFilterController.php
@@ -57,10 +57,11 @@ class CustomFilterController extends BaseController
     public function save()
     {
         $project = $this->getProject();
 
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
         $values['user_id'] = $this->userSession->getId();
 
         list($valid, $errors) = $this->customFilterValidator->validateCreation($values);
 
         if ($valid) {
@@ -82,11 +83,11 @@ class CustomFilterController extends BaseController
      * @access public
      */
     public function confirm()
     {
         $project = $this->getProject();
-        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
+        $filter = $this->getCustomFilter($project);
 
         $this->response->html($this->helper->layout->project('custom_filter/remove', array(
             'project' => $project,
             'filter' => $filter,
             'title' => t('Remove a custom filter')
@@ -100,11 +101,11 @@ class CustomFilterController extends BaseController
      */
     public function remove()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
+        $filter = $this->getCustomFilter($project);
 
         $this->checkPermission($project, $filter);
 
         if ($this->customFilterModel->remove($filter['id'])) {
             $this->flash->success(t('Custom filter removed successfully.'));
@@ -151,10 +152,12 @@ class CustomFilterController extends BaseController
         $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
 
         $this->checkPermission($project, $filter);
 
         $values = $this->request->getValues();
+        $values['id'] = $filter['id'];
+        $values['project_id'] = $project['id'];
 
         if (! isset($values['is_shared'])) {
             $values += array('is_shared' => 0);
         }
 
diff --git a/app/Controller/ProjectEditController.php b/app/Controller/ProjectEditController.php
index ae39fdf35..dd5345084 100644
--- a/app/Controller/ProjectEditController.php
+++ b/app/Controller/ProjectEditController.php
@@ -63,10 +63,12 @@ class ProjectEditController extends BaseController
      * @param  array  $values
      * @return array
      */
     private function prepareValues(array $project, array $values)
     {
+        $values['id'] = $project['id'];
+
         if (isset($values['is_private'])) {
             if (! $this->helper->user->hasProjectAccess('ProjectCreationController', 'create', $project['id'])) {
                 unset($values['is_private']);
             }
         } elseif ($project['is_private'] == 1 && ! isset($values['is_private'])) {
diff --git a/app/Controller/ProjectTagController.php b/app/Controller/ProjectTagController.php
index d225f0cab..c45e71e15 100644
--- a/app/Controller/ProjectTagController.php
+++ b/app/Controller/ProjectTagController.php
@@ -1,11 +1,9 @@
 <?php
 
 namespace Kanboard\Controller;
 
-use Kanboard\Core\Controller\AccessForbiddenException;
-
 /**
  * Class ProjectTagController
  *
  * @package Kanboard\Controller
  * @author  Frederic Guillot
@@ -25,14 +23,10 @@ class ProjectTagController extends BaseController
 
     public function create(array $values = array(), array $errors = array())
     {
         $project = $this->getProject();
 
-        if (empty($values)) {
-            $values['project_id'] = $project['id'];
-        }
-
         $this->response->html($this->template->render('project_tag/create', array(
             'project' => $project,
             'values'  => $values,
             'errors'  => $errors,
         )));
@@ -40,10 +34,12 @@ class ProjectTagController extends BaseController
 
     public function save()
     {
         $project = $this->getProject();
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
+
         list($valid, $errors) = $this->tagValidator->validateCreation($values);
 
         if ($valid) {
             if ($this->tagModel->create($project['id'], $values['name']) > 0) {
                 $this->flash->success(t('Tag created successfully.'));
@@ -58,12 +54,11 @@ class ProjectTagController extends BaseController
     }
 
     public function edit(array $values = array(), array $errors = array())
     {
         $project = $this->getProject();
-        $tag_id = $this->request->getIntegerParam('tag_id');
-        $tag = $this->tagModel->getById($tag_id);
+        $tag = $this->getProjectTag($project);
 
         if (empty($values)) {
             $values = $tag;
         }
 
@@ -76,18 +71,16 @@ class ProjectTagController extends BaseController
     }
 
     public function update()
     {
         $project = $this->getProject();
-        $tag_id = $this->request->getIntegerParam('tag_id');
-        $tag = $this->tagModel->getById($tag_id);
+        $tag = $this->getProjectTag($project);
         $values = $this->request->getValues();
-        list($valid, $errors) = $this->tagValidator->validateModification($values);
+        $values['project_id'] = $project['id'];
+        $values['id'] = $tag['id'];
 
-        if ($tag['project_id'] != $project['id']) {
-            throw new AccessForbiddenException();
-        }
+        list($valid, $errors) = $this->tagValidator->validateModification($values);
 
         if ($valid) {
             if ($this->tagModel->update($values['id'], $values['name'])) {
                 $this->flash->success(t('Tag updated successfully.'));
             } else {
@@ -101,12 +94,11 @@ class ProjectTagController extends BaseController
     }
 
     public function confirm()
     {
         $project = $this->getProject();
-        $tag_id = $this->request->getIntegerParam('tag_id');
-        $tag = $this->tagModel->getById($tag_id);
+        $tag = $this->getProjectTag($project);
 
         $this->response->html($this->template->render('project_tag/remove', array(
             'tag'     => $tag,
             'project' => $project,
         )));
@@ -114,18 +106,13 @@ class ProjectTagController extends BaseController
 
     public function remove()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $tag_id = $this->request->getIntegerParam('tag_id');
-        $tag = $this->tagModel->getById($tag_id);
-
-        if ($tag['project_id'] != $project['id']) {
-            throw new AccessForbiddenException();
-        }
+        $tag = $this->getProjectTag($project);
 
-        if ($this->tagModel->remove($tag_id)) {
+        if ($this->tagModel->remove($tag['id'])) {
             $this->flash->success(t('Tag removed successfully.'));
         } else {
             $this->flash->failure(t('Unable to remove this tag.'));
         }
 
diff --git a/app/Controller/SwimlaneController.php b/app/Controller/SwimlaneController.php
index 0d81d83cc..e6368b248 100644
--- a/app/Controller/SwimlaneController.php
+++ b/app/Controller/SwimlaneController.php
@@ -1,39 +1,19 @@
 <?php
 
 namespace Kanboard\Controller;
 
 use Kanboard\Core\Controller\AccessForbiddenException;
-use Kanboard\Core\Controller\PageNotFoundException;
-use Kanboard\Model\SwimlaneModel;
 
 /**
  * Swimlanes Controller
  *
  * @package Kanboard\Controller
  * @author  Frederic Guillot
  */
 class SwimlaneController extends BaseController
 {
-    /**
-     * Get the swimlane (common method between actions)
-     *
-     * @access private
-     * @return array
-     * @throws PageNotFoundException
-     */
-    private function getSwimlane()
-    {
-        $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));
-
-        if (empty($swimlane)) {
-            throw new PageNotFoundException();
-        }
-
-        return $swimlane;
-    }
-
     /**
      * List of swimlanes for a given project
      *
      * @access public
      */
@@ -76,10 +56,12 @@ class SwimlaneController extends BaseController
      */
     public function save()
     {
         $project = $this->getProject();
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
+
         list($valid, $errors) = $this->swimlaneValidator->validateCreation($values);
 
         if ($valid) {
             if ($this->swimlaneModel->create($project['id'], $values['name'], $values['description']) !== false) {
                 $this->flash->success(t('Your swimlane have been created successfully.'));
@@ -102,11 +84,11 @@ class SwimlaneController extends BaseController
      * @throws \Kanboard\Core\Controller\PageNotFoundException
      */
     public function edit(array $values = array(), array $errors = array())
     {
         $project = $this->getProject();
-        $swimlane = $this->getSwimlane();
+        $swimlane = $this->getSwimlane($project);
 
         $this->response->html($this->helper->layout->project('swimlane/edit', array(
             'values' => empty($values) ? $swimlane : $values,
             'errors' => $errors,
             'project' => $project,
@@ -119,12 +101,15 @@ class SwimlaneController extends BaseController
      * @access public
      */
     public function update()
     {
         $project = $this->getProject();
-
+        $swimlane = $this->getSwimlane($project);
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
+        $values['id'] = $swimlane['id'];
+
         list($valid, $errors) = $this->swimlaneValidator->validateModification($values);
 
         if ($valid) {
             if ($this->swimlaneModel->update($values['id'], $values)) {
                 $this->flash->success(t('Swimlane updated successfully.'));
@@ -143,11 +128,11 @@ class SwimlaneController extends BaseController
      * @access public
      */
     public function confirm()
     {
         $project = $this->getProject();
-        $swimlane = $this->getSwimlane();
+        $swimlane = $this->getSwimlane($project);
 
         $this->response->html($this->helper->layout->project('swimlane/remove', array(
             'project' => $project,
             'swimlane' => $swimlane,
         )));
@@ -160,13 +145,13 @@ class SwimlaneController extends BaseController
      */
     public function remove()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
+        $swimlane = $this->getSwimlane($project);
 
-        if ($this->swimlaneModel->remove($project['id'], $swimlane_id)) {
+        if ($this->swimlaneModel->remove($project['id'], $swimlane['id'])) {
             $this->flash->success(t('Swimlane removed successfully.'));
         } else {
             $this->flash->failure(t('Unable to remove this swimlane.'));
         }
 
@@ -180,13 +165,13 @@ class SwimlaneController extends BaseController
      */
     public function disable()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
+        $swimlane = $this->getSwimlane($project);
 
-        if ($this->swimlaneModel->disable($project['id'], $swimlane_id)) {
+        if ($this->swimlaneModel->disable($project['id'], $swimlane['id'])) {
             $this->flash->success(t('Swimlane updated successfully.'));
         } else {
             $this->flash->failure(t('Unable to update this swimlane.'));
         }
 
@@ -200,13 +185,13 @@ class SwimlaneController extends BaseController
      */
     public function enable()
     {
         $this->checkCSRFParam();
         $project = $this->getProject();
-        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
+        $swimlane = $this->getSwimlane($project);
 
-        if ($this->swimlaneModel->enable($project['id'], $swimlane_id)) {
+        if ($this->swimlaneModel->enable($project['id'], $swimlane['id'])) {
             $this->flash->success(t('Swimlane updated successfully.'));
         } else {
             $this->flash->failure(t('Unable to update this swimlane.'));
         }
 
diff --git a/app/Controller/TaskCreationController.php b/app/Controller/TaskCreationController.php
index 0d808c54c..d050a60df 100644
--- a/app/Controller/TaskCreationController.php
+++ b/app/Controller/TaskCreationController.php
@@ -47,10 +47,11 @@ class TaskCreationController extends BaseController
      */
     public function save()
     {
         $project = $this->getProject();
         $values = $this->request->getValues();
+        $values['project_id'] = $project['id'];
 
         list($valid, $errors) = $this->taskValidator->validateCreation($values);
 
         if (! $valid) {
             $this->flash->failure(t('Unable to create your task.'));
diff --git a/app/Template/action_creation/create.php b/app/Template/action_creation/create.php
index 862ee4746..a1169dca1 100644
--- a/app/Template/action_creation/create.php
+++ b/app/Template/action_creation/create.php
@@ -1,11 +1,10 @@
 <div class="page-header">
     <h2><?= t('Add an action') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('ActionCreationController', 'event', array('project_id' => $project['id'])) ?>">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Action'), 'action_name') ?>
     <?= $this->form->select('action_name', $available_actions, $values) ?>
 
     <?= $this->modal->submitButtons(array(
diff --git a/app/Template/action_creation/event.php b/app/Template/action_creation/event.php
index e41665483..2ea72612a 100644
--- a/app/Template/action_creation/event.php
+++ b/app/Template/action_creation/event.php
@@ -3,11 +3,10 @@
 </div>
 
 <form method="post" action="<?= $this->url->href('ActionCreationController', 'params', array('project_id' => $project['id'])) ?>">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->hidden('action_name', $values) ?>
 
     <?= $this->form->label(t('Action'), 'action_name') ?>
     <?= $this->form->select('action_name', $available_actions, $values, array(), array('disabled')) ?>
 
diff --git a/app/Template/action_creation/params.php b/app/Template/action_creation/params.php
index 0cc98f501..6c30d6c60 100644
--- a/app/Template/action_creation/params.php
+++ b/app/Template/action_creation/params.php
@@ -3,11 +3,10 @@
 </div>
 
 <form method="post" action="<?= $this->url->href('ActionCreationController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->hidden('event_name', $values) ?>
     <?= $this->form->hidden('action_name', $values) ?>
 
     <?= $this->form->label(t('Action'), 'action_name') ?>
     <?= $this->form->select('action_name', $available_actions, $values, array(), array('disabled')) ?>
diff --git a/app/Template/category/create.php b/app/Template/category/create.php
index b12ff7fa7..b32a770c8 100644
--- a/app/Template/category/create.php
+++ b/app/Template/category/create.php
@@ -1,11 +1,10 @@
 <div class="page-header">
     <h2><?= t('Add a new category') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('CategoryController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Category Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?>
 
     <?= $this->modal->submitButtons() ?>
diff --git a/app/Template/category/edit.php b/app/Template/category/edit.php
index 108826f3b..9ad5a9e99 100644
--- a/app/Template/category/edit.php
+++ b/app/Template/category/edit.php
@@ -3,13 +3,10 @@
 </div>
 
 <form method="post" action="<?= $this->url->href('CategoryController', 'update', array('project_id' => $project['id'], 'category_id' => $values['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('id', $values) ?>
-    <?= $this->form->hidden('project_id', $values) ?>
-
     <?= $this->form->label(t('Category Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?>
 
     <?= $this->form->label(t('Description'), 'description') ?>
     <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?>
diff --git a/app/Template/column/create.php b/app/Template/column/create.php
index aad9606bd..2b0c4641e 100644
--- a/app/Template/column/create.php
+++ b/app/Template/column/create.php
@@ -2,12 +2,10 @@
     <h2><?= t('Add a new column') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('ColumnController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('project_id', $values) ?>
-
     <?= $this->form->label(t('Title'), 'title') ?>
     <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?>
 
     <?= $this->form->label(t('Task limit'), 'task_limit') ?>
     <?= $this->form->number('task_limit', $values, $errors, array('tabindex="2"')) ?>
diff --git a/app/Template/column/edit.php b/app/Template/column/edit.php
index e590b5cc7..25cf60c9c 100644
--- a/app/Template/column/edit.php
+++ b/app/Template/column/edit.php
@@ -3,13 +3,10 @@
 </div>
 
 <form method="post" action="<?= $this->url->href('ColumnController', 'update', array('project_id' => $project['id'], 'column_id' => $column['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('id', $values) ?>
-    <?= $this->form->hidden('project_id', $values) ?>
-
     <?= $this->form->label(t('Title'), 'title') ?>
     <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?>
 
     <?= $this->form->label(t('Task limit'), 'task_limit') ?>
     <?= $this->form->number('task_limit', $values, $errors) ?>
diff --git a/app/Template/custom_filter/create.php b/app/Template/custom_filter/create.php
index 24e896eef..724cbc85a 100644
--- a/app/Template/custom_filter/create.php
+++ b/app/Template/custom_filter/create.php
@@ -1,11 +1,10 @@
 <div class="page-header">
     <h2><?= t('Add a new filter') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('CustomFilterController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="100"')) ?>
 
     <?= $this->form->label(t('Filter'), 'filter') ?>
diff --git a/app/Template/custom_filter/edit.php b/app/Template/custom_filter/edit.php
index b64dee53b..786e0c91d 100644
--- a/app/Template/custom_filter/edit.php
+++ b/app/Template/custom_filter/edit.php
@@ -3,13 +3,11 @@
 </div>
 
 <form method="post" action="<?= $this->url->href('CustomFilterController', 'update', array('project_id' => $filter['project_id'], 'filter_id' => $filter['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('id', $values) ?>
     <?= $this->form->hidden('user_id', $values) ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="100"')) ?>
 
     <?= $this->form->label(t('Filter'), 'filter') ?>
diff --git a/app/Template/project_edit/show.php b/app/Template/project_edit/show.php
index d4d0f8a64..8b85f0105 100644
--- a/app/Template/project_edit/show.php
+++ b/app/Template/project_edit/show.php
@@ -7,11 +7,10 @@
         <h2><?= t('Edit project') ?></h2>
     </div>
 <?php endif ?>
 <form method="post" action="<?= $this->url->href('ProjectEditController', 'update', array('project_id' => $project['id'], 'redirect' => 'edit')) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('id', $values) ?>
 
     <fieldset>
         <legend><?= t('General') ?></legend>
 
         <?= $this->form->label(t('Name'), 'name') ?>
diff --git a/app/Template/project_tag/create.php b/app/Template/project_tag/create.php
index a0e6243b7..6765e8fc8 100644
--- a/app/Template/project_tag/create.php
+++ b/app/Template/project_tag/create.php
@@ -1,11 +1,10 @@
 <div class="page-header">
     <h2><?= t('Add new tag') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('ProjectTagController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?>
 
     <?= $this->modal->submitButtons() ?>
diff --git a/app/Template/project_tag/edit.php b/app/Template/project_tag/edit.php
index 8cb1e2091..29290c0c9 100644
--- a/app/Template/project_tag/edit.php
+++ b/app/Template/project_tag/edit.php
@@ -1,12 +1,10 @@
 <div class="page-header">
     <h2><?= t('Edit a tag') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('ProjectTagController', 'update', array('tag_id' => $tag['id'], 'project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('id', $values) ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?>
 
     <?= $this->modal->submitButtons() ?>
diff --git a/app/Template/swimlane/create.php b/app/Template/swimlane/create.php
index 7d05e731b..5ff8cbeec 100644
--- a/app/Template/swimlane/create.php
+++ b/app/Template/swimlane/create.php
@@ -1,12 +1,10 @@
 <div class="page-header">
     <h2><?= t('Add a new swimlane') ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('SwimlaneController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
-
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?>
 
     <?= $this->form->label(t('Description'), 'description') ?>
diff --git a/app/Template/swimlane/edit.php b/app/Template/swimlane/edit.php
index c1c41196d..b1d713ee5 100644
--- a/app/Template/swimlane/edit.php
+++ b/app/Template/swimlane/edit.php
@@ -1,16 +1,12 @@
 <div class="page-header">
     <h2><?= t('Swimlane modification for the project "%s"', $project['name']) ?></h2>
 </div>
 
 <form method="post" action="<?= $this->url->href('SwimlaneController', 'update', array('project_id' => $project['id'], 'swimlane_id' => $values['id'])) ?>" autocomplete="off">
-
     <?= $this->form->csrf() ?>
 
-    <?= $this->form->hidden('id', $values) ?>
-    <?= $this->form->hidden('project_id', $values) ?>
-
     <?= $this->form->label(t('Name'), 'name') ?>
     <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?>
 
     <?= $this->form->label(t('Description'), 'description') ?>
     <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?>
diff --git a/app/Template/task_creation/show.php b/app/Template/task_creation/show.php
index e957087f5..cc9277933 100644
--- a/app/Template/task_creation/show.php
+++ b/app/Template/task_creation/show.php
@@ -1,11 +1,10 @@
 <div class="page-header">
     <h2><?= $this->text->e($project['name']) ?> &gt; <?= t('New task') ?><?= $this->task->getNewTaskDropdown($project['id'], $values['swimlane_id'], $values['column_id']) ?></h2>
 </div>
 <form method="post" action="<?= $this->url->href('TaskCreationController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
     <?= $this->form->csrf() ?>
-    <?= $this->form->hidden('project_id', $values) ?>
 
     <div class="task-form-container">
         <div class="task-form-main-column">
             <?= $this->task->renderTitleField($values, $errors) ?>
             <?= $this->task->renderDescriptionField($values, $errors) ?>

Vulnerable code:             'action' => $this->actionModel->getById($this->request->getIntegerParam('action_id')),
        $action = $this->actionModel->getById($this->request->getIntegerParam('action_id'));
        if (empty($values['action_name']) || empty($values['project_id'])) {
        if (empty($values['action_name']) || empty($values['project_id']) || empty($values['event_name'])) {
    /**
     * Get the category (common method between actions)
     *
     * @access private
     * @return array
     * @throws PageNotFoundException
     */
    private function getCategory()
    {
        $category = $this->categoryModel->getById($this->request->getIntegerParam('category_id'));

        if (empty($category)) {
            throw new PageNotFoundException();
        }

        return $category;
    }


        $category = $this->getCategory();
        $category = $this->getCategory();
        $category = $this->getCategory();
        $column = $this->columnModel->getById($this->request->getIntegerParam('column_id'));
            'column' => $this->columnModel->getById($this->request->getIntegerParam('column_id')),
        $project = $this->getProject();
        $column_id = $this->request->getIntegerParam('column_id');
        if ($this->columnModel->remove($column_id)) {
        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
use Kanboard\Core\Controller\AccessForbiddenException;

        if (empty($values)) {
            $values['project_id'] = $project['id'];
        }

        $tag_id = $this->request->getIntegerParam('tag_id');
        $tag = $this->tagModel->getById($tag_id);
        $tag_id = $this->request->getIntegerParam('tag_id');
        $tag = $this->tagModel->getById($tag_id);
        list($valid, $errors) = $this->tagValidator->validateModification($values);
        if ($tag['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }
        $tag_id = $this->request->getIntegerParam('tag_id');
        $tag = $this->tagModel->getById($tag_id);
        $tag_id = $this->request->getIntegerParam('tag_id');
        $tag = $this->tagModel->getById($tag_id);

        if ($tag['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }
        if ($this->tagModel->remove($tag_id)) {
use Kanboard\Core\Controller\PageNotFoundException;
use Kanboard\Model\SwimlaneModel;
    /**
     * Get the swimlane (common method between actions)
     *
     * @access private
     * @return array
     * @throws PageNotFoundException
     */
    private function getSwimlane()
    {
        $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));

        if (empty($swimlane)) {
            throw new PageNotFoundException();
        }

        return $swimlane;
    }

        $swimlane = $this->getSwimlane();

        $swimlane = $this->getSwimlane();
        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
        if ($this->swimlaneModel->remove($project['id'], $swimlane_id)) {
        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
        if ($this->swimlaneModel->disable($project['id'], $swimlane_id)) {
        $swimlane_id = $this->request->getIntegerParam('swimlane_id');
        if ($this->swimlaneModel->enable($project['id'], $swimlane_id)) {
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>
    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('id', $values) ?>
    <?= $this->form->hidden('project_id', $values) ?>

    <?= $this->form->hidden('project_id', $values) ?>
Fixed code: Security Issues:

* Avoid people to alter other project resources by changing form data

        $action = $this->getAction($project);
            'action' => $action,
        $action = $this->getAction($project);
        $values['project_id'] = $project['id'];
        if (empty($values['action_name'])) {
        $values['project_id'] = $project['id'];
        if (empty($values['action_name']) || empty($values['event_name'])) {
        $values['project_id'] = $project['id'];

    protected function getColumn(array $project)
    {
        $column = $this->columnModel->getById($this->request->getIntegerParam('column_id'));

        if (empty($column)) {
            throw new PageNotFoundException();
        }

        if ($column['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $column;
    }

    protected function getSwimlane(array $project)
    {
        $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));

        if (empty($swimlane)) {
            throw new PageNotFoundException();
        }

        if ($swimlane['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $swimlane;
    }

    protected function getCategory(array $project)
    {
        $category = $this->categoryModel->getById($this->request->getIntegerParam('category_id'));

        if (empty($category)) {
            throw new PageNotFoundException();
        }

        if ($category['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $category;
    }

    protected function getProjectTag(array $project)
    {
        $tag = $this->tagModel->getById($this->request->getIntegerParam('tag_id'));

        if (empty($tag)) {
            throw new PageNotFoundException();
        }

        if ($tag['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $tag;
    }

    protected function getAction(array $project)
    {
        $action = $this->actionModel->getById($this->request->getIntegerParam('action_id'));

        if (empty($action)) {
            throw new PageNotFoundException();
        }

        if ($action['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $action;
    }

    protected function getCustomFilter(array $project)
    {
        $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));

        if (empty($filter)) {
            throw new PageNotFoundException();
        }

        if ($filter['project_id'] != $project['id']) {
            throw new AccessForbiddenException();
        }

        return $filter;
    }
        $values['project_id'] = $project['id'];

        $category = $this->getCategory($project);
        $category = $this->getCategory($project);
        $values['project_id'] = $project['id'];
        $values['id'] = $category['id'];

        $category = $this->getCategory($project);
        $category = $this->getCategory($project);
        $values['project_id'] = $project['id'];
        $column = $this->getColumn($project);
        $column = $this->getColumn($project);

        $values['project_id'] = $project['id'];
        $values['id'] = $column['id'];
        $column = $this->getColumn($project);
            'column' => $column,
        $project = $this->getProject();
        $column = $this->getColumn($project);
        if ($this->columnModel->remove($column['id'])) {
        $values['project_id'] = $project['id'];
        $filter = $this->getCustomFilter($project);
        $filter = $this->getCustomFilter($project);
        $values['id'] = $filter['id'];
        $values['project_id'] = $project['id'];
        $values['id'] = $project['id'];

        $values['project_id'] = $project['id'];

        $tag = $this->getProjectTag($project);
        $tag = $this->getProjectTag($project);
        $values['project_id'] = $project['id'];
        $values['id'] = $tag['id'];
        list($valid, $errors) = $this->tagValidator->validateModification($values);
        $tag = $this->getProjectTag($project);
        $tag = $this->getProjectTag($project);
        if ($this->tagModel->remove($tag['id'])) {
        $values['project_id'] = $project['id'];

        $swimlane = $this->getSwimlane($project);
        $swimlane = $this->getSwimlane($project);
        $values['project_id'] = $project['id'];
        $values['id'] = $swimlane['id'];

        $swimlane = $this->getSwimlane($project);
        $swimlane = $this->getSwimlane($project);
        if ($this->swimlaneModel->remove($project['id'], $swimlane['id'])) {
        $swimlane = $this->getSwimlane($project);
        if ($this->swimlaneModel->disable($project['id'], $swimlane['id'])) {
        $swimlane = $this->getSwimlane($project);
        if ($this->swimlaneModel->enable($project['id'], $swimlane['id'])) {
        $values['project_id'] = $project['id'];