VYPR
High severityNVD Advisory· Published Apr 12, 2018· Updated Aug 6, 2024

CVE-2014-6633

CVE-2014-6633

Description

The safe_eval function in trytond in Tryton before 2.4.15, 2.6.x before 2.6.14, 2.8.x before 2.8.11, 3.0.x before 3.0.7, and 3.2.x before 3.2.3 allows remote authenticated users to execute arbitrary commands via shell metacharacters in (1) the collection.domain in the webdav module or (2) the formula field in the price_list module.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Remote authenticated users can execute arbitrary commands via shell metacharacters in Tryton's safe_eval function in webdav and price_list modules.

Vulnerability

The safe_eval function in Tryton's server (trytond) before versions 2.4.15, 2.6.14, 2.8.11, 3.0.7, and 3.2.3 allows remote authenticated users to execute arbitrary commands. The vulnerability resides in the webdav module's collection.domain field and the price_list module's formula field, where user-supplied input is passed to safe_eval without proper sanitization [1][2].

Exploitation

An attacker must have valid authentication credentials to the Tryton server. They can then provide shell metacharacters (e.g., backticks, $()) in either the collection.domain parameter of the WebDAV module or the formula field of the price list module. When the system evaluates these inputs using safe_eval, it executes the embedded shell commands [1][3].

Impact

Successful exploitation leads to arbitrary command execution with the privileges of the Tryton server process. This can result in full compromise of the application's data, server resources, and potential lateral movement within the network. Confidentiality, integrity, and availability are all at risk [1].

Mitigation

The vulnerability is fixed in Tryton versions 2.4.15, 2.6.14, 2.8.11, 3.0.7, and 3.2.3. The patch replaces safe_eval with literal_eval from Python's ast module, which only evaluates literal expressions and prevents code execution [2]. Users should upgrade to the patched versions immediately. No workarounds are documented; the safest mitigation is applying the update [3].

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
trytonPyPI
< 2.4.152.4.15
trytonPyPI
>= 2.6.0, < 2.6.142.6.14
trytonPyPI
>= 2.8.0, < 2.8.112.8.11
trytonPyPI
>= 3.2.0, < 3.2.33.2.3
trytondPyPI
>= 2.4.0, < 2.4.152.4.15
trytondPyPI
>= 2.6.0, < 2.6.142.6.14
trytondPyPI
>= 2.8.0, < 2.8.112.8.11
trytondPyPI
>= 3.2.0, < 3.2.33.2.3
trytondPyPI
>= 3.0.0, < 3.0.73.0.7

Affected products

2

Patches

2
19fc2a01357b

Use literal_eval instead of safe_eval whenever possible

