Bug 1026184: Port /security to bedrock.

Add an update_security_advisories command to pull
in and parse the advisroies from the git repository.
This commit is contained in:
Paul McLanahan 2014-08-06 12:00:14 -04:00
Родитель 53470c32ff
Коммит a730fe41da
40 изменённых файлов: 4063 добавлений и 6 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -31,3 +31,4 @@ james.ini
node_modules
/media/js/test/test-results.xml
bedrock/externalfiles/files_cache
mofo_security_advisories

Просмотреть файл

@ -12,7 +12,7 @@ def cache_control_expires(num_hours):
Set the appropriate Cache-Control and Expires headers for the given
number of hours.
"""
num_seconds = num_hours * 60 * 60
num_seconds = int(num_hours * 60 * 60)
def decorator(func):

Просмотреть файл

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
from util import page
import views
@ -15,8 +14,7 @@ urlpatterns = patterns('',
page('about', 'mozorg/about.html'),
page('book', 'mozorg/book.html'),
url('^credits/$', views.credits_view, name='mozorg.credits'),
url('^credits/faq/$', TemplateView.as_view(template_name='mozorg/credits-faq.html'),
name='mozorg.credits-faq'),
page('credits/faq', 'mozorg/credits-faq.html'),
url('^about/partnerships/$', views.partnerships, name='mozorg.partnerships'),
page('about/partnerships/distribution', 'mozorg/partnerships-distribution.html'),
page('about/history', 'mozorg/about/history.html'),

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,254 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import errno
import glob
import os
import re
import sys
from optparse import make_option
from subprocess import check_call, Popen, PIPE, STDOUT
from django.conf import settings
from django.core.cache import cache
from django.core.management.base import NoArgsCommand, BaseCommand
from django.db import transaction
from dateutil.parser import parse as parsedate
from raven.contrib.django.raven_compat.models import client as raven_client
from bedrock.security.models import Product, SecurityAdvisory
from bedrock.security.utils import chdir, parse_md_file
ADVISORIES_REPO = settings.MOFO_SECURITY_ADVISORIES_REPO
ADVISORIES_PATH = settings.MOFO_SECURITY_ADVISORIES_PATH
GIT = getattr(settings, 'GIT_BIN', 'git')
GIT_CLONE = (GIT, 'clone', ADVISORIES_REPO, ADVISORIES_PATH)
GIT_PULL = (GIT, 'pull', '--ff-only', 'origin', 'master')
GIT_GET_HASH = (GIT, 'rev-parse', 'HEAD')
SM_RE = re.compile('seamonkey', flags=re.IGNORECASE)
FNULL = open(os.devnull, 'w')
def fix_product_name(name):
if 'seamonkey' in name.lower():
name = SM_RE.sub('SeaMonkey', name, 1)
return name
def mkdir_p(path):
"""Mimic mkdir -p from *nix."""
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
@chdir(ADVISORIES_PATH)
def git_pull():
old_hash = get_current_git_hash()
check_call(GIT_PULL, stdout=FNULL, stderr=STDOUT)
new_hash = get_current_git_hash()
return old_hash, new_hash
@chdir(ADVISORIES_PATH)
def git_diff(old_hash, new_hash):
modified_files = []
if old_hash != new_hash:
proc = Popen((GIT, 'diff', '--name-only', old_hash, new_hash), stdout=PIPE)
git_out = proc.communicate()[0].split()
for mf in git_out:
if not mf.endswith('.md'):
continue
modified_files.append(os.path.join(ADVISORIES_PATH, mf))
return modified_files
@chdir(ADVISORIES_PATH)
def update_repo():
modified_files = []
deleted_files = []
mod_files = git_diff(*git_pull())
for mf in mod_files:
if os.path.exists(mf):
modified_files.append(mf)
else:
deleted_files.append(mf)
return modified_files, deleted_files
@chdir(ADVISORIES_PATH)
def get_current_git_hash():
p = Popen(GIT_GET_HASH, stdout=PIPE)
return p.communicate()[0].strip()
@transaction.commit_on_success
def delete_files(filenames):
ids = []
for filename in filenames:
match = re.search('(\d{4}-\d{2,3})\.md$', filename)
ids.append(match.group(1))
SecurityAdvisory.objects.filter(id__in=ids).delete()
@transaction.commit_on_success
def add_or_update_advisory(data, html):
"""
Add or update an advisory in the database.
:param data: dict of metadata about the advisory
:param html: HTML content of the advisory
:return: SecurityAdvisory
"""
mfsa_id = data.pop('mfsa_id')
year, order = [int(x) for x in mfsa_id.split('-')]
kwargs = {
'id': mfsa_id,
'title': data.pop('title'),
'impact': data.pop('impact'),
'reporter': data.pop('reporter', None),
'year': year,
'order': order,
'html': html,
}
datestr = data.pop('announced', None)
if datestr:
dateobj = parsedate(datestr).date()
kwargs['announced'] = dateobj
prodver_objs = []
for productname in data.pop('fixed_in'):
productname = fix_product_name(productname)
productobj, created = Product.objects.get_or_create(name=productname)
prodver_objs.append(productobj)
# discard products. we rely on fixed_in.
data.pop('products', None)
if data:
kwargs['extra_data'] = data
advisory = SecurityAdvisory(**kwargs)
advisory.save()
advisory.fixed_in.clear()
advisory.fixed_in.add(*prodver_objs)
return advisory
def update_db_from_file(filename):
"""
Parse file for YAML and Markdown and update database.
:raises: KeyError or ValueError
:param filename: path to markdown file.
:return: SecurityAdvisory instance
"""
return add_or_update_advisory(*parse_md_file(filename))
def clone_repo():
mkdir_p(ADVISORIES_PATH)
check_call(GIT_CLONE, stdout=FNULL, stderr=STDOUT)
def get_all_md_files():
return glob.glob(os.path.join(ADVISORIES_PATH, 'announce', '*', '*.md'))
class Command(NoArgsCommand):
help = 'Refresh database of MoFo Security Advisories.'
lock_key = 'command-lock:update_security_advisories'
option_list = BaseCommand.option_list + (
make_option('--force',
action='store_true',
dest='force',
default=False,
help='Force updating files even if up-to-date.'),
make_option('--quiet',
action='store_true',
dest='quiet',
default=False,
help='Do not print output to stdout.'),
make_option('--skip-git',
action='store_true',
dest='no_git',
default=False,
help='No update, just import files (implies --force)'),
)
def get_lock(self):
lock = cache.get(self.lock_key)
if not lock:
cache.set(self.lock_key, True, 60)
return True
return False
def release_lock(self):
cache.delete(self.lock_key)
def handle(self, *args, **options):
if self.get_lock():
super(Command, self).handle(*args, **options)
self.release_lock()
def handle_noargs(self, **options):
quiet = options['quiet']
force = options['force']
no_git = options['no_git']
if no_git:
force = True
cloned = False
def printout(msg, ending=None):
if not quiet:
self.stdout.write(msg, ending=ending)
if not no_git:
if not os.path.exists(ADVISORIES_PATH):
printout('Cloning repository.')
clone_repo()
cloned = True
elif force:
printout('Updating repository.')
git_pull()
if force or cloned:
printout('Reading all files.')
modified_files = get_all_md_files()
deleted_files = []
else:
printout('Updating repository and finding modified files.')
modified_files, deleted_files = update_repo()
if modified_files:
for mf in modified_files:
try:
update_db_from_file(mf)
except (KeyError, ValueError) as e:
print 'ERROR parsing %s: %s' % (mf, e)
raven_client.captureException()
continue
if not quiet:
sys.stdout.write('.')
sys.stdout.flush()
printout('\nUpdated {0} files.'.format(len(modified_files)))
if deleted_files:
delete_files(deleted_files)
printout('Deleted {0} files.'.format(len(deleted_files)))
if not modified_files and not deleted_files:
printout('Nothing to update.')

Просмотреть файл

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Product'
db.create_table(u'security_product', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=50)),
('slug', self.gf('django.db.models.fields.CharField')(max_length=50, db_index=True)),
('product', self.gf('django.db.models.fields.CharField')(max_length=50)),
('product_slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
))
db.send_create_signal(u'security', ['Product'])
# Adding model 'SecurityAdvisory'
db.create_table(u'security_securityadvisory', (
('id', self.gf('django.db.models.fields.CharField')(max_length=8, primary_key=True, db_index=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200)),
('impact', self.gf('django.db.models.fields.CharField')(max_length=100)),
('reporter', self.gf('django.db.models.fields.CharField')(max_length=100, null=True)),
('announced', self.gf('django.db.models.fields.DateField')(null=True)),
('year', self.gf('django.db.models.fields.SmallIntegerField')()),
('order', self.gf('django.db.models.fields.SmallIntegerField')()),
('extra_data', self.gf('django.db.models.fields.TextField')(default='{}')),
('html', self.gf('django.db.models.fields.TextField')()),
('last_modified', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, blank=True)),
))
db.send_create_signal(u'security', ['SecurityAdvisory'])
# Adding M2M table for field fixed_in on 'SecurityAdvisory'
m2m_table_name = db.shorten_name(u'security_securityadvisory_fixed_in')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('securityadvisory', models.ForeignKey(orm[u'security.securityadvisory'], null=False)),
('product', models.ForeignKey(orm[u'security.product'], null=False))
))
db.create_unique(m2m_table_name, ['securityadvisory_id', 'product_id'])
def backwards(self, orm):
# Deleting model 'Product'
db.delete_table(u'security_product')
# Deleting model 'SecurityAdvisory'
db.delete_table(u'security_securityadvisory')
# Removing M2M table for field fixed_in on 'SecurityAdvisory'
db.delete_table(db.shorten_name(u'security_securityadvisory_fixed_in'))
models = {
u'security.product': {
'Meta': {'ordering': "('slug',)", 'object_name': 'Product'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
'product': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'product_slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
},
u'security.securityadvisory': {
'Meta': {'ordering': "('-year', '-order')", 'object_name': 'SecurityAdvisory'},
'announced': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'extra_data': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
'fixed_in': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'advisories'", 'symmetrical': 'False', 'to': u"orm['security.Product']"}),
'html': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True', 'db_index': 'True'}),
'impact': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'last_modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'blank': 'True'}),
'order': ('django.db.models.fields.SmallIntegerField', [], {}),
'reporter': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'year': ('django.db.models.fields.SmallIntegerField', [], {})
}
}
complete_apps = ['security']

Просмотреть файл

Просмотреть файл

@ -0,0 +1,83 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.functional import total_ordering
from django_extensions.db.fields import ModificationDateTimeField
from django_extensions.db.fields.json import JSONField
from funfactory.urlresolvers import reverse
from product_details.version_compare import Version
@total_ordering
class Product(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = models.CharField(max_length=50, db_index=True)
product = models.CharField(max_length=50)
product_slug = models.SlugField()
class Meta:
ordering = ('slug',)
def __unicode__(self):
return self.name
@property
def name_tuple(self):
name, vers = self.name.rsplit(None, 1)
return name, Version(vers)
@property
def version(self):
return self.name_tuple[1]
def __lt__(self, other):
return self.name_tuple < other.name_tuple
def get_absolute_url(self):
return reverse('security.product-version-advisories',
kwargs={'slug': self.slug})
def save(self, force_insert=False, force_update=False,
using=None, update_fields=None):
self.product = self.name_tuple[0]
self.product_slug = slugify(self.product)
self.slug = '{0}-{1}'.format(self.product_slug, self.version)
super(Product, self).save(force_insert, force_update,
using, update_fields)
class SecurityAdvisory(models.Model):
id = models.CharField(max_length=8, primary_key=True, db_index=True)
title = models.CharField(max_length=200)
impact = models.CharField(max_length=100)
reporter = models.CharField(max_length=100, null=True)
announced = models.DateField(null=True)
year = models.SmallIntegerField()
order = models.SmallIntegerField()
fixed_in = models.ManyToManyField(Product, related_name='advisories')
extra_data = JSONField()
html = models.TextField()
last_modified = ModificationDateTimeField()
class Meta:
ordering = ('-year', '-order')
get_latest_by = 'last_modified'
def __unicode__(self):
return u'MFSA {0}'.format(self.id)
def get_absolute_url(self):
return reverse('security.advisory', kwargs={'pk': self.id})
@property
def impact_class(self):
return self.impact.lower().split(None, 1)[0]
@property
def products(self):
prods_set = set(v.product for v in self.fixed_in.all())
return sorted(prods_set)

Просмотреть файл

@ -0,0 +1,25 @@
{% extends "security/base.html" %}
{% block page_title %}Mozilla Foundation Secuirty Advisories{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Mozilla Foundation Security Advisories</h1>
</header>
<div itemprop="articleBody">
{% include "security/partials/impact_key.html" %}
<ul>
{% for group in advisories|groupby('announced')|reverse %}
<li>{{ group.grouper|datetime }}<ul>
{% for advisory in group.list %}
<li><a class="{{ advisory.impact_class }}" href="{{ advisory.get_absolute_url() }}">{{ advisory.id }}</a>: {{ advisory.title|safe }}</li>
{% endfor %}
</ul></li>
{% endfor %}
</ul>
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,36 @@
{% extends "security/base.html" %}
{% block page_title %}{{ advisory.title|striptags }}{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">{{ advisory.title|safe }}</h1>
</header>
<div itemprop="articleBody">
<dl>
<dt>Fixed in</dt>
<dd>
<ul>
{% for prodver in advisory.fixed_in.all() %}
<li>{{ prodver.name }}</li>
{% endfor %}
</ul>
</dd>
<dt>Products:</dt>
<dd>
<ul>
{% for prod in advisory.products %}
<li>{{ prod }}</li>
{% endfor %}
</ul>
</dd>
<dt>Impact:</dt>
<dd class="{{ advisory.impact_class }}">{{ advisory.impact }}</dd>
</dl>
{{ advisory.html|safe }}
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,47 @@
{# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. -#}
{% extends "base-resp.html" %}
{% block extrahead %}
{{ css('security') }}
{% endblock %}
{% block body_class %}sand{% endblock %}
{% block breadcrumbs %}
<nav class="breadcrumbs">
<a href="{{ url('mozorg.home') }}">{{ _('Home') }}</a> &gt;
<a href="{{ url('security.index') }}">{{ _('Mozilla Security') }}</a> &gt;
</nav>
{% endblock %}
{% block content %}
{% block main_feature %}{% endblock %}
{% block menu_bar %}{% endblock %}
<main id="main-content">
<div class="main-column">
{% block article %}{% endblock %}
</div>
{% block sidebar %}
<aside class="sidebar">
{% block side_nav %}
<nav>
<ul>
<li><a href="{{ url('security.index') }}">Security Center</a></li>
<li><a href="{{ url('security.advisories') }}">Security Advisories</a></li>
<li><a href="{{ url('security.known-vulnerabilities') }}">Known Vulnerabilities</a></li>
<li><a href="{{ url('security.bug-bounty') }}">Bug Bounty</a></li>
<li><a href="http://blog.mozilla.com/security/">Security Blog</a></li>
</ul>
</nav>
{% endblock %}
{% block side_extra %}
{% endblock %}
</aside>
{% endblock %}
</main>
{% endblock %}
{% block email_form %}{% endblock %}

Просмотреть файл

@ -0,0 +1,222 @@
{% extends "security/base.html" %}
{% block page_title %}Mozilla Web Application Security Bug Bounty FAQ{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Web Application Security Bug Bounty FAQ</h1>
</header>
<div itemprop="articleBody">
<p>This FAQ attempts to answer various questions about how the
Mozilla security bounty program relates to Web Applications.
This FAQ covers web applications and if you are reporting an issue
unrelated to a web application security vulnerability,
(e.g. a security issue in the Firefox browser), please see the original:
<a href="{{ url('security.bug-bounty-faq') }}">Security Bug Bounty Program FAQ.</a>
For more about the background of the bug bounty program see the
<a href="{{ url('security.bug-bounty') }}">official guidelines</a>
governing the program.</p>
<h3>General questions</h3>
<ul>
<li><a href="#why">Why do we include web applications as part
of our security Bug Bounty Program?</a></li>
<li><a href="#howto">How can I find potential vulnerabilities
and are there things I shouldn't do in trying to find them?</a></li>
<li><a href="#bounty-amount">Is the amount of the bounty
different for web applications vulnerabilities?</a></li>
<li><a href="#severity-ratings">Is there a list of severity ratings
with examples?</a></li>
</ul>
<h3>Eligible bugs</h3>
<ul>
<li><a href="#eligible-bugs">Which domains and web applications will be
considered to be part of the bug bounty?</a></li>
<li><a href="#issues">What types of issues will be considered as
part of the bounty program?</a></li>
<li><a href="#dos-bugs">Why won't you provide a reward for denial of service
bugs?</a></li>
<li><a href="#sites-not-listed">What about sites which are not listed?</a></li>
</ul>
<h3>Bug reporting</h3>
<ul>
<li><a href="#what-next">Once I have found a vulnerability,
what next?</a></li>
<li><a href="#nondisclosure">If I report the bug directly to you,
do I have to keep the bug confidential and not publish information
about it in order to receive a reward?</a></li>
<li><a href="#cooperation">I don't have the time or desire to work
with you further in investigating and fixing the bug; can I still get a
bug bounty reward?</a></li>
</ul>
<h2>General questions</h2>
<dl class="qandaset">
<dt class="question" id="why">Why do we include web applications
as part of our security Bug Bounty Program?</dt>
<dd class="answer">
<p>Many people are not aware that we have paid the bounty in the past on
web application security vulnerabilities which impact client security.
We are, however, expanding the bounty beyond web vulnerabilities which
just affect the client. We also feel we should have a more formal
structure around our web properties when it comes to paying a bounty
because our goal is to make our products and services more secure.</p>
</dd>
<dt class="question" id="howto">How can I find potential vulnerabilities
and are there things I shouldn't do in trying to find them?</dt>
<dd class="answer">
<p>We have received many questions around how to find web application
security issues. The most common concern is the use of automatic tools.
We ask that people don't use automatic tools against our web services
as it is important to maintain our services and availability. We do
encourage people to examine typical areas for vulnerabilities such as
authentication and session management. Since our code is opensource, you are
encourage to run on the software on your own server instance or just look
at the source code for potential issues.
(See the list below for the domains and applications which are in scope.)</p>
</dd>
<dt class="question" id="bounty-amount">Is the amount of the bounty
different for web applications vulnerabilities?</dt>
<dd class="answer">
<p>In the past we have not formally paid the bug bounty on web vulnerabilities
but we have paid the bounty for critical and extraordinary web application
vulnerabilities.
We are now going to include high severity web applications vulnerabilities.
So we are giving a range starting at $500 (US) for high severity and, in some
cases,
may pay up to $3000 (US) for extraordinary or critical vulnerabilities.
</p>
</dd>
<dt class="question" id="severity-ratings">Is there a list of severity
ratings
with examples?</dt>
<dd class="answer">
<p>Yes, here it is:
<a href="https://wiki.mozilla.org/WebAppSec/Web_App_Severity_Ratings">
Web Application Severity Ratings</a></p>
</dd>
</dl>
<h2>Eligible bugs</h2>
<dl class="qandaset">
<dt class="question" id="eligible-bugs">Which domains and web applications
will be considered to be part of the bug bounty?</dt>
<dd class="answer">
<p>Below is the list of domains under scope for Mozilla's web application
security
bug bounty. While this list doesn't include all the Mozilla web properties,
we do plan on adding to this list as we introduce our web security process to
other sites not included in this list.</p>
<ul>
<li>bugzilla.mozilla.org</li>
<li>*.services.mozilla.com</li>
<li>aus*.mozilla.org</li>
<li>www.mozilla.com/org</li>
<li>www.firefox.com</li>
<li>www.getfirefox.com</li>
<li>addons.mozilla.org</li>
<li>services.addons.mozilla.org</li>
<li>versioncheck.addons.mozilla.org</li>
<li>pfs.mozilla.org</li>
<li>download.mozilla.org</li>
</ul>
<p>The Mozilla Developer Network (developer.mozilla.org) has been removed from this
list due to site vandalism by researchers looking for security issues. It will be
added back at a later date when a test server is deployed to avoid negative impacts
on our primary reference site.</p>
</dd>
<br>
<dt class="question" id="sites-not-listed">What about sites which are not
listed?</dt>
<dd class="answer">
<p>If you find an issue with a site which is not "officially" part under the
web application bug bounty, we would still like to know. If the bug is
extraordinary, we might still consider the bug to be nominated for a bounty. In
the past we have paid for interesting bugs which are outside of normal
policy.</p>
</dd>
</dl>
<dl class="qandaset">
<dt class="question" id="issues">What types of issues will be considered
as part of the bounty program?</dt>
<dd class="answer">
<p>While there are many types of web vulnerabilities, the list below directly
affects our users and our infrastructure. These are just a few examples.</p>
<ul>
<li>Cross-Site Scripting (XSS)</li>
<li>Cross-Site Request Forgery (CSRF)</li>
<li>Injection / RFI/LFI</li>
</ul>
<p>The
<a href="https://wiki.mozilla.org/WebAppSec/Web_App_Severity_Ratings">
Web Application Severity Ratings</a> is consider to be the master list
for what will be part of the bug bounty. </p>
</dd>
<dt class="question" id="dos-bugs">Why won't you provide a reward
for denial of service bugs?</dt>
<dd class="answer">
<p>Because DoS bugs are generally less serious than other web application
security bugs and in many cases a DoS doesn't need to involve a technical
vulnerability within a web application. We have decided to concentrate our
limited resources on rewarding people who find what we consider to be more
serious security problems.</p>
</dd>
</dl>
<h2>Bug reporting</h2>
<dl class="qandaset">
<dt class="question" id="what-next">Once I have found a
vulnerability, what next?</dt>
<dd class="answer">
<p>Please <a href="https://bugzilla.mozilla.org/enter_bug.cgi">
file a bug</a> describing the security bug. The security check-box
should also be checked when filing the bug. Further details on the security
check-box can be found
<a
href=https://wiki.mozilla.org/WebAppSec/Web_App_Severity_Ratings#
Security_Group_Settings>here.</a>
</p>
<p>We also ask that you notify the <a
href="mailto:security@mozilla.org?subject=Web%20Security%20Bug%20Bounty:&lt;
DESCRIPTION&gt;">
Mozilla Security Group</a> by email and include the bug number and a brief
summary.
</p>
</dd>
<dt class="question" id="nondisclosure">If I report the bug
directly to you, do I have to keep the bug confidential and not publish
information about it in order to receive a reward?</dt>
<dd class="answer">
<p>No. We're rewarding you for finding a bug, not trying to buy
your silence. However if you report the bug through the standard
Mozilla process and haven't already published information about it then
we do ask that you follow the guidelines set forth in the official
policy on <a href="{{ url('mozorg.about.governance.policies.security.bugs') }}">handling
Mozilla security bugs</a>. Under this policy security-sensitive bug
reports in our Bugzilla system may be kept private for a limited period
of time to give us a chance to fix the bug before the bug is made
public, with an option for the bug reporter (or others) to open the bug
to public view earlier whenever circumstances warrant it (e.g., if you feel your
bug report is being completely ignored).However, in the interest of
protecting our users, we would appreciate a reasonable amount of
time to address the issue before the information is publicly disclosed.</p>
</dd>
<dt class="question" id="cooperation">I don't have the time or
desire to work with you further in investigating and fixing the bug;
can I still get a bug bounty reward?</dt>
<dd class="answer">
<p>Yes. Again, we're rewarding you for finding a bug, not trying to
buy your cooperation. However we do invite you to work together with
us, and we hope that you'll accept that offer in the spirit in which it
was intended. In return you'll get the opportunity to work as a full
member of the team fixing your bug and see "from the inside" exactly
how Mozilla security bugs get resolved.</p>
</dd>
</dl>
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,283 @@
{% extends "security/base.html" %}
{% block page_title %}Mozilla Security Bug Bounty Program{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Bug Bounty Program FAQ</h1>
</header>
<div itemprop="articleBody">
<p>This FAQ attempts to answer various questions about the Mozilla
security bug bounty program sponsored by the Mozilla Foundation. For
more information see the <a href="https://blog.mozilla.org/press/2004/08/mozilla-foundation-announces-security-bug-bounty-program/">original
announcement</a> and the <a href="{{ url('security.bug-bounty') }}">official
guidelines</a> governing the program.</p>
<h3>General questions</h3>
<ul>
<li><a href="#why">Why is the Mozilla Foundation doing this?</a></li>
<li><a href="#eligibility">Are Mozilla developers eligible for the bug bounty
reward?</a></li>
</ul>
<h3>Eligible software</h3>
<ul>
<li><a href="#other-products">Can I get the bug bounty reward if I
discover a bug in Camino, Galeon, K-Meleon, Netscape 7, or other
products based on Mozilla code?</a></li>
<li><a href="#bugzilla-etc">Does the bug bounty cover bugs found in
Bugzilla, Tinderbox, Bonsai, and other software created and distributed
as part of the Mozilla project?</a></li>
<li><a href="#most-recent">What do you mean by the "most recent
version" of Firefox, Firefox for Android, and/or Thunderbird?</a></li>
<li><a href="#older-releases">Can I get the bug bounty reward if I
discover a bug in an older release of Firefox, Firefox for Android,
and/or Thunderbird?</a></li>
<li><a href="#development-releases">Can I get the bug bounty reward if I
discover a bug in a pre-release version of Firefox, Firefox for Android, or
Thunderbird?</a></li>
<li><a href="#third-party-releases">Can I get the bug bounty reward
if I discover a bug that occurs in a third-party release of Firefox,
Firefox for Android, and/or Thunderbird (e.g., a localized build, optimized
build, or third-party Firefox, Firefox for Android, or Thunderbird
distribution)?</a></li>
<li><a href="#platform-specific">Can I get the bug bounty reward if I
discover a bug that occurs only on a particular operating system?</a></li>
</ul>
<h3>Eligible bugs</h3>
<ul>
<li><a href="#eligible-bugs">What types of security bugs are eligible?</a></li>
<li><a href="#dos-bugs">Why won't you provide a reward for denial of
service bugs?</a></li>
</ul>
<h3>Bug reporting, etc.</h3>
<ul>
<li><a href="#already-published">I've already published information
about the bug, and didn't go through the Mozilla bug process; can I
still get a reward?</a></li>
<li><a href="#nondisclosure">If I report the bug directly to you, do
I have to keep the bug confidential and not publish information about
it in order to receive a reward?</a></li>
<li><a href="#cooperation">I don't have the time or desire to work
with you further in investigating and fixing the bug; can I still get a
bug bounty reward?</a></li>
</ul>
<h2>General questions</h2>
<dl class="qandaset">
<dt class="question" id="why">Why is the Mozilla Foundation doing
this?</dt>
<dd class="answer">
<p>Because we want to encourage more people to find and report
security bugs in our products, so that we can make our products even
more secure than they already are. It's as simple as that.</p>
</dd>
<dt class="question" id="eligibility">Are Mozilla developers
eligible for the bug bounty reward?</dt>
<dd class="answer">
<p>Yes. Anyone is eligible to receive a reward except for employees of
the Mozilla Foundation and its subsidiaries and the creators and
reviewers of the code in which the bug was found. However, as noted in
the policy, if you found this bug as part of your job (in other words,
while being paid to work on Mozilla) then we'd appreciate it if you
would not apply for the bounty, in order to preserve our limited funds
for rewarding volunteer contributors.</p>
</dd>
</dl>
<h2>Eligible software</h2>
<dl class="qandaset">
<dt class="question" id="other-products">Can I get the bug
bounty reward if I discover a bug in Camino, Galeon, K-Meleon, Netscape
7, Mozilla Suite, SeaMonkey, or other products based on Mozilla code?</dt>
<dd class="answer">
<p>Only if we can reproduce the problem in the most recent version
of Firefox, Firefox for Android, and/or Thunderbird.</p>
</dd>
<dt class="question" id="bugzilla-etc">Does the bug bounty cover
bugs found in Bugzilla, Tinderbox, Bonsai, and other software created
and distributed as part of the Mozilla project?</dt>
<dd class="answer">
<p>No. We have decided to use our limited resources to focus on our
end-user products, as opposed to the other software produced and used
by the Mozilla project.</p>
</dd>
<dt class="question" id="most-recent">What do you mean by the
"most recent version" of Firefox, Firefox for Android, and/or
Thunderbird?</dt>
<dd class="answer">
<p>In general we mean the releases available for download on the <a
href="{{ url('mozorg.products') }}">mozilla.org download pages</a> at the time the
bug was reported. However we will also consider paying rewards for
security bugs as discussed in the questions and answers below.</p>
</dd>
<dt class="question" id="older-releases">Can I get the bug
bounty reward if I discover a bug in an older release of Firefox,
Firefox for Android, and/or Thunderbird?</dt>
<dd class="answer">
<p>In general bugs found in earlier releases are eligible for a
reward only if we can reproduce the problem using the most recent
version.</p>
<p>However as a special exception we will also consider paying
rewards for bugs found in the most recent releases from designated
stable branches (e.g., from the Mozilla 17 Extended Support Release branch while
supported) if the bugs are not present in the most recent version but
were never recognized and fixed as security bugs. (For example, the bug
might be in code associated with a feature that was removed and/or
heavily modified in the most recent version, and might have been
"fixed" solely as a byproduct of other unrelated changes.)</p>
</dd>
<dt class="question" id="development-releases">Can I get the bug bounty
reward if I discover a bug in a pre-release version of Firefox, Firefox for
Android, or Thunderbird?</dt>
<dd class="answer">
<p>Yes, as long as the bug otherwise meets the published bug bounty
program guidelines. Bugs found in Aurora and Beta releases of Firefox and
Firefox for Android, EarlyBird and Beta releases of Thunderbird are eligible as
long the bug is reproducible in the latest nightly mozilla-central build and has
not been previously reported.</p>
</dd>
<dt class="question" id="third-party-releases">Can I get the bug
bounty reward if I discover a bug that occurs in a third-party release
of Firefox, Firefox for Android, and/or Thunderbird (e.g., a localized
build, optimized build, or third-party Firefox, Firefox for Android, or
Thunderbird distribution)?</dt>
<dd class="answer">
<p>Yes, if the bug can be reproduced in an official Mozilla
Foundation release and otherwise meets the published guidelines.</p>
</dd>
<dt class="question" id="platform-specific">Can I get the bug
bounty reward if I discover a bug that occurs only on a particular
operating system?</dt>
<dd class="answer">
<p>Yes, if the operating system is officially supported by the most
recent version of the product for which you're reporting the bug. (For
a list of supported operating systems and hardware configurations see
the system requirements for the
<a href="{{ url('firefox.sysreq') }}">Firefox
</a>, <a href="https://support.mozilla.org/kb/will-firefox-work-my-mobile-device">Firefox for
Android</a>, and
{# There isn't a good url for latest Tbird sys-req. #}
{# TODO Make a latest Tbird sys-req url. #}
<a href="/thunderbird/">Thunderbird</a>.)</p>
</dd>
</dl>
<h2>Eligible bugs</h2>
<dl class="qandaset">
<dt class="question" id="eligible-bugs">What types of security bugs are
eligible?</dt>
<dd class="answer">
<p>Reproducible security bugs that are determined to be rated
<a href="https://wiki.mozilla.org/Security_Severity_Ratings">sec-critical or
sec-high</a> are eligible. In general we consider critical security bugs to be
those that allow execution of arbitrary code on users' systems, while high
severity security bugs allow access to users' confidential information. In the
latter case we consider bugs to be sec-high only if they potentially expose
high-value personal information (e.g., passwords, credit card numbers, and the
like); in the context of the bug bounty program we do not consider bugs to be
sec-high if they potentially expose only lower-value information (e.g., browsing
history) or information that would be useful primarily for other exploits
(e.g., the names of files or directories on the user's system).</p>
<p>Finally, in general we do not consider bugs that permit only denial of
service attacks to be eligible in the sense described above.</p>
</dd>
<dt class="question" id="dos-bugs">Why won't you provide a
reward for denial of service (DoS) bugs?</dt>
<dd class="answer">
<p>Because DoS bugs are generally less serious than other security
bugs (e.g., they typically do not lead to corruption or destruction of
user data, much less theft of data), and in many cases a DoS attack
does not involve an actual bug but simply misuse of standard product
features (e.g., putting up a web site with an excessive number of
graphics, sending excessively long mail messages, etc.). We have
decided to concentrate our limited resources on rewarding people who
find what we consider to be more serious security problems.</p>
</dd>
</dl>
<h2>Bug reporting, etc.</h2>
<dl class="qandaset">
<dt class="question" id="already-published">I've already
published information about the bug, and didn't go through the Mozilla
bug process; can I still get a reward?</dt>
<dd class="answer">
<p>Yes, as long as the bug report occurred after the official
announcement of the bug bounty program on August 2, 2004, and otherwise
meets the published bug bounty program guidelines (e.g., the bug has
not been reported previously and is reproducible in the most recent
version of the affected product).</p>
<p>However we do encourage people to <a
href="mailto:security@mozilla.org?subject=Security%20exploit%20submission">
report bugs directly</a> to the Mozilla project, in order to ensure that the
bug is made known as soon as possible to the people who can fix it.</p>
</dd>
<dt class="question" id="nondisclosure">If I report the bug
directly to you, do I have to keep the bug confidential and not publish
information about it in order to receive a reward?</dt>
<dd class="answer">
<p>No. We're rewarding you for finding a bug, not trying to buy
your silence. However if you report the bug through the standard
Mozilla process and haven't already published information about it then
we do ask that you follow the guidelines set forth in the official
policy on <a href="{{ url('mozorg.about.governance.policies.security.bugs') }}">handling
Mozilla security bugs</a>. Under this policy security-sensitive bug
reports in our Bugzilla system may be kept private for a limited period
of time to give us a chance to fix the bug before the bug is made
public, with an option for the bug reporter (or others) to open the bug
to public view earlier whenever circumstances warrant it (e.g., if your
bug report is being completely ignored).</p>
</dd>
<dt class="question" id="cooperation">I don't have the time or
desire to work with you further in investigating and fixing the bug;
can I still get a bug bounty reward?</dt>
<dd class="answer">
<p>Yes. Again, we're rewarding you for finding a bug, not trying to
buy your cooperation. However we do invite you to work together with
us, and we hope that you'll accept that offer in the spirit in which it
was intended. In return you'll get the opportunity to work as a full
member of the team fixing your bug and see "from the inside" exactly
how Mozilla security bugs get resolved.</p>
</dd>
</dl>
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,129 @@
{% extends "security/base.html" %}
{% block page_title %}Mozilla Security Bug Bounty Program{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Bug Bounty Program</h1>
</header>
<div itemprop="articleBody">
<h2>Introduction</h2>
<p>The Mozilla Security Bug Bounty Program is designed to encourage
security research in Mozilla software and to reward those who help us create
the safest Internet clients in existence.</p>
<p>Many thanks to <a href="http://en.wikipedia.org/wiki/Linspire">Linspire</a>
and <a href="http://www.markshuttleworth.com/">Mark Shuttleworth</a>, who
provided start-up funding for this endeavor.</p>
<h2>General Bounty Guidelines</h2>
<p>Mozilla will pay a bounty for certain client and service security bugs,
as detailed below. All security bugs must follow the following general
criteria to be eligible:</p>
<ul>
<li>Security bug must be original and previously unreported.</li>
<li>Security bug must be a remote exploit.</li>
<li>Submitter must not be the author of the buggy code nor otherwise involved
in its
contribution to the Mozilla project (such as by providing check-in
reviews).
</li>
<li>Employees of the Mozilla Foundation and its subsidiaries are
ineligible.
</li>
</ul>
<p>If you found the security bug as part of your job (in other words, while
being
paid to work on Mozilla code) then we would appreciate your not applying
for the bounty. Our funds are limited and we would like this program to
focus on people who are not otherwise paid to work on the Mozilla project.</p>
<p>Mozilla reserves the right to not give a bounty payment if we believe
the actions of the reporter have endangered the security of Mozilla's end
users.</p>
<p>If two or more people report the bug together the
reward will be divided among them. </p>
<h2>Client Reward Guidelines</h2>
<p>The bounty for valid critical client security bugs will be $3000 (US) cash
reward and a Mozilla T-shirt. The bounty will be awarded for
<a href="https://wiki.mozilla.org/Security_Severity_Ratings">sec-critical and
sec-high</a> severity security bugs that meet the following criteria:</p>
<ul>
<li>Security bug is present in the most recent main development (i.e.,
Aurora, Beta or EarlyBird, and nightly mozilla-central releases) or released
versions of Firefox, Thunderbird, Firefox for Android, or in Mozilla services
which could compromise users of those products, as released by Mozilla
Corporation.
</li>
<li>Security bugs in or caused by additional 3rd-party software (e.g.
plugins, extensions) are excluded from the Bug Bounty program.
</li>
</ul>
<p>More information about this program can be found in the
<a href="{{ url('security.bug-bounty-faq') }}">Client Security
Bug Bounty Program FAQ.</a>
<h2>Web Application and Services Reward Guidelines</h2>
<p>The bounty for valid web applications or services related security bugs,
we are giving a range starting at $500 (US) for high severity and, in some
cases,
may pay up to $3000 (US) for extraordinary or critical vulnerabilities.
We will also include a Mozilla T-shirt. The bounty will be awarded for
<a
href="https://wiki.mozilla.org/WebAppSec/Web_App_Severity_Ratings#
Web_Application_Severity_Ratings_Table">
sec-critical and sec-high</a> security bugs that meet the following
criteria:</p>
<ul>
<li>Security bug is present in the web properties outlined in the
<a href="{{ url('security.bug-bounty-faq-webapp') }}">Web Application Security Bounty
FAQ.</a></li>
<li>Security bug is on the list of sites which part of the bounty.
See the <a href="{{ url('security.bug-bounty-faq-webapp') }}#eligible-bugs">eligible bugs</a>
section of the <a href="{{ url('security.bug-bounty-faq-webapp') }}">Web Application Security
Bounty FAQ</a>
for the list of sites which is included under the bounty.</li>
</ul>
<p>More information about this program can be found in the
<a href="{{ url('security.bug-bounty-faq-webapp') }}">Web Application Security Bounty
FAQ.</a></p>
<h2>Process</h2>
<p>Please <a href="https://bugzilla.mozilla.org/enter_bug.cgi">file a bug</a> describing the
security bug; be sure to check the box near the bottom of the entry
form that marks this bug report as confidential. We encourage you
to attach a "proof of concept" testcase or link to the bug report that
demonstrates the vulnerability. While not required, such a testcase will
help us judge submissions more quickly and accurately.</p>
<p>Notify the
<a
href="mailto:security@mozilla.org?subject=Security%20Bug%20Bounty:&lt;DESCRIPTION&gt;">
Mozilla Security Group</a> by email and include the number of the bug you filed
and a brief summary. If you cannot file a bug include the full details
in the email and attach any proof of concept testcases or links.
Mozilla Foundation staff and the Mozilla Security Group will consider
your submission for the Security Bug Bounty and will contact you.</p>
<p>We ask that you be available to provide further information on the bug
as needed, and invite you to work together with Mozilla engineers in
reproducing, diagnosing, and fixing the bug. As part of this process we
will provide you full access to participate in our internal discussions
about the bug; for more information read our <a
href="{{ url('mozorg.about.governance.policies.security.bugs') }}">policy</a>
for handling security bugs.</p>
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,227 @@
{# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. -#}
{% extends "security/base.html" %}
{% block page_title_suffix %}{% endblock %}
{% block page_title %}{{ _('Mozilla Security') }}{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block body_id %}security-landing{% endblock %}
{% block main_feature %}
<hgroup id="main-feature" class="center">
<h1 class="large">{{ _('Mozilla Security') }}</h1>
</hgroup>
{% endblock %}
{% block side_nav %}{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Security Center</h1>
</header>
<div itemprop="articleBody">
<p>Whether you're using the Web or checking your email, you care about
your security and privacy. In the Mozilla project
<a href="{{ url('security.advisories') }}">we understand the importance of security</a>.
Here you will find alerts and announcements on security and privacy
issues, general tips for surfing the Web and using email more securely,
more information about how we maintain and enhance the security of our
products, and useful links for Web developers.</p>
<p>On this page:</p>
<ul class="toc">
<li><a href="#Security_Updates">Security Updates</a></li>
<li><a href="#Tips_for_secure_browsing">Tips for Secure Browsing</a></li>
<li><a href="#Tips_for_using_email_securely">Tips for Using Email Securely</a></li>
<li><a href="#For_Developers">For Developers: Contacting Mozilla</a>
(our <a href="#pgpkey">PGP key</a>)
</li>
</ul>
<h2 id="Security_Updates">Security Updates</h2>
<ul>
<li><a href="{{ url('security.advisories') }}">
Mozilla Foundation Security Advisories</a> for all products
</li>
<li><a href="{{ url('security.known-vulnerabilities') }}">
Known vulnerabilities</a> listed by product
</li>
<li><a href="http://blog.mozilla.com/">The Mozilla Blog</a> announces
all of our releases.
</li>
<li><a href="http://blog.mozilla.com/security/">The Mozilla Security Blog</a>
features security-related articles about Mozilla products.
</li>
</ul>
<p>The latest security updates will be delivered to most users
automatically. Users who have turned off automatic updates can use the
"Check for Updates..." item on the Help menu. If the menu item is disabled
your account does not have sufficient privileges to update Firefox--contact
the person who installed Firefox on your machine. Additional help is also
available through our <a href="http://support.mozilla.com/">Community
Support</a> site.</p>
<h2 id="Tips_for_secure_browsing">Tips for Secure Browsing</h2>
<ul>
<li>Always use the most current version of your
<a href="/firefox/">browser</a>.
</li>
<li>Check for the "lock" icon on the status bar that shows that you
are on a secured web site. Also check that the URL begins with
"https" in the location bar when making transactions online.
</li>
<li>In the Tools menu of Firefox, Tools &gt; Options... &gt; Privacy,
you can clear your information with one click of a button. This
is especially useful when using a computer in a public location.
</li>
<li>Perform transactions (like shopping or submitting personal
information) at sites that are well established and that are familiar
to you. If you're not familiar with a site, make sure that the
site has a privacy policy and information about the site's security
measures.
</li>
</ul>
<h2 id="Tips_for_using_email_securely">Tips for Using Email Securely</h2>
<ul>
<li>Be aware that it is extremely easy for someone to forge an email
message to make it appear as if the message has been sent by your bank,
a software vendor (e.g., Microsoft), or another entity with whom you do
business. If a message requests that you send your password or other
private information, or asks that you run or install an attached file,
then it is very likely that the message is not legitimate. When in
doubt, just mark the message as "junk" and delete it.
</li>
<li>Be cautious when clicking on links sent to you in email messages.
If you do click on such a link, double-check the name of the site as
shown in the location bar of the browser, and be especially careful if
the site name displayed is an IP address (e.g., "192.168.25.75")
instead of a domain name (e.g., "www.example.com"); in the former case
it is very likely the site is not legitimate. Don't enter any personal
information into forms displayed at such a site, and if you have any
concerns whatsoever about your security, just close the browser window.
</li>
</ul>
<h2 id="For_Developers">For Developers: Contacting Mozilla</h2>
<p>Report security-related bugs and learn more about how we secure our
products:</p>
<ul>
<li><strong>If you believe that you've found a Mozilla-related
security vulnerability, please report it by sending email to the
address security@mozilla.org.</strong> Note that your report may be
eligible for a reward; see below.
</li>
<li>For more information on how to report security vulnerabilities
and how the Mozilla community will respond to such reports, see our
<a href="{{ url('mozorg.about.governance.policies.security.bugs') }}">policy
for handling security bugs</a>.
</li>
<li>We want to make Firefox, Thunderbird, the Mozilla Suite, and
other Mozilla products as secure as possible, and want to encourage
research, study, timely disclosure, and rapid fixing of any serious
security vulnerabilities. We've established a
<a href="{{ url('security.bug-bounty') }}">Security Bug
Bounty Program</a> to reward people who help us reach that objective.
</li>
<li>Mozilla-based products include a default list of CA certificates
used when connecting to SSL-enabled servers and in other contexts. If you
are a CA and would like your CA certificate(s) considered for inclusion
in Mozilla, please see the <a href="{{ url('mozorg.about.governance.policies.security.certs.policy') }}">
Mozilla CA certificate policy</a>.
</li>
<li>We encourage you to learn more about our
<a href="/projects/security/">Mozilla security
projects</a> and participate in the development of security features
and capabilities in our products.
</li>
</ul>
<p>Press Contact: send mail to <em>press</em> at <em>mozilla dot com</em>.</p>
<p id="pgpkey">The PGP key for security@mozilla.org can be used to send encrypted mail
or to verify responses received from that address.</p>
<pre>
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
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
JdatyZglJXgcBKU=
=Ia2B
-----END PGP PUBLIC KEY BLOCK-----
</pre>
</div>
</article>
{% endblock %}

Просмотреть файл

@ -0,0 +1,73 @@
{% extends "security/base.html" %}
{% block page_title %}Known Vulnerabilities in Mozilla Products{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Known Vulnerabilities in Mozilla Products</h1>
</header>
<div itemprop="articleBody">
<p>The links below list security vulnerabilities known to affect
particular versions of Mozilla products and instructions on what users
can do to protect themselves. The lists will be added to when new security
problems are found. For a complete list not sorted by product or version
please see the <a href="{{ url('security.advisories') }}">
Mozilla Foundation Security Advisories</a>.</p>
<p>Please read
<a href="{{ url('mozorg.about.governance.policies.security.bugs') }}">
Mozilla.org's security bug policy</a> for information on how we handle
security bugs. If you have found a security problem which is not on this
list and has not already been filed as a bug in
<a href="https://bugzilla.mozilla.org/query.cgi">Bugzilla</a>,
or if you find errors or inconsistencies in this list, please
<a href="mailto:security@mozilla.org">mail us</a>.
If needed our PGP key can be found on the main
<a href="{{ url('security.index') }}#pgpkey">security</a> page.</p>
<h2>Product Advisories</h2>
<ul>
<li><a href="{{ url('security.product-advisories', slug='firefox') }}">Firefox</a></li>
<li><a href="{{ url('security.product-advisories', slug='firefox-esr') }}">Firefox ESR</a></li>
<li><a href="{{ url('security.product-advisories', slug='thunderbird') }}">Thunderbird</a></li>
<li><a href="{{ url('security.product-advisories', slug='thunderbird-esr') }}">Thunderbird ESR</a></li>
<li><a href="{{ url('security.product-advisories', slug='seamonkey') }}">SeaMonkey</a></li>
</ul>
<h2>Advisories for older products</h2>
<h3>Firefox</h3>
<ul>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-3.6') }}">Firefox 3.6</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-3.5') }}">Firefox 3.5</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-3.0') }}">Firefox 3.0</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-2.0') }}">Firefox 2.0</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-1.5') }}">Firefox 1.5</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='firefox-1.0') }}">Firefox 1.0</a></li>
</ul>
<h3>Thunderbird</h3>
<ul>
<li><a href="{{ url('security.product-version-advisories', slug='thunderbird-3.1') }}">Thunderbird 3.1</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='thunderbird-3.0') }}">Thunderbird 3.0</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='thunderbird-2.0') }}">Thunderbird 2.0</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='thunderbird-1.5') }}">Thunderbird 1.5</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='thunderbird-1.0') }}">Thunderbird 1.0</a></li>
</ul>
<h3>SeaMonkey</h3>
<ul>
<li><a href="{{ url('security.product-version-advisories', slug='seamonkey-2.0') }}">SeaMonkey 2.0</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='seamonkey-1.1') }}">SeaMonkey 1.1</a></li>
<li><a href="{{ url('security.product-version-advisories', slug='seamonkey-1.0') }}">SeaMonkey 1.0</a></li>
</ul>
<h3>Older</h3>
<ul>
<li><a href="{{ url('security.product-advisories', slug='mozilla-suite') }}">Mozilla Suite 1.7</a></li>
<li><a href="{{ url('security.older-vulnerabilities') }}">Older vulnerabilities</a></li>
</ul>
</div>
</article>
{% endblock %}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,23 @@
<p>Impact key:</p>
<ul>
<li><span class="critical">Critical:</span>
Vulnerability can be used to run attacker code and install
software, requiring no user interaction beyond normal browsing.
</li>
<li><span class="high">High:</span>
Vulnerability can be used to gather sensitive data
from sites in other windows or inject data or code into
those sites, requiring no more than normal browsing actions.
</li>
<li><span class="moderate">Moderate:</span>
Vulnerabilities that would otherwise be High or Critical
except they only work in uncommon non-default configurations or
require the user to perform complicated and/or unlikely steps.
</li>
<li><span class="low">Low:</span>
Minor security vulnerabilities such as Denial of Service
attacks, minor data leaks, or spoofs. (Undetectable spoofs of
SSL indicia would have "High" impact because those are generally
used to steal sensitive data intended for other sites.)
</li>
</ul>

Просмотреть файл

@ -0,0 +1,29 @@
{% extends "security/base.html" %}
{% block page_title %}Mozilla Foundation Secuirty Advisories{% endblock %}
{% block article %}
<article class="section-content" itemscope itemtype="http://schema.org/Article">
<header>
<h1 itemprop="name">Mozilla Foundation Security Advisories</h1>
</header>
<div itemprop="articleBody">
{% include "security/partials/impact_key.html" %}
<ul>
{% for version in product_versions %}
<li id="{{ version.slug }}">Fixed in {{ version.name }} <a href="#{{ version.slug }}">#</a>
<ul>
{% for advisory in version.advisories.all() %}
<li><a class="{{ advisory.impact_class }}"
href="{{ advisory.get_absolute_url() }}">{{ advisory.id }}</a>: {{ advisory.title|safe }}
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</div>
</article>
{% endblock %}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,18 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from nose.tools import eq_
from bedrock.mozorg.tests import TestCase
from bedrock.security.management.commands import update_security_advisories
class TestUpdateSecurityAdvisories(TestCase):
def test_fix_product_name(self):
"""Should fix SeaMonkey and nothing else."""
eq_(update_security_advisories.fix_product_name('Seamonkey 2.2'),
'SeaMonkey 2.2')
eq_(update_security_advisories.fix_product_name('Firefox 2.2'),
'Firefox 2.2')
eq_(update_security_advisories.fix_product_name('fredflintstone 2.2'),
'fredflintstone 2.2')

Просмотреть файл

@ -0,0 +1,23 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from bedrock.mozorg.tests import TestCase
from bedrock.security.models import Product
class TestModels(TestCase):
def test_version_ordering(self):
pv3 = Product.objects.create(name='Firefox 24.0.1')
pv2 = Product.objects.create(name='Firefox 24.0')
pv0 = Product.objects.create(name='Fennec 24.0')
pv1 = Product.objects.create(name='Firefox 23.0')
pvs = [pv2, pv0, pv3, pv1]
self.assertListEqual([pv0, pv1, pv2, pv3], sorted(pvs))
def test_product_version_slug(self):
"""Slug should include the version."""
pv0 = Product.objects.create(name='Firefox 24.0.1')
pv1 = Product.objects.create(name='Firefox ESR 24.2')
self.assertEqual(pv0.slug, 'firefox-24.0.1')
self.assertEqual(pv1.slug, 'firefox-esr-24.2')

Просмотреть файл

@ -0,0 +1,54 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from textwrap import dedent
from cStringIO import StringIO
from nose.tools import eq_
from bedrock.security.utils import mfsa_id_from_filename, parse_md_front_matter
def test_parse_front_matter():
"""Should return front matter and MD separately."""
lines = StringIO(dedent("""
---
dude: abiding
walter: angry
donny: oblivious
---
Let's go bowling.
"""))
yaml, md = parse_md_front_matter(lines)
eq_(yaml, dedent("""\
dude: abiding
walter: angry
donny: oblivious
"""))
eq_(md, "\nLet's go bowling.\n")
def test_parse_front_matter_only():
"""Should not care about any other --- lines."""
lines = StringIO(dedent("""
---
dude: abiding
walter: angry
---
Art
---
Maude's thing.
"""))
yaml, md = parse_md_front_matter(lines)
eq_(yaml, 'dude: abiding\nwalter: angry\n')
eq_(md, "\nArt\n---\n\nMaude's thing.\n")
def test_mfsa_id_from_filename():
eq_(mfsa_id_from_filename('announce/2014/mfsa2014-01.md'),
'2014-01')
eq_(mfsa_id_from_filename('announce/2014/mfsa2014-101.md'),
'2014-101')
assert mfsa_id_from_filename('dude.txt') is None

Просмотреть файл

@ -0,0 +1,120 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from django.test import RequestFactory
from mock import patch, Mock
from product_details.version_compare import Version
from bedrock.mozorg.tests import TestCase
from bedrock.security.management.commands.update_security_advisories import add_or_update_advisory
from bedrock.security.models import Product
from bedrock.security.views import ProductView, ProductVersionView, latest_queryset
class TestViews(TestCase):
def setUp(self):
pvnames = [
'Firefox 3.6',
'Firefox 4.0',
'Firefox 4.0.1',
'Firefox 4.2',
'Firefox 4.2.3',
'Firefox 24.0',
]
self.pvs = [Product.objects.create(name=pv) for pv in pvnames]
def test_product_view_min_version(self):
"""Should not include versions below minimum."""
pview = ProductView()
pview.kwargs = {'slug': 'firefox'}
with patch.dict(pview.minimum_versions, {'firefox': Version('4.2')}):
self.assertListEqual(pview.get_queryset(),
[self.pvs[5], self.pvs[4], self.pvs[3]])
with patch.dict(pview.minimum_versions, {'firefox': Version('22.0')}):
self.assertListEqual(pview.get_queryset(), [self.pvs[5]])
def test_product_version_view_filter_major(self):
"""Given a major version should return all minor versions."""
pview = ProductVersionView()
pview.kwargs = {'slug': 'firefox-4'}
self.assertListEqual(pview.get_queryset(),
[self.pvs[4], self.pvs[3], self.pvs[2], self.pvs[1]])
def test_product_version_view_filter_minor(self):
"""Given a minor version should return all point versions."""
pview = ProductVersionView()
pview.kwargs = {'slug': 'firefox-4.2'}
self.assertListEqual(pview.get_queryset(), [self.pvs[4], self.pvs[3]])
class TestLastModified(TestCase):
def setUp(self):
self.next_id = 1
self.rf = RequestFactory()
def new_advisory(self, mfsa_id=None, title='WILMAAAA!', impact='Critical',
announced='August 18, 2014', fixed_in=None,
html='Wilma finally leaves Fred for a brontosaurus.'):
if mfsa_id is None:
mfsa_id = '2014-{0:0>2}'.format(self.next_id)
self.next_id += 1
if fixed_in is None:
fixed_in = ['Firefox 29', 'Thunderbird 29']
return add_or_update_advisory({
'mfsa_id': mfsa_id,
'title': title,
'impact': impact,
'announced': announced,
'fixed_in': fixed_in,
}, html)
def test_latest_queryset_all(self):
"""Should return all advisories for the all page."""
advisories = [self.new_advisory() for i in range(10)]
req = self.rf.get('/')
req.resolver_match = Mock()
req.resolver_match.url_name = 'security.advisories'
qs = latest_queryset(req, {})
self.assertListEqual(advisories, list(qs.order_by('year', 'order')))
def test_latest_queryset_single(self):
"""Should return a single advisory based on PK."""
advisories = [self.new_advisory() for i in range(10)]
req = self.rf.get('/')
req.resolver_match = Mock()
req.resolver_match.url_name = 'security.advisory'
qs = latest_queryset(req, {'pk': '2014-05'})
self.assertEqual(advisories[4], qs.get())
def test_latest_queryset_product(self):
"""Should advisories for a single product."""
advisories_fx = [self.new_advisory(fixed_in=['Firefox 30.0']) for i in range(5)]
for i in range(5):
self.new_advisory(fixed_in=['Thunderbird 30.0'])
req = self.rf.get('/')
req.resolver_match = Mock()
req.resolver_match.url_name = 'security.product-advisories'
qs = latest_queryset(req, {'slug': 'firefox'})
self.assertListEqual(advisories_fx, list(qs.order_by('year', 'order')))
def test_latest_queryset_product_version(self):
"""Should advisories for a single product version."""
advisories_30 = [self.new_advisory(fixed_in=['Firefox 30.{0}'.format(i)])
for i in range(5)]
advisories_29 = [self.new_advisory(fixed_in=['Firefox 29.0.{0}'.format(i)])
for i in range(1, 5)]
# make sure the one with no point version is included
advisories_29.append(self.new_advisory(fixed_in=['Firefox 29.0']))
req = self.rf.get('/')
req.resolver_match = Mock()
req.resolver_match.url_name = 'security.product-version-advisories'
qs = latest_queryset(req, {'slug': 'firefox-30'})
self.assertListEqual(advisories_30, list(qs.order_by('year', 'order')))
qs = latest_queryset(req, {'slug': 'firefox-30.1'})
self.assertEqual(advisories_30[1], qs.get())
qs = latest_queryset(req, {'slug': 'firefox-29.0'})
self.assertListEqual(advisories_29, list(qs.order_by('year', 'order')))

37
bedrock/security/urls.py Normal file
Просмотреть файл

@ -0,0 +1,37 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from django.conf.urls import patterns, url
from bedrock.mozorg.util import page
from bedrock.security.views import (
AdvisoriesView,
AdvisoryView,
OldAdvisoriesListView,
OldAdvisoriesView,
ProductView,
ProductVersionView,
)
urlpatterns = patterns('', # noqa
page('', 'security/index.html'),
page('bug-bounty', 'security/bug-bounty.html'),
page('bug-bounty-faq', 'security/bug-bounty-faq.html'),
page('bug-bounty-faq-webapp', 'security/bug-bounty-faq-webapp.html'),
url(r'^advisories/$',
AdvisoriesView.as_view(), name='security.advisories'),
url(r'^advisories/mfsa(?P<pk>\d{4}-\d{2,3})/$',
AdvisoryView.as_view(), name='security.advisory'),
page('known-vulnerabilities', 'security/known-vulnerabilities.html'),
page('known-vulnerabilities/older-vulnerabilities', 'security/older-vulnerabilities.html'),
url(r'^known-vulnerabilities/(?P<slug>[a-z-]+)/$',
ProductView.as_view(), name='security.product-advisories'),
url(r'^known-vulnerabilities/(?P<slug>[\w-]+-\d{1,3}(\.\d{1,3})?)/$',
ProductVersionView.as_view(), name='security.product-version-advisories'),
url(r'^announce/\d{4}/mfsa(?P<pk>\d{4}-\d{2,3})\.html$', OldAdvisoriesView.as_view()),
url(r'^announce/$', OldAdvisoriesListView.as_view()),
)

82
bedrock/security/utils.py Normal file
Просмотреть файл

@ -0,0 +1,82 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import codecs
from functools import wraps
import os
import re
import yaml
from markdown import markdown
FILENAME_RE = re.compile('mfsa(\d{4}-\d{2,3})\.md$')
def mfsa_id_from_filename(filename):
match = FILENAME_RE.search(filename)
if match:
return match.group(1)
return None
def parse_md_front_matter(lines):
"""Return the YAML and MD sections.
:param: lines iterator
:return: str YAML, str Markdown
"""
# fm_count: 0: init, 1: in YAML, 2: in Markdown
fm_count = 0
yaml_lines = []
md_lines = []
for line in lines:
# first line we care about is FM start
if fm_count < 2 and line.strip() == '---':
fm_count += 1
continue
if fm_count == 1:
yaml_lines.append(line)
if fm_count == 2:
md_lines.append(line)
if fm_count < 2:
raise ValueError('Front Matter not found.')
return ''.join(yaml_lines), ''.join(md_lines)
def parse_md_file(file_name):
"""Return the YAML and MD sections for file_name."""
with codecs.open(file_name, encoding='utf8') as fh:
yamltext, mdtext = parse_md_front_matter(fh)
data = yaml.safe_load(yamltext)
if 'mfsa_id' not in data:
mfsa_id = mfsa_id_from_filename(file_name)
if mfsa_id:
data['mfsa_id'] = mfsa_id
return data, markdown(mdtext)
def chdir(dirname=None):
"""Decorator to run a function in a different directory then return."""
def decorator(func):
@wraps(func)
def inner(*args, **kwargs):
curdir = os.getcwd()
try:
if dirname is not None:
os.chdir(dirname)
return func(*args, **kwargs)
finally:
os.chdir(curdir)
return inner
return decorator

143
bedrock/security/views.py Normal file
Просмотреть файл

@ -0,0 +1,143 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from django.db.models import Q
from django.utils.decorators import method_decorator
from django.views.decorators.http import last_modified
from django.views.generic import DetailView, ListView, RedirectView
from funfactory.urlresolvers import reverse
from product_details.version_compare import Version
from bedrock.mozorg.decorators import cache_control_expires
from bedrock.security.models import Product, SecurityAdvisory
def latest_queryset(request, kwargs):
"""
Return a queryset for use as a way to find last-modified date.
:param request: the http request object
:param kwargs: the URL param args for the request
:return: QuerySet
"""
urlname = request.resolver_match.url_name.split('.')[1]
if urlname == 'advisories':
return SecurityAdvisory.objects.all()
if urlname == 'advisory':
pk = kwargs.get('pk')
return SecurityAdvisory.objects.filter(pk=pk)
if urlname == 'product-advisories':
slug = kwargs.get('slug')
# doesn't take minimum versions into account.
# don't think that's really a problem as they shouldn't change.
return SecurityAdvisory.objects.filter(fixed_in__product_slug=slug)
if urlname == 'product-version-advisories':
slug = kwargs.get('slug')
qfilter = Q(fixed_in__slug__startswith=slug + '.')
dots = slug.count('.')
if dots == 1:
# minor version. add exact match.
qfilter |= Q(fixed_in__slug__exact=slug)
return SecurityAdvisory.objects.filter(qfilter)
def latest_advisory(request, *args, **kwargs):
"""
Callback function for use with last_modified decorator.
:params: request, *args, **kwargs same as sent to view
:return: function
"""
queryset = latest_queryset(request, kwargs)
try:
latest = queryset.only('last_modified').latest()
except SecurityAdvisory.DoesNotExist:
return None
return latest.last_modified
class AdvisoriesView(ListView):
template_name = 'security/advisories.html'
queryset = SecurityAdvisory.objects.only('id', 'impact', 'title', 'announced')
context_object_name = 'advisories'
@method_decorator(cache_control_expires(0.5))
@method_decorator(last_modified(latest_advisory))
def dispatch(self, request, *args, **kwargs):
return super(AdvisoriesView, self).dispatch(request, *args, **kwargs)
class AdvisoryView(DetailView):
model = SecurityAdvisory
template_name = 'security/advisory.html'
context_object_name = 'advisory'
@method_decorator(cache_control_expires(0.5))
@method_decorator(last_modified(latest_advisory))
def dispatch(self, request, *args, **kwargs):
return super(AdvisoryView, self).dispatch(request, *args, **kwargs)
class ProductView(ListView):
template_name = 'security/product-advisories.html'
context_object_name = 'product_versions'
allow_empty = False
minimum_versions = {
'firefox': Version('4.0'),
'thunderbird': Version('6.0'),
'seamonkey': Version('2.3'),
}
@method_decorator(cache_control_expires(0.5))
@method_decorator(last_modified(latest_advisory))
def dispatch(self, request, *args, **kwargs):
return super(ProductView, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
product_slug = self.kwargs.get('slug')
versions = Product.objects.filter(product_slug=product_slug)
min_version = self.minimum_versions.get(product_slug)
if min_version:
versions = [vers for vers in versions if vers.version >= min_version]
return sorted(versions, reverse=True)
class ProductVersionView(ListView):
template_name = 'security/product-advisories.html'
context_object_name = 'product_versions'
allow_empty = False
@method_decorator(cache_control_expires(0.5))
@method_decorator(last_modified(latest_advisory))
def dispatch(self, request, *args, **kwargs):
return super(ProductVersionView, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
slug = self.kwargs['slug']
qfilter = Q(slug__startswith=slug + '.')
dots = slug.count('.')
if dots == 1:
# minor version. add exact match.
qfilter |= Q(slug__exact=slug)
versions = Product.objects.filter(qfilter)
return sorted(versions, reverse=True)
class CachedRedirectView(RedirectView):
@method_decorator(cache_control_expires(24 * 30)) # 30 days
def dispatch(self, request, *args, **kwargs):
return super(CachedRedirectView, self).dispatch(request, *args, **kwargs)
class OldAdvisoriesView(CachedRedirectView):
def get_redirect_url(self, **kwargs):
return reverse('security.advisory', kwargs=kwargs)
class OldAdvisoriesListView(CachedRedirectView):
def get_redirect_url(self, **kwargs):
return reverse('security.advisories')

Просмотреть файл

@ -56,6 +56,7 @@ SUPPORTED_NONLOCALES += [
'gameon',
'robots.txt',
'credits',
'security',
]
ALLOWED_HOSTS = [
@ -350,6 +351,9 @@ MINIFY_BUNDLES = {
'privacy': (
'css/privacy/privacy.less',
),
'security': (
'css/security/security.less',
),
'privacy-day': (
'css/privacy/privacy-day.less',
),
@ -828,6 +832,7 @@ INSTALLED_APPS = get_apps(exclude=(
'%s.tabzilla' % PROJECT_MODULE,
'%s.facebookapps' % PROJECT_MODULE,
'%s.externalfiles' % PROJECT_MODULE,
'%s.security' % PROJECT_MODULE,
# libs
'django_extensions',
@ -1035,6 +1040,9 @@ RNA = {
'VERIFY_SSL_CERT': os.environ.get('VERIFY_SSL_CERT', False),
}
MOFO_SECURITY_ADVISORIES_PATH = path('mofo_security_advisories')
MOFO_SECURITY_ADVISORIES_REPO = 'https://github.com/mozilla/foundation-security-advisories.git'
LOGGING = {
'root': {
'level': 'WARNING',

Просмотреть файл

@ -32,6 +32,7 @@ urlpatterns = patterns(
(r'^privacy', include('bedrock.privacy.urls')),
(r'^styleguide/', include('bedrock.styleguide.urls')),
(r'^tabzilla/', include('bedrock.tabzilla.urls')),
(r'^security/', include('bedrock.security.urls')),
(r'', include('bedrock.firefox.urls')),
(r'', include('bedrock.mozorg.urls')),
(r'', include('bedrock.newsletter.urls')),

Просмотреть файл

@ -13,6 +13,7 @@ npm install
cp bedrock/settings/local.py-dist bedrock/settings/local.py
./manage.py update_product_details
./manage.py update_externalfiles
./manage.py update_security_advisories
mysql-ctl start
./manage.py syncdb --migrate --noinput
./manage.py rnasync

Просмотреть файл

@ -47,6 +47,7 @@ def update_assets(ctx):
management_cmd(ctx, 'compress_assets')
management_cmd(ctx, 'update_product_details')
management_cmd(ctx, 'update_externalfiles')
management_cmd(ctx, 'update_security_advisories')
@task

Просмотреть файл

@ -782,5 +782,9 @@ RewriteRule ^/media/flash/playerWithControls.swf - [F]
# Bug 896474
RewriteRule ^/(\w{2,3}(?:-\w{2})?/)?about(/?|/.+)$ /b/$1about$2 [PT]
#Bug 1040970
# Bug 1040970
RewriteRule ^/mozillacareers$ https://wiki.mozilla.org/People/mozillacareers?utm_medium=redirect&utm_source=mozillacareers-vanity [L,R=301]
# Bug 1026184
# TODO: enable this after testing and porting/archiving all pages
#RewriteRule ^/(\w{2,3}(?:-\w{2})?/)?security(/?|/.+)$ /b/$1security$2 [PT]

Просмотреть файл

@ -35,6 +35,10 @@ def render(request, template, context=None, **kwargs):
if isinstance(template, list):
template = template[0]
# skip l10n if path exempt
if template.partition('/')[0] in settings.SUPPORTED_NONLOCALES:
return django_render(request, template, context, **kwargs)
# Every template gets its own .lang file, so figure out what it is
# and pass it in the context
context['langfile'] = get_lang_path(template)

Просмотреть файл

@ -83,6 +83,11 @@ class TestRender(TestCase):
self._test(path, template, 'zu', 'zu,fr;q=0.7,en;q=0.3',
302, '/fr/firefox/new/')
@override_settings(SUPPORTED_NONLOCALES=['non-locale'])
def test_supported_nonlocales(self):
resp = self.client.get('/non-locale/test/')
self.assertEqual(resp.status_code, 200)
class TestGetAcceptLanguages(TestCase):
def _test(self, accept_lang, list):

Просмотреть файл

@ -0,0 +1 @@
SUCCESS

Просмотреть файл

@ -14,4 +14,5 @@ urlpatterns = patterns('',
page('some-lang-files', 'some_lang_files.html'),
page('state-of-mozilla', 'state_of_mozilla.html'),
page('firefox/new', 'firefox/new.html'),
page('non-locale/test', 'non-locale/test.html'),
)

Просмотреть файл

@ -134,4 +134,4 @@ class TestNoLocale(TestCase):
request = Mock(spec=object)
# Note: no .locale on request
# Should not cause an exception
render(request, None)
render(request, '500.html')

Просмотреть файл

@ -0,0 +1,497 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@import "../sandstone/sandstone-resp.less";
// IMPACT LEVELS
.critical {
background-color: #FF8080;
}
.high {
background-color: #FFC080;
}
.moderate {
background-color: #FFFF80;
}
// none for .low
li:target {
background-color: lighten(@linkSkyBlue, 25%);
}
#outer-wrapper {
overflow: hidden; /* Fix the layout on IE */
}
#masthead {
margin: 0 auto;
}
#main-content {
margin-top: 50px;
padding: 0;
}
.main-column {
float: left;
margin: 0;
padding: 0;
width: (@gridColumnWidth * 9) + (@gridGutterWidth * 9);
section, article {
padding: 25px;
}
article {
header {
.logo {
position: relative;
float: right;
margin: -80px -20px 0 0;
vertical-align: top;
}
p {
clear: both;
margin: 1em 0;
}
.meta {
color: @textColorTertiary;
font-style: italic;
}
& + * {
clear: both;
}
}
section {
margin-top: 2.5em;
padding: 0;
section {
margin-top: 1.5em;
}
}
.highlight {
margin: 15px 0;
padding: 15px;
color: @textColorPrimary;
background-color: #f9fafb;
box-shadow: 1px 1px 2px #999;
line-height: 1.5;
h2, h3, h4 {
line-height: 1.3;
}
h4 {
font-size: 20px;
}
hr {
margin: 20px auto;
border-bottom: 1px solid #ccc;
width: 80%;
}
[tabindex] {
outline: 0;
}
[role="tab"] {
&[aria-expaned] {
cursor: pointer;
}
a {
margin: 0 .5em;
}
}
[aria-hidden="true"] {
display: none;
}
}
}
}
.sidebar {
float: left;
margin: 0;
padding: 0;
width: (@gridColumnWidth * 3) + (@gridGutterWidth * 5);
section, nav {
padding: 25px 25px 0;
}
section section {
padding: 0;
}
nav h2 {
font-size: 20px;
}
}
.section-content {
margin-bottom: @gridGutterWidth;
padding: @gridGutterWidth;
background-color: #fff;
@shadow: 0 0 0 1px #fff inset;
.box-shadow(@shadow);
p, ul {
margin: 1em 0;
}
li {
margin: .5em 0 0 1.5em;
}
}
#side-principles a:after {
content: "\00A0\00BB"; /* nbsp raquo */
}
#side-notices nav {
padding: 0;
ul {
margin: 0;
}
li {
padding: 5px 0;
font-size: @baseFontSize;
.open-sans;
&:last-of-type {
border-width: 0;
}
a {
padding: 12px 0 12px 48px;
background-image: url(/media/img/privacy/icons.png);
background-repeat: no-repeat;
}
&.policy-firefox a,
&.policy-firefox-os a,
&.policy-firefox-cloud a {
background-position: left -40px;
}
&.policy-marketplace a {
background-position: left -80px;
}
&.policy-persona a {
background-position: left -120px;
}
}
}
#side-archives h2 a {
.open-sans;
font-size: @baseFontSize;
letter-spacing: normal;
}
/* Landing Page */
#privacy-landing {
#main-content {
margin-top: 0;
}
#contact {
header {
float: left;
width: 250px;
}
form {
display: block;
margin-left: 275px;
legend {
font-size: 20px;
line-height: 1.3;
/* A hack for IEs */
&, & span {
display: block;
width: 95%;
white-space: normal;
}
}
input,
textarea {
.border-box;
margin-bottom: 15px;
width: 100%;
*width: 95%; /* IE6, IE7 */
}
}
}
}
/* Principles Page */
#privacy-principles {
.main-column {
margin: 0;
li {
/* Style the list counters */
color: @textColorSecondary;
font-size: 32px;
.open-sans-light;
}
p {
/* And reset the style for the child node */
color: @textColorPrimary;
font-size: @baseFontSize;
.open-sans;
}
}
}
/* Firefox Browser Privacy Notice Page */
#firefox-notice {
.main-column .highlight h3 {
margin-top: @baseLine;
}
}
/* I18N */
html[dir="rtl"] {
.main-column,
.sidebar {
float: right;
}
.main-column article header .logo {
float: left;
margin: -80px 0 0 -20px;
}
.section-content li {
margin: .5em 1.5em 0 0;
}
.title-shadow-box {
float: right;
margin-right: 0;
}
#side-notices nav li {
a {
padding: 12px 48px 12px 0;
}
&.policy-websites a {
background-position: right 0;
}
&.policy-firefox a,
&.policy-firefox-os a {
background-position: right -40px;
}
&.policy-marketplace a {
background-position: right -80px;
}
&.policy-persona a {
background-position: right -120px;
}
}
#side-archives li {
margin: 0 20px 0 0;
}
#privacy-landing #contact {
header {
float: right;
}
form {
margin: 0 275px 0 0;
}
}
#privacy-principles .main-column li {
float: right;
margin: 30px 65px 0 30px;
}
}
/* Tablet & Mobile */
@media only screen and (max-width: @breakDesktop) {
#privacy-landing #contact {
header {
float: none;
width: auto;
}
form {
margin: 0;
}
}
html[dir="rtl"] {
#privacy-landing #contact {
header {
float: none;
}
form {
margin: 0;
}
}
}
}
@media only screen and (min-width: @breakTablet) and (max-width: @breakDesktop) {
#main-content {
width: @breakTablet;
}
.main-column {
.span_narrow(8);
margin: 0;
width: (@gridColumnWidthNarrow * 8) + (@gridGutterWidth * 8);
}
.sidebar {
.span_narrow(4);
margin: 0;
width: (@gridColumnWidthNarrow * 4) + (@gridGutterWidth * 6);
}
#privacy-principles .main-column li {
.span_narrow(5);
margin: 30px 10px 0 65px;
}
html[dir="rtl"] #privacy-principles .main-column li {
margin: 30px 65px 0 10px;
}
}
@media only screen and (max-width: @breakTablet) {
#masthead {
h2, .breadcrumbs {
display: none;
}
}
#main-content {
margin-top: 25px;
}
.main-column,
.sidebar {
.span-all();
margin: 0;
}
.main-column article header {
.logo {
float: left;
margin: -10px 0 0 -10px;
width: 80px;
& + h1,
& + h1 + .meta {
margin: 0 0 12px 80px;
}
}
.title-shadow-box {
margin-top: -50px;
}
}
.main-column article .highlight {
margin: 15px -15px;
}
#privacy-principles .main-column {
header {
width: auto;
}
li {
float: none;
margin: 30px 0 0 40px;
width: auto;
font-size: 24px;
}
h2 {
font-size: 24px;
}
p {
font-size: @baseFontSize;
}
}
html[dir="rtl"] {
.main-column article header {
.logo {
float: right;
margin: -10px -10px 0 0;
& + h1,
& + h1 + .meta {
margin: 0 80px 12px 0;
}
}
}
#privacy-principles .main-column li {
margin: 30px 40px 0 0;
}
}
}
@media only screen and (min-width: @breakMobileLandscape) and (max-width: @breakTablet) {
#wrapper {
width: @breakMobileLandscape - @gridGutterWidth;
}
#masthead {
width: @breakMobileLandscape - (@gridGutterWidth * 3);
}
}
@media only screen and (max-width: @breakMobileLandscape) {
/* Bug 980659: Avoid a title overflow in Germany */
html[lang="de"] #fxos-notice {
.main-column article header {
.logo {
float: none;
& + h1,
& + h1 + .meta {
margin-left: 0;
}
}
}
}
}