<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>spec/controllers/admin/articles_controller_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,22 +1,11 @@
 This is a list of issues that we need to fix before making a Mephisto
 release based on Rails 2.2.
 
+/ Try to upgrade to gem version of coderay
+  Make sure both old- and new-style plugins work
+  Security audit--see blow
   Drop TZInfo completely--see app/models/site.rb (fix docs, too)
-  Handle inactive users with named scopes, not acts_as_versioned
-  SECURITY: Don't ship :session_key in environment.rb!
-  Try to upgrade to gem version of coderay
   We need to review our TODO comments
-  Clean out the issue tracker: http://ar-code.lighthouseapp.com/projects/34-mephisto
-  rake rails:update:javascripts =&gt; complicated because mephisto/application.js depends on older versions.
-
-== Other issues
-
-When running the unit tests, we need theme directories in themes/site-$ID.
-But this namespace is also used by the development and production
-databases.  Are the test suites clobbering user themes accidentally?  See
-spec/models/membership_spec.rb for one quick-and-dirty workaround.  Perhaps
-for all non-production environments, we should prepend RAILS-ENV to the
-theme name, giving us themes/test-site-$ID?
 
 == Security
 
@@ -26,13 +15,39 @@ We need to do a basic security audit.
     Make sure cookies are HTTP-only whenever possible
     Can we restrict admin cookies to /admin ?
     Make sure logging out clears all relevant cookies and tokens
+    Check for session fixation attacks
+    Expire sessions after a while?
   Cross-site scripting
+/   Turn on protect_against_forgery
     Check all fields in comments
+      It looks like the failed comment error form has issues
     Check macro:* bodies and parameters
       filtered_column_code_macro
       filtered_column_flikr_macro
     Do we have trackback support to check?
     Do we need to upgrade to an industrial-strength HTML sanitizer?
     For now, we'll assume that users with access to /admin don't try XSS
+  Password change
+    Make change-password forms safe against CSRF
+    Require the user to enter the old password when changing it
+    Require password to change e-mail address
   Everything else
+/   Don't ship :session_key in environment.rb!
+    Do we need to override verifiable_request_format?
+    Review mass assignment in public controllers
     Review http://guides.rubyonrails.org/security.html
+    Can we use SafeERB?
+
+  Admin only
+    Filter file names for uploads
+    Review mass assignment in admin controllers
+
+== After next release
+
+  Handle inactive users with named scopes, not acts_as_versioned
+  Clean out the issue tracker
+    http://ar-code.lighthouseapp.com/projects/34-mephisto
+  rake rails:update:javascripts
+    (complicated because mephisto/application.js depends on older versions)
+  Fix sidebar tabs to do something sensible with unsaved articles
+</diff>
      <filename>RAILS-2.2-TODO.txt</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,9 @@ class Admin::BaseController &lt; ApplicationController
   before_filter :login_from_cookie
   before_filter :login_required, :except =&gt; :feed
 
+  # See ActionController::RequestForgeryProtection for details.
+  protect_from_forgery
+  
   protected
     def protect_action
       if request.get?</diff>
      <filename>app/controllers/admin/base_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -49,6 +49,12 @@ module ApplicationHelper
     ActionController::Base.relative_url_root
   end
 
+  # Make our form_authenticity_token token available to JavaScript.
+  def init_mephisto_authenticity_token
+    return &quot;&quot; unless protect_against_forgery?
+    &quot;Mephisto.token = '#{form_authenticity_token}';&quot;
+  end
+
   if RAILS_ENV == 'development'
     def gravatar_url_for(user, size = 80)
       'mephisto/avatar.gif'</diff>
      <filename>app/helpers/application_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@
     &lt;title&gt;&lt;%= site.title %&gt;: Admin &lt;%= controller.controller_name %&gt;&lt;/title&gt;
     &lt;%= stylesheet_link_tag 'mephisto/mephisto' %&gt;
     &lt;%= javascript_include_tag 'mephisto/prototype', 'mephisto/effects', 'mephisto/dragdrop', 'mephisto/lowpro', 'mephisto/application' %&gt;
-    &lt;script type=&quot;text/javascript&quot;&gt;Mephisto.root = '&lt;%= relative_url_root %&gt;';&lt;/script&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;Mephisto.root = '&lt;%= relative_url_root %&gt;'; &lt;%= init_mephisto_authenticity_token %&gt;&lt;/script&gt;
     &lt;%= yield :head %&gt;
   &lt;/head&gt;
   &lt;body&gt;</diff>
      <filename>app/views/layouts/application.rhtml</filename>
    </modified>
    <modified>
      <diff>@@ -3,4 +3,7 @@ config.whiny_nils    = true
 config.action_controller.consider_all_requests_local = true
 config.action_controller.perform_caching             = true
 config.action_controller.page_cache_directory        = File.join(RAILS_ROOT, 'tmp/cache')
-config.action_mailer.delivery_method = :test
\ No newline at end of file
+config.action_mailer.delivery_method = :test
+
+# Disable request forgery protection in test environment
+config.action_controller.allow_forgery_protection    = false</diff>
      <filename>config/environments/test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -28,7 +28,7 @@ module Mephisto
       map.overview 'admin/overview.xml', :controller =&gt; 'admin/overview', :action =&gt; 'feed'
       map.admin    'admin', :controller =&gt; 'admin/overview', :action =&gt; 'index'
       map.resources :assets, :path_prefix =&gt; '/admin', :controller =&gt; 'admin/assets', :member =&gt; { :add_bucket =&gt; :post },
