Compare commits

...

No commits in common. "c8s" and "c8-beta" have entirely different histories.
c8s ... c8-beta

25 changed files with 5 additions and 448 deletions

2
.emacs.metadata Normal file
View File

@ -0,0 +1,2 @@
53c01d987b2613701f42d9f941c2d5225a5874c4 SOURCES/emacs-26.1.tar.xz
c962aff1571d9fb346775ec4329877dbb63307d6 SOURCES/package-keyring.gpg

2
.gitignore vendored
View File

@ -1,4 +1,2 @@
SOURCES/emacs-26.1.tar.xz SOURCES/emacs-26.1.tar.xz
SOURCES/package-keyring.gpg SOURCES/package-keyring.gpg
/emacs-26.1.tar.xz
/package-keyring.gpg

View File

@ -5,7 +5,7 @@ Summary: GNU Emacs text editor
Name: emacs Name: emacs
Epoch: 1 Epoch: 1
Version: 26.1 Version: 26.1
Release: 15%{?dist} Release: 11%{?dist}
License: GPLv3+ and CC0-1.0 License: GPLv3+ and CC0-1.0
URL: http://www.gnu.org/software/emacs/ URL: http://www.gnu.org/software/emacs/
Group: Applications/Editors Group: Applications/Editors
@ -29,11 +29,6 @@ Patch4: emacs-mh-rmail-nonempty-dir.patch
Patch5: emacs-etags-local-command-injection-vulnerability.patch Patch5: emacs-etags-local-command-injection-vulnerability.patch
Patch6: emacs-htmlfontify-command-injection-vulnerability.patch Patch6: emacs-htmlfontify-command-injection-vulnerability.patch
Patch7: emacs-ob-latex-command-injection-vulnerability.patch Patch7: emacs-ob-latex-command-injection-vulnerability.patch
Patch8: emacs-consider-org-file-contents-unsafe.patch
Patch9: emacs-org-link-expand-abbrev-unsafe-elisp.patch
Patch10: emacs-mark-contents-untrusted.patch
Patch11: emacs-man-el-shell-injection-vulnerability.patch
Patch12: emacs-CVE-2024-53920.patch
BuildRequires: atk-devel BuildRequires: atk-devel
BuildRequires: cairo-devel BuildRequires: cairo-devel
@ -73,6 +68,7 @@ BuildRequires: desktop-file-utils
BuildRequires: libacl-devel BuildRequires: libacl-devel
BuildRequires: gtk3-devel BuildRequires: gtk3-devel
BuildRequires: webkit2gtk3-devel
# For lucid # For lucid
BuildRequires: Xaw3d-devel BuildRequires: Xaw3d-devel
@ -192,11 +188,6 @@ packages that add functionality to Emacs.
%patch5 -p1 -b .etags-local-command-injection-vulnerability %patch5 -p1 -b .etags-local-command-injection-vulnerability
%patch6 -p1 -b .htmlfontify-command-injection-vulnerability %patch6 -p1 -b .htmlfontify-command-injection-vulnerability
%patch7 -p1 -b .ob-latex-command-injection-vulnerability %patch7 -p1 -b .ob-latex-command-injection-vulnerability
%patch8 -p1 -b .consider-org-file-contents-unsafe
%patch9 -p1 -b .org-link-expand-abbrev-unsafe-elisp
%patch10 -p1 -b .mark-contents-untrusted
%patch11 -p1 -b .emacs-man-el-shell-injection-vulnerability
%patch12 -p1 -b .CVE-2024-53920
autoconf autoconf
# We prefer our emacs.desktop file # We prefer our emacs.desktop file
@ -252,7 +243,7 @@ ln -s ../configure .
%configure --with-dbus --with-gif --with-jpeg --with-png --with-rsvg \ %configure --with-dbus --with-gif --with-jpeg --with-png --with-rsvg \
--with-tiff --with-xft --with-xpm --with-x-toolkit=gtk3 --with-gpm=no \ --with-tiff --with-xft --with-xpm --with-x-toolkit=gtk3 --with-gpm=no \
--with-modules --with-xwidgets --with-modules
make bootstrap make bootstrap
%{setarch} make %{?_smp_mflags} %{setarch} make %{?_smp_mflags}
cd .. cd ..
@ -483,21 +474,6 @@ fi
%dir %{_datadir}/emacs/site-lisp/site-start.d %dir %{_datadir}/emacs/site-lisp/site-start.d
%changelog %changelog
* Wed May 21 2025 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-15
- Restore definition of variable "enable-dir-local-variables" (RHEL-92830)
* Mon May 05 2025 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-14
- Fix arbitrary code execution via Lisp macro expansion (RHEL-69394)
* Wed Feb 19 2025 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-13
- Fix man.el shell injection vulnerability (RHEL-79016)
* Fri Aug 23 2024 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-12
- org-file-contents: Consider all remote files unsafe (CVE-2024-30205)
- org-link-expand-abbrev: Do not evaluate arbitrary unsafe Elisp code (CVE-2024-39331)
- Make Gnus treats inline MIME contents as untrusted (CVE-2024-30203)
- Disable xwidgets (RHEL-14549)
* Wed Apr 12 2023 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-11 * Wed Apr 12 2023 Jacek Migacz <jmigacz@redhat.com> - 1:26.1-11
- Bump version - Bump version