https://github.com/tryton/trytondCédric KrierSep 29, 2014via ghsa
5 files changed · +18 11
  • CHANGELOG+1 0 modified
    @@ -1,3 +1,4 @@
    +* Use literal_eval instead of safe_eval (CVE-2014-6633)
     * Prevent double underscore in safe_eval (CVE-2014-6633)
     * Add pre-validation on button
     * Model and Field access checked only if _check_access is set
    
  • trytond/ir/cron.py+3 2 modified
    @@ -7,9 +7,10 @@
     import logging
     from email.mime.text import MIMEText
     from email.header import Header
    +from ast import literal_eval
     
     from ..model import ModelView, ModelSQL, fields
    -from ..tools import safe_eval, get_smtp_server
    +from ..tools import get_smtp_server
     from ..transaction import Transaction
     from ..pool import Pool
     from .. import backend
    @@ -156,7 +157,7 @@ def _callback(cls, cron):
             pool = Pool()
             Config = pool.get('ir.configuration')
             try:
    -            args = (cron.args or []) and safe_eval(cron.args)
    +            args = (cron.args or []) and literal_eval(cron.args)
                 Model = pool.get(cron.model)
                 with Transaction().set_user(cron.user.id):
                     getattr(Model, cron.function)(*args)
    
  • trytond/ir/lang.py+5 4 modified
    @@ -2,10 +2,11 @@
     #this repository contains the full copyright notices and license terms.
     import datetime
     import warnings
    +from ast import literal_eval
     
     from ..model import ModelView, ModelSQL, fields
     from ..cache import Cache
    -from ..tools import safe_eval, datetime_strftime
    +from ..tools import datetime_strftime
     from ..transaction import Transaction
     from ..pool import Pool
     from .time_locale import TIME_LOCALE
    @@ -135,7 +136,7 @@ def check_grouping(cls, langs):
             '''
             for lang in langs:
                 try:
    -                grouping = safe_eval(lang.grouping)
    +                grouping = literal_eval(lang.grouping)
                     for i in grouping:
                         if not isinstance(i, int):
                             raise
    @@ -257,10 +258,10 @@ def _grouping_intervals(grouping):
     
             if monetary:
                 thousands_sep = monetary.mon_thousands_sep
    -            grouping = safe_eval(monetary.mon_grouping)
    +            grouping = literal_eval(monetary.mon_grouping)
             else:
                 thousands_sep = lang.thousands_sep
    -            grouping = safe_eval(lang.grouping)
    +            grouping = literal_eval(lang.grouping)
             if not grouping:
                 return (s, 0)
             if s[-1] == ' ':
    
  • trytond/res/user.py+4 2 modified
    @@ -9,6 +9,8 @@
     import datetime
     from itertools import groupby, ifilter
     from operator import attrgetter
    +from ast import literal_eval
    +
     from sql import Literal
     from sql.conditionals import Coalesce
     from sql.aggregate import Count
    @@ -21,7 +23,7 @@
     
     from ..model import ModelView, ModelSQL, fields
     from ..wizard import Wizard, StateView, Button, StateTransition
    -from ..tools import safe_eval, grouped_slice
    +from ..tools import grouped_slice
     from .. import backend
     from ..transaction import Transaction
     from ..cache import Cache
    @@ -341,7 +343,7 @@ def _get_preferences(cls, user, context_only=False):
                     date = date.replace(i, j)
                 res['locale'] = {
                     'date': date,
    -                'grouping': safe_eval(user.language.grouping),
    +                'grouping': literal_eval(user.language.grouping),
                     'decimal_point': user.language.decimal_point,
                     'thousands_sep': user.language.thousands_sep,
                 }
    
  • trytond/webdav/webdav.py+5 3 modified
    @@ -8,12 +8,14 @@
     import encodings
     import uuid
     import datetime
    +from ast import literal_eval
    +
     from dateutil.relativedelta import relativedelta
     from sql.functions import Extract
     from sql.conditionals import Coalesce
     
     from trytond.model import ModelView, ModelSQL, fields
    -from trytond.tools import reduce_ids, safe_eval
    +from trytond.tools import reduce_ids
     from trytond.transaction import Transaction
     from trytond.pool import Pool
     from trytond.config import config
    @@ -307,7 +309,7 @@ def get_childs(cls, uri, filter=None, cache=None):
                     if not Model:
                         return res
                     models = Model.search(
    -                        safe_eval(collection.domain or "[]"))
    +                    literal_eval(collection.domain))
                     for child in models:
                         if '/' in child.rec_name:
                             continue
    @@ -759,7 +761,7 @@ def get_path(cls, attachments, name):
                 model_name = collection.model.model
                 Model = pool.get(model_name)
                 ids = list(resources[model_name])
    -            domain = safe_eval(collection.domain or '[]')
    +            domain = literal_eval(collection.domain)
                 domain = [domain, ('id', 'in', ids)]
                 records = Model.search(domain)
                 for record in records:
    
3e4c2b7e8c7b

Prevent double underscore in safe_eval

https://github.com/tryton/trytondCédric KrierSep 29, 2014via ghsa
3 files changed · +4 3
  • CHANGELOG+1 0 modified
    @@ -1,3 +1,4 @@
    +* Prevent double underscore in safe_eval (CVE-2014-6633)
     * Add pre-validation on button
     * Model and Field access checked only if _check_access is set
     * Add check_access to RPC
    
  • trytond/tests/test_tools.py+1 1 modified
    @@ -64,7 +64,7 @@ def test0060safe_eval_builtin(self):
     
         def test0061safe_eval_getattr(self):
             'Attempt to get arround direct attr access'
    -        self.assertRaises(NameError, safe_eval, "getattr(int, '__abs__')")
    +        self.assertRaises(NameError, safe_eval, "getattr(int, 'real')")
     
         def test0062safe_eval_func_globals(self):
             'Attempt to access global enviroment where fun was defined'
    
  • trytond/tools/misc.py+2 2 modified
    @@ -369,8 +369,8 @@ def _compile_source(source):
     
     
     def safe_eval(source, data=None):
    -    if '__subclasses__' in source:
    -        raise ValueError('__subclasses__ not allowed')
    +    if '__' in source:
    +        raise ValueError('Double underscores not allowed')
     
         comp = _compile_source(source)
         return eval(comp, {'__builtins__': {
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.