-        :collection =&gt; { :latest =&gt; :post, :search =&gt; :post, :upload =&gt; :post, :clear_bucket =&gt; :post }
+        :collection =&gt; { :latest =&gt; [:get, :post], :search =&gt; [:get, :post], :upload =&gt; :post, :clear_bucket =&gt; :post }
       
       # Where oh where is my xmlrpc code?
       # map.connect 'xmlrpc', :controller =&gt; 'backend', :action =&gt; 'xmlrpc' </diff>
      <filename>lib/mephisto/routing.rb</filename>
    </modified>
    <modified>
      <diff>@@ -157,7 +157,7 @@ TinyTab.callbacks ={
   'search-files': function(q) {
     if(!q) return;
     $('spinner').show();
-    new Ajax.Request(Mephisto.root + '/admin/assets/search', {parameters: 'q=' + escape(q)});
+    new Ajax.Request(Mephisto.root + '/admin/assets/search', {method: 'get', parameters: 'q=' + escape(q)});
   }
 };
 
@@ -300,7 +300,8 @@ var ArticleForm = {
     var articleId = location.href.match(/\/([0-9]+)\/(edit|upload)/)[1];
     var attached  = $('attached-widget-' + assetId);
     if(attached) return;
-    new Ajax.Request('/admin/articles/attach/' + articleId + '/' + assetId);
+    new Ajax.Request('/admin/articles/attach/' + articleId + '/' + assetId,
+                     { parameters: 'authenticity_token=' + Mephisto.token });
     $$('.widget').each(function(asset) { if(assetId == asset.getAttribute('id').match(/-(\d+)$/)[1]) asset.addClassName('selected-widget'); });
   },
 
@@ -308,7 +309,9 @@ var ArticleForm = {
     var articleId = location.href.match(/\/([0-9]+)\/(edit|upload)/)[1];
     var attached  = $('attached-widget-' + assetId);
     var label     = $('attached-widget-version-' + assetId);
-    new Ajax.Request('/admin/articles/label/' + articleId + '/' + assetId + '?label=' + escape(label.value));
+    new Ajax.Request('/admin/articles/label/' + articleId + '/' + assetId,
+                     { parameters: 'authenticity_token=' + Mephisto.token +
+                         '&amp;label=' + escape(label.value) });
     if(attached) return;
   },
 
@@ -316,7 +319,8 @@ var ArticleForm = {
     var articleId = location.href.match(/\/([0-9]+)\/(edit|upload)/)[1];
     var attached  = $('attached-widget-' + assetId);
     if(!attached) return;
-    new Ajax.Request('/admin/articles/detach/' + articleId + '/' + assetId);
+    new Ajax.Request('/admin/articles/detach/' + articleId + '/' + assetId,
+                     { parameters: 'authenticity_token=' + Mephisto.token });
     new Effect.DropOut(attached, {afterFinish: function() { attached.remove(); }});
     $$('.widget').each(function(asset) { if(assetId == asset.getAttribute('id').match(/-(\d+)$/)[1]) asset.removeClassName('selected-widget'); });
   },</diff>
      <filename>public/javascripts/mephisto/application.js</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d558ba11e393b1bd444039d535aad3f9853e2592</id>
    </parent>
  </parents>
  <author>
    <name>Eric Kidd</name>
    <login>emk</login>
    <email>git@randomhacks.net</email>
  </author>
  <url>http://github.com/emk/mephisto/commit/dd9f41d2d4f168281b2e4eca12a525065b999f61</url>
  <id>dd9f41d2d4f168281b2e4eca12a525065b999f61</id>
  <committed-date>2008-12-10T14:46:03-08:00</committed-date>
  <authored-date>2008-12-10T14:44:21-08:00</authored-date>
  <message>Security: Turn on protect_from_forgery for admin/

The Rails protect_from_forgery function helps protect against cross-site
request forgery attacks, as described on Wikipedia:

  http://en.wikipedia.org/wiki/Cross-site_request_forgery

These attacks involve a hostile site sending requests to a site where
the user is logged in, exploiting the user's session cookie to do
various bad things.

The protect_from_forgery function works by requiring all POST (and PUT
and UPDATE) requests to have an authenticity_token parameter that
corresponds to a value in the user's session.  This is automatically
included in generated forms by the various form helpers, and checked in
the controller.  However, we still need to deal with some cases
(specifically Ajax.Request) manually.

We make several types of changes to get everything working again:
  - Some POST requests were changed to GET requests, when appropriate.
  - The token was added manually to other POST requests.  This was
    done using the new init_mephisto_authenticity_token.
  - Forgery protection was disabled in the test environment.

Note that we still need to review the authentication controller closely,
and eliminate various XSS attacks against our application before this
protection will do much good.

I tested this code by manually using the admin/ interface, editing
articles, adding users, and working with assets.  There's probably still
some breakage somewhere that I missed, so let me know if you have problems.

I also updated the TODO list for Rails 2.2 and added security-auditing
notes.</message>
  <tree>15c6118726423e5dc37552ad237d9e9644e1e73d</tree>
  <committer>
    <name>Eric Kidd</name>
    <login>emk</login>
    <email>git@randomhacks.net</email>
  </committer>
</commit>