View File

@ -1,238 +0,0 @@
---
emacs-27.2/doc/emacs/misc.texi | 33 +++++++++++++++++
emacs-27.2/lisp/emacs-lisp/macroexp.el | 10 ++++-
emacs-27.2/lisp/files.el | 60 +++++++++++++++++++++++++++++---
emacs-27.2/lisp/ielm.el | 3 +
emacs-27.2/lisp/progmodes/elisp-mode.el | 58 +++++++++++++++++++++++++-----
emacs-27.2/lisp/simple.el | 1
6 files changed, 189 insertions(+), 20 deletions(-)
--- emacs-27.2/doc/emacs/misc.texi
+++ emacs-27.2/doc/emacs/misc.texi 2025-03-03 09:18:41.368169799 +0000
@@ -279,6 +279,39 @@ trusted and the default checking for the
you can set @code{enable-local-variables} to @code{:all}. @xref{Safe
File Variables}.
+@cindex trusted files and directories
+Loading a file of Emacs Lisp code with @code{load-file} or
+@code{load-library} (@pxref{Lisp Libraries}) can execute some of the
+Lisp code in the file being loaded, so you should only load Lisp files
+whose source you trust. However, some Emacs features can in certain
+situations execute Lisp code even without your explicit command or
+request. For example, Flymake, the on-the-fly syntax checker for Emacs
+(@pxref{Top,,, flymake, GNU Flymake}), if it is enabled, can
+automatically execute some of the code in a Lisp file you visit as part
+of its syntax-checking job. Similarly, some completion commands
+(@pxref{Completion}) in buffers visiting Lisp files sometimes need to
+expand Lisp macros for best results. In these cases, just visiting a
+Lisp file and performing some editing in it could trigger execution of
+Lisp code. If the visited file came from an untrusted source, it could
+include dangerous or even malicious code that Emacs would execute in
+those situations.
+
+To protect against this, Emacs disables execution of Lisp code by
+Flymake, completion, and some other features, unless the visited file is
+@dfn{trusted}. It is up to you to specify which files on your system
+should be trusted, by customizing the user option
+@code{trusted-content}.
+
+@defopt trusted-content
+The value of this option is @code{nil} by default, which means no file
+is trusted. You can customize the variable to be a list of one or more
+names of trusted files and directories. A file name that ends in a
+slash @file{/} is interpreted as a directory, which means all its files
+and subdirectories are also trusted. A special value @code{:all} means
+@emph{all} the files and directories on your system should be trusted;
+@strong{this is not recommended}, as it opens a gaping security hole.
+@end defopt
+
@xref{Security Considerations,,, elisp, The Emacs Lisp Reference
Manual}, for more information about security considerations when using
Emacs as part of a larger application.
--- emacs-27.2/lisp/emacs-lisp/macroexp.el
+++ emacs-27.2/lisp/emacs-lisp/macroexp.el 2025-03-03 09:18:41.368169799 +0000
@@ -94,12 +94,20 @@ each clause."
(macroexp--all-forms clause skip)
clause)))
+(defvar macroexp-inhibit-compiler-macros nil
+ "Inhibit application of compiler macros if non-nil.")
+
(defun macroexp--compiler-macro (handler form)
+ "Apply compiler macro HANDLER to FORM and return the result.
+Unless `macroexp-inhibit-compiler-macros' is non-nil, in which
+case return FORM unchanged."
+ (if macroexp-inhibit-compiler-macros
+ form
(condition-case err
(apply handler form (cdr form))
(error
(message "Compiler-macro error for %S: %S" (car form) err)
- form)))
+ form))))
(defun macroexp--funcall-if-compiled (_form)
"Pseudo function used internally by macroexp to delay warnings.
--- emacs-27.2/lisp/files.el
+++ emacs-27.2/lisp/files.el 2025-03-03 09:20:04.078645249 +0000
@@ -591,6 +596,57 @@ buffer contents as untrusted.
Some modes may wish to set this to nil to prevent directory-local
settings being applied, but still respect file-local ones.")
+(defcustom trusted-content nil
+ "List of files and directories whose content we trust.
+Be extra careful here since trusting means that Emacs might execute the
+code contained within those files and directories without an explicit
+request by the user.
+One important case when this might happen is when `flymake-mode' is
+enabled (for example, when it is added to a mode hook).
+Each element of the list should be a string:
+- If it ends in \"/\", it is considered as a directory name and means that
+ Emacs should trust all the files whose name has this directory as a prefix.
+- Otherwise, it is considered a file name.
+Use abbreviated file names. For example, an entry \"~/mycode/\" means
+that Emacs will trust all the files in your directory \"mycode\".
+This variable can also be set to `:all', in which case Emacs will trust
+all files, which opens a gaping security hole. Emacs Lisp authors
+should note that this value must never be set by a major or minor mode."
+ :type '(choice (repeat :tag "List" file)
+ (const :tag "Trust everything (DANGEROUS!)" :all))
+ :version "27.2")
+(put 'trusted-content 'risky-local-variable t)
+
+(defun trusted-content-p ()
+ "Return non-nil if we trust the contents of the current buffer.
+Here, \"trust\" means that we are willing to run code found inside of it.
+See also `trusted-content'."
+ ;; We compare with `buffer-file-truename' i.s.o `buffer-file-name'
+ ;; to try and avoid marking as trusted a file that's merely accessed
+ ;; via a symlink that happens to be inside a trusted dir.
+ (and (not untrusted-content)
+ (or
+ (eq trusted-content :all)
+ (and
+ buffer-file-truename
+ (with-demoted-errors "trusted-content-p: %S"
+ (let ((exists (file-exists-p buffer-file-truename)))
+ (or
+ ;; We can't avoid trusting the user's init file.
+ (if (and exists user-init-file)
+ (file-equal-p buffer-file-truename user-init-file)
+ (equal buffer-file-truename user-init-file))
+ (let ((file (abbreviate-file-name buffer-file-truename))
+ (trusted nil))
+ (dolist (tf trusted-content)
+ (when (or (if exists (file-equal-p tf file) (equal tf file))
+ ;; We don't use `file-in-directory-p' here, because
+ ;; we want to err on the conservative side: "guilty
+ ;; until proven innocent".
+ (and (string-suffix-p "/" tf)
+ (string-prefix-p tf file)))
+ (setq trusted t)))
+ trusted))))))))
;; This is an odd variable IMO.
;; You might wonder why it is needed, when we could just do:
;; (set (make-local-variable 'enable-local-variables) nil)
--- emacs-27.2/lisp/ielm.el
+++ emacs-27.2/lisp/ielm.el 2025-03-03 09:18:41.372169725 +0000
@@ -616,7 +616,8 @@ See `inferior-emacs-lisp-mode' for detai
(unless (comint-check-proc "*ielm*")
(with-current-buffer (get-buffer-create "*ielm*")
(unless (zerop (buffer-size)) (setq old-point (point)))
- (inferior-emacs-lisp-mode)))
+ (inferior-emacs-lisp-mode)
+ (setq-local trusted-content :all)))
(pop-to-buffer-same-window "*ielm*")
(when old-point (push-mark old-point))))
--- emacs-27.2/lisp/progmodes/elisp-mode.el
+++ emacs-27.2/lisp/progmodes/elisp-mode.el 2025-03-03 09:18:41.372169725 +0000
@@ -333,6 +333,43 @@ Blank lines separate paragraphs. Semico
(defvar warning-minimum-log-level)
+(defvar elisp--local-macroenv
+ `((cl-eval-when . ,(lambda (&rest args) `(progn . ,(cdr args))))
+ (eval-when-compile . ,(lambda (&rest args) `(progn . ,args)))
+ (eval-and-compile . ,(lambda (&rest args) `(progn . ,args))))
+ "Environment to use while tentatively expanding macros.
+This is used to try and avoid the most egregious problems linked to the
+use of `macroexpand-all' as a way to find the \"underlying raw code\".")
+
+(defvar elisp--macroexpand-untrusted-warning t)
+
+(defun elisp--safe-macroexpand-all (sexp)
+ (if (not (trusted-content-p))
+ ;; FIXME: We should try and do better here, either using a notion
+ ;; of "safe" macros, or with `bwrap', or ...
+ (progn
+ (when elisp--macroexpand-untrusted-warning
+ (setq-local elisp--macroexpand-untrusted-warning nil) ;Don't spam!
+ (let ((inhibit-message t)) ;Only log.
+ (message "Completion of local vars is disabled in %s (untrusted content)"
+ (buffer-name))))
+ sexp)
+ (let ((macroexpand-advice
+ (lambda (expander form &rest args)
+ (condition-case err
+ (apply expander form args)
+ (error
+ (message "Ignoring macroexpansion error: %S" err) form)))))
+ (unwind-protect
+ ;; Silence any macro expansion errors when
+ ;; attempting completion at point (bug#58148).
+ (let ((inhibit-message t)
+ (macroexp-inhibit-compiler-macros t)
+ (warning-minimum-log-level :emergency))
+ (advice-add 'macroexpand-1 :around macroexpand-advice)
+ (macroexpand-all sexp elisp--local-macroenv))
+ (advice-remove 'macroexpand-1 macroexpand-advice)))))
+
(defun elisp--local-variables ()
"Return a list of locally let-bound variables at point."
(save-excursion
@@ -348,17 +385,8 @@ Blank lines separate paragraphs. Semico
(car (read-from-string
(concat txt "elisp--witness--lisp" closer)))
((invalid-read-syntax end-of-file) nil)))
- (macroexpand-advice (lambda (expander form &rest args)
- (condition-case nil
- (apply expander form args)
- (error form))))
- (sexp
- (unwind-protect
- (let ((warning-minimum-log-level :emergency))
- (advice-add 'macroexpand :around macroexpand-advice)
- (macroexpand-all sexp))
- (advice-remove 'macroexpand macroexpand-advice)))
- (vars (elisp--local-variables-1 nil sexp)))
+ (vars (elisp--local-variables-1
+ nil (elisp--safe-macroexpand-all sexp))))
(delq nil
(mapcar (lambda (var)
(and (symbolp var)
@@ -1721,6 +1749,14 @@ directory of the buffer being compiled,
"A Flymake backend for elisp byte compilation.
Spawn an Emacs process that byte-compiles a file representing the
current buffer state and calls REPORT-FN when done."
+ (unless (trusted-content-p)
+ ;; FIXME: Use `bwrap' and friends to compile untrusted content.
+ ;; FIXME: We emit a message *and* signal an error, because by default
+ ;; Flymake doesn't display the warning it puts into "*flmake log*".
+ (message "Disabling elisp-flymake-byte-compile in %s (untrusted content)"
+ (buffer-name))
+ (error "Disabling elisp-flymake-byte-compile in %s (untrusted content)"
+ (buffer-name)))
(when elisp-flymake--byte-compile-process
(when (process-live-p elisp-flymake--byte-compile-process)
(kill-process elisp-flymake--byte-compile-process)))
--- emacs-27.2/lisp/simple.el
+++ emacs-27.2/lisp/simple.el 2025-03-03 09:18:41.372169725 +0000
@@ -1621,6 +1621,7 @@ display the result of expression evaluat
(eldoc-mode 1)
(add-hook 'completion-at-point-functions
#'elisp-completion-at-point nil t)
+ (setq-local trusted-content :all)
(run-hooks 'eval-expression-minibuffer-setup-hook))
(read-from-minibuffer prompt initial-contents
read-expression-map t

View File

@ -1,36 +0,0 @@
From 2bc865ace050ff118db43f01457f95f95112b877 Mon Sep 17 00:00:00 2001
From: Ihor Radchenko <yantar92@posteo.net>
Date: Tue, 20 Feb 2024 14:59:20 +0300
Subject: org-file-contents: Consider all remote files unsafe
* lisp/org/org.el (org-file-contents): When loading files, consider all
remote files (like TRAMP-fetched files) unsafe, in addition to URLs.
---
lisp/org/org.el | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 0f5d17d..76559c9 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -4576,12 +4576,16 @@ from file or URL, and return nil.
If NOCACHE is non-nil, do a fresh fetch of FILE even if cached version
is available. This option applies only if FILE is a URL."
(let* ((is-url (org-file-url-p file))
+ (is-remote (condition-case nil
+ (file-remote-p file)
+ ;; In case of error, be safe.
+ (t t)))
(cache (and is-url
(not nocache)
(gethash file org--file-cache))))
(cond
(cache)
- (is-url
+ ((or is-url is-remote)
(with-current-buffer (url-retrieve-synchronously file)
(goto-char (point-min))
;; Move point to after the url-retrieve header.
--
cgit v1.1

View File

@ -1,34 +0,0 @@
From 820f0793f0b46448928905552726c1f1b999062f Mon Sep 17 00:00:00 2001
From: Xi Lu <lx@shellcodes.org>
Date: Tue, 10 Oct 2023 22:20:05 +0800
Subject: Fix man.el shell injection vulnerability
* lisp/man.el (Man-translate-references): Fix shell injection
vulnerability. (Bug#66390)
* test/lisp/man-tests.el (man-tests-Man-translate-references): New
test.
---
lisp/man.el | 6 +++++-
test/lisp/man-tests.el | 12 ++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/lisp/man.el b/lisp/man.el
index 55cb938..d963964 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -761,7 +761,11 @@ and the `Man-section-translations-alist' variables)."
(setq name (match-string 2 ref)
section (match-string 1 ref))))
(if (string= name "")
- ref ; Return the reference as is
+ ;; see Bug#66390
+ (mapconcat 'identity
+ (mapcar #'shell-quote-argument
+ (split-string ref "\\s-+"))
+ " ") ; Return the reference as is
(if Man-downcase-section-letters-flag
(setq section (downcase section)))
(while slist
--
cgit v1.1

View File

@ -1,25 +0,0 @@
From 937b9042ad7426acdcca33e3d931d8f495bdd804 Mon Sep 17 00:00:00 2001
From: Ihor Radchenko <yantar92@posteo.net>
Date: Tue, 20 Feb 2024 12:44:30 +0300
Subject: * lisp/gnus/mm-view.el (mm-display-inline-fontify): Mark contents
untrusted.
---
lisp/gnus/mm-view.el | 1 +
1 file changed, 1 insertion(+)
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 2e1261c..5f234e5 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -504,6 +504,7 @@ If MODE is not set, try to find mode automatically."
(setq coding-system (mm-find-buffer-file-coding-system)))
(setq text (buffer-string))))
(with-temp-buffer
+ (setq untrusted-content t)
(buffer-disable-undo)
(mm-enable-multibyte)
(insert (cond ((eq charset 'gnus-decoded)
--
cgit v1.1

View File

@ -1,78 +0,0 @@
From f4cc61636947b5c2f0afc67174dd369fe3277aa8 Mon Sep 17 00:00:00 2001
From: Ihor Radchenko <yantar92@posteo.net>
Date: Tue, 18 Jun 2024 13:06:44 +0200
Subject: org-link-expand-abbrev: Do not evaluate arbitrary unsafe Elisp code
* lisp/org/org.el (org-link-expand-abbrev): Refuse expanding %(...) link
abbrevs that specify unsafe function. Instead, display a warning, and
do not expand the abbrev. Clear all the text properties from the
returned link, to avoid any potential vulnerabilities caused by
properties that may contain arbitrary Elisp.
---
lisp/org/org.el | 40 +++++++++++++++++++++++++++++-----------
1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 7a7f4f5..8a556c7 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -1152,26 +1152,44 @@ Abbreviations are defined in `org-link-abbrev-alist'."
(defun org-link-expand-abbrev (link)
"Apply replacements as defined in `org-link-abbrev-alist'."
- (if (string-match "^\\([^:]*\\)\\(::?\\(.*\\)\\)?$" link)
+ (if (not (string-match "^\\([^:]*\\)\\(::?\\(.*\\)\\)?$" link)) link
(let* ((key (match-string 1 link))
(as (or (assoc key org-link-abbrev-alist-local)
(assoc key org-link-abbrev-alist)))
(tag (and (match-end 2) (match-string 3 link)))
rpl)
(if (not as)
link
(setq rpl (cdr as))
- (cond
- ((symbolp rpl) (funcall rpl tag))
- ((string-match "%(\\([^)]+\\))" rpl)
- (replace-match
- (save-match-data
- (funcall (intern-soft (match-string 1 rpl)) tag)) t t rpl))
- ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
- ((string-match "%h" rpl)
- (replace-match (url-hexify-string (or tag "")) t t rpl))
- (t (concat rpl tag)))))
- link))
+ ;; Drop any potentially dangerous text properties like
+ ;; `modification-hooks' that may be used as an attack vector.
+ (substring-no-properties
+ (cond
+ ((symbolp rpl) (funcall rpl tag))
+ ((string-match "%(\\([^)]+\\))" rpl)
+ (let ((rpl-fun-symbol (intern-soft (match-string 1 rpl))))
+ ;; Using `unsafep-function' is not quite enough because
+ ;; Emacs considers functions like `genenv' safe, while
+ ;; they can potentially be used to expose private system
+ ;; data to attacker if abbreviated link is clicked.
+ (if (or (eq t (get rpl-fun-symbol 'org-link-abbrev-safe))
+ (eq t (get rpl-fun-symbol 'pure)))
+ (replace-match
+ (save-match-data
+ (funcall (intern-soft (match-string 1 rpl)) tag))
+ t t rpl)
+ (org-display-warning
+ (format "Disabling unsafe link abbrev: %s
+You may mark function safe via (put '%s 'org-link-abbrev-safe t)"
+ rpl (match-string 1 rpl)))
+ (setq org-link-abbrev-alist-local (delete as org-link-abbrev-alist-local)
+ org-link-abbrev-alist (delete as org-link-abbrev-alist))
+ link
+ )))
+ ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
+ ((string-match "%h" rpl)
+ (replace-match (url-hexify-string (or tag "")) t t rpl))
+ (t (concat rpl tag))))))))
;;; Storing and inserting links
--
cgit v1.1

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-8
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional}

View File

@ -1,2 +0,0 @@
SHA512 (emacs-26.1.tar.xz) = 537c2cfdd281151b360002419dde6280c313e07a937ed96405c67f754b3401ec5541091a3c0aa6690929bc33dd79e8e0d8844e7a6b014b7798c63cb15de210c2
SHA512 (package-keyring.gpg) = ca0dfa2edda9a6de5837dd6d754d574b13e007561e8dcc99c178d24f6a5dbb6880edc95db9d6afbea8bdf0b409671657fe22a778003ea0ccf351dce5e4fd429f