A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/python/cpython/commit/fae93ab16377db23ba6abc10480b04a58db62bdd below:

Make mailcap refuse to match unsafe filenames/types/… · python/cpython@fae93ab · GitHub

File tree Expand file treeCollapse file tree 4 files changed

+46

-4

lines changed

Filter options

Expand file treeCollapse file tree 4 files changed

+46

-4

lines changed Original file line number Diff line number Diff line change

@@ -60,6 +60,18 @@ standard. However, mailcap files are supported on most Unix systems.

60 60

use) to determine whether or not the mailcap line applies. :func:`findmatch`

61 61

will automatically check such conditions and skip the entry if the check fails.

62 62 63 +

.. versionchanged:: 3.11

64 + 65 +

To prevent security issues with shell metacharacters (symbols that have

66 +

special effects in a shell command line), ``findmatch`` will refuse

67 +

to inject ASCII characters other than alphanumerics and ``@+=:,./-_``

68 +

into the returned command line.

69 + 70 +

If a disallowed character appears in *filename*, ``findmatch`` will always

71 +

return ``(None, None)`` as if no entry was found.

72 +

If such a character appears elsewhere (a value in *plist* or in *MIMEtype*),

73 +

``findmatch`` will ignore all mailcap entries which use that value.

74 +

A :mod:`warning <warnings>` will be raised in either case.

63 75 64 76

.. function:: getcaps()

65 77 Original file line number Diff line number Diff line change

@@ -2,6 +2,7 @@

2 2 3 3

import os

4 4

import warnings

5 +

import re

5 6 6 7

__all__ = ["getcaps","findmatch"]

7 8

@@ -19,6 +20,11 @@ def lineno_sort_key(entry):

19 20

else:

20 21

return 1, 0

21 22 23 +

_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search

24 + 25 +

class UnsafeMailcapInput(Warning):

26 +

"""Warning raised when refusing unsafe input"""

27 + 22 28 23 29

# Part 1: top-level interface.

24 30

@@ -171,15 +177,22 @@ def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):

171 177

entry to use.

172 178 173 179

"""

180 +

if _find_unsafe(filename):

181 +

msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,)

182 +

warnings.warn(msg, UnsafeMailcapInput)

183 +

return None, None

174 184

entries = lookup(caps, MIMEtype, key)

175 185

# XXX This code should somehow check for the needsterminal flag.

176 186

for e in entries:

177 187

if 'test' in e:

178 188

test = subst(e['test'], filename, plist)

189 +

if test is None:

190 +

continue

179 191

if test and os.system(test) != 0:

180 192

continue

181 193

command = subst(e[key], MIMEtype, filename, plist)

182 -

return command, e

194 +

if command is not None:

195 +

return command, e

183 196

return None, None

184 197 185 198

def lookup(caps, MIMEtype, key=None):

@@ -212,14 +225,23 @@ def subst(field, MIMEtype, filename, plist=[]):

212 225

elif c == 's':

213 226

res = res + filename

214 227

elif c == 't':

228 +

if _find_unsafe(MIMEtype):

229 +

msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,)

230 +

warnings.warn(msg, UnsafeMailcapInput)

231 +

return None

215 232

res = res + MIMEtype

216 233

elif c == '{':

217 234

start = i

218 235

while i < n and field[i] != '}':

219 236

i = i+1

220 237

name = field[start:i]

221 238

i = i+1

222 -

res = res + findparam(name, plist)

239 +

param = findparam(name, plist)

240 +

if _find_unsafe(param):

241 +

msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name)

242 +

warnings.warn(msg, UnsafeMailcapInput)

243 +

return None

244 +

res = res + param

223 245

# XXX To do:

224 246

# %n == number of parts if type is multipart/*

225 247

# %F == list of alternating type and filename for parts

Original file line number Diff line number Diff line change

@@ -128,7 +128,8 @@ def test_subst(self):

128 128

(["", "audio/*", "foo.txt"], ""),

129 129

(["echo foo", "audio/*", "foo.txt"], "echo foo"),

130 130

(["echo %s", "audio/*", "foo.txt"], "echo foo.txt"),

131 -

(["echo %t", "audio/*", "foo.txt"], "echo audio/*"),

131 +

(["echo %t", "audio/*", "foo.txt"], None),

132 +

(["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"),

132 133

(["echo \\%t", "audio/*", "foo.txt"], "echo %t"),

133 134

(["echo foo", "audio/*", "foo.txt", plist], "echo foo"),

134 135

(["echo %{total}", "audio/*", "foo.txt", plist], "echo 3")

@@ -212,7 +213,10 @@ def test_findmatch(self):

212 213

('"An audio fragment"', audio_basic_entry)),

213 214

([c, "audio/*"],

214 215

{"filename": fname},

215 -

("/usr/local/bin/showaudio audio/*", audio_entry)),

216 +

(None, None)),

217 +

([c, "audio/wav"],

218 +

{"filename": fname},

219 +

("/usr/local/bin/showaudio audio/wav", audio_entry)),

216 220

([c, "message/external-body"],

217 221

{"plist": plist},

218 222

("showexternal /dev/null default john python.org /tmp foo bar", message_entry))

Original file line number Diff line number Diff line change

@@ -0,0 +1,4 @@

1 +

The deprecated mailcap module now refuses to inject unsafe text (filenames,

2 +

MIME types, parameters) into shell commands. Instead of using such text, it

3 +

will warn and act as if a match was not found (or for test commands, as if

4 +

the test failed).

You can’t perform that action at this time.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4