Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialization arbitrary code execution attack #93

Open
thomascwells opened this issue May 1, 2024 · 12 comments
Open

Deserialization arbitrary code execution attack #93

thomascwells opened this issue May 1, 2024 · 12 comments

Comments

@thomascwells
Copy link

Is the qs format susceptible to the same type of deserialization attack underlying the recent RDS CVE?

References:

@traversc
Copy link
Owner

traversc commented May 1, 2024

Thank you, I will look into it.

@TimTaylor
Copy link

FWIW - AFAICT yes. You can use qs to replicate the following example given by George Stagg in https://mstdn.social/@gws/112359739655466497

traversc added a commit that referenced this issue May 2, 2024
@traversc
Copy link
Owner

traversc commented May 2, 2024

Updated on github. R 4.4 throws an error if you try to unserialize a promise. I actually think that's the wrong approach, instead I replace it with NULL and issue a warning.

e <- new.env()
delayedAssign("x", system("uname -msrn"), assign.env = e)
qsave(e, "/mnt/n/temp.qs")
qread("/mnt/n/temp.qs")$x
# Warning message:
#   In qread("/mnt/n/temp.qs") :
#   PROMSXP detected, replacing with NULL (see https://github.com/traversc/qs/issues/93)

Editorial: I agree with gws on mastadon, I don't think this is a big deal, the issue is equivalent to if you ran source on an unknown file. Make sure you know where your files come from!

@TimTaylor
Copy link

Editorial: I agree with gws on mastadon, I don't think this is a big deal, the issue is equivalent to if you ran source on an unknown file. Make sure you know where your files come from!

Agree completely. Mainly came to flag for awareness and saw the issue already.

@traversc
Copy link
Owner

On CRAN now

@sda030
Copy link

sda030 commented May 29, 2024

Hm, I understand the security concern, but the patch is breaking a few hundred ggplot2/ggiraph objects stored to disk being used in our reports (longer story why we pre-store these to disk). Except for locally rolling back to qs 0.26.1 (0.26.2 is not in the CRAN archive?), is there a way to avoid replacing the PROMSXP with NULL if I trust these files? An override_safety argument perhaps?
The gg objects would also be somewhat cumbersome to reproduce and store as new file (formats) now in our production process.

@traversc
Copy link
Owner

An override argument sounds reasonable.

@traversc traversc reopened this May 30, 2024
@traversc
Copy link
Owner

traversc commented Jun 5, 2024

@sda030 Try the latest commit with your previous ggplots and let me know if it works.

New function set_trust_promises

Standard behavior: evaluate promises during save, don't allow promises during read.

e <- new.env()
delayedAssign("x", system("uname -msrn"), assign.env = e)

qsave(e, "/mnt/n/temp.qs")
# Linux Travers-PC 5.15.146.1-microsoft-standard-WSL2 x86_64

qread("/mnt/n/temp.qs")$x
[1] 0

With set_trust_promises

e <- new.env()
delayedAssign("x", system("uname -msrn"), assign.env = e)

set_trust_promises(TRUE)
qsave(e, "/mnt/n/temp.qs")

qread("/mnt/n/temp.qs")$x
# Linux Travers-PC 5.15.146.1-microsoft-standard-WSL2 x86_64
# [1] 0

@sda030
Copy link

sda030 commented Jun 9, 2024

Thanks for quick response @traversc! And sorry for my late response.
It works for your example. Tough a bit weird that when setting set_trust_promises(TRUE), I get a FALSE in return? Should not the returned value be the value being changed to, not the value it was? (Alternatively consider a more informative "Previous value: FALSE")
Very much like the idea of a global option. However, this setting only applies before saving files, which is a bit late for my already saved plots..?

P.S. Will completely change my setup this summer to avoid pre-storing the plots for the future.

@traversc
Copy link
Owner

The global option changes both saving and reading files, so you should be able to read previously saved promises from earlier versions of R / qs.

@sda030
Copy link

sda030 commented Jun 10, 2024

I swear it did not work the first time, but maybe I missed a step. Now it works consistently, also with reading in a ggobj. I also tested turning it off and on again. Nice! Thank you very much for swift action. :)

@sda030
Copy link

sda030 commented Jun 12, 2024

@traversc, may I politely request a patch release on CRAN before August? (I try to protect my less-technically oriented colleagues from R's many ideosyncracies such as Rtools, devtools::install_github(), etc)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants