ropensci-archive / defender Goto Github PK
View Code? Open in Web Editor NEW:no_entry: ARCHIVED :no_entry: Check Package for Potential Security Violations
License: Other
:no_entry: ARCHIVED :no_entry: Check Package for Potential Security Violations
License: Other
@czeildi 👋 according to our recently created package curation policy this repo should now be transferred to either one of your personal accounts, or the ropensci-archive organization.
If you don't answer within one month, I'll transfer the repository to ropensci-archive, after which you could still email me to transfer the repo to a personal account.
Thank you!
if the above is regularly updated and considered ready,
I am getting Error in parse(r_file): invalid multibyte character in parser at line 1
when scanning a package that contains a non-*.R
file in the source code, specifically openssl
containing a certificate file. I am not sure how this would be fixed. Test parse or display files that couldn't be scanned?
I think this is where the error happens:
https://github.com/ropenscilabs/defender/blob/0919859261008c776c6eea6f357c7df8635d024d/R/system_calls.R#L28
#make sure dir is empty
dir <- file.path(tempdir(), paste0(sample(letters,16), collapse=""))
dir.create(dir)
#clone to local
git2r::clone("https://github.com/jeroen/openssl", local_path = dir)
#> cloning into '/home/tmp/RtmpsBKtJt/fkhogjzupdcinvtw'...
#> Receiving objects: 1% (41/4031), 16 kb
#> Receiving objects: 11% (444/4031), 81 kb
#> Receiving objects: 21% (847/4031), 329 kb
#> Receiving objects: 31% (1250/4031), 425 kb
#> Receiving objects: 41% (1653/4031), 489 kb
#> Receiving objects: 51% (2056/4031), 537 kb
#> Receiving objects: 61% (2459/4031), 810 kb
#> Receiving objects: 71% (2863/4031), 3258 kb
#> Receiving objects: 81% (3266/4031), 3306 kb
#> Receiving objects: 91% (3669/4031), 3354 kb
#> Receiving objects: 100% (4031/4031), 9070 kb, done.
#> Local: master /home/tmp/RtmpsBKtJt/fkhogjzupdcinvtw
#> Remote: master @ origin (https://github.com/jeroen/openssl)
#> Head: [d7cefaf] 2019-03-22: Fix partial matching
#summarize_system_calls
defender::summarize_system_calls(dir)
#> Error in parse(r_file): invalid multibyte character in parser at line 1
#which file is causing it?
#certificate file
defender:::get_r_script_paths(dir)[29]
#> [1] "/home/tmp/RtmpsBKtJt/fkhogjzupdcinvtw/tests/keys/opencpu.org.cer"
#what do we see with just this file?
defender:::digest_system_calls(defender:::get_r_script_paths(dir)[29], dir)
#> Error in parse(r_file): invalid multibyte character in parser at line 1
#is it the base::parse? likely
parse(defender:::get_r_script_paths(dir)[29])
#> Error in parse(defender:::get_r_script_paths(dir)[29]): invalid multibyte character in parser at line 1
#are there other files that error out?
# not here
lapply(defender:::get_r_script_paths(dir)[-29], defender:::digest_system_calls, dir)
#> [[1]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[2]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[3]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[4]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[5]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[6]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[7]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[8]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[9]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[10]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[11]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[12]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[13]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[14]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[15]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[16]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[17]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[18]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[19]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[20]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[21]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[22]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[23]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[24]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[25]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[26]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[27]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[28]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[29]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[30]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[31]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[32]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[33]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[34]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[35]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[36]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[37]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[38]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[39]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[40]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[41]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[42]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[43]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[44]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[45]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[46]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[47]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
#>
#> [[48]]
#> [1] line1 col1 line2 col2 id parent token terminal
#> [9] text
#> <0 rows> (or 0-length row.names)
Created on 2019-05-13 by the reprex package (v0.2.1)
I am getting an error Error in strsplit(all_imports$import, "::") : non-character argument
when I call defender::check_namespace
on a package with no imports, such as digest
.
I believe this is where the issue is thrown:
#make sure dir is empty
dir <- file.path(tempdir(), paste0(sample(letters,16), collapse=""))
dir.create(dir)
#clone to local
git2r::clone("https://github.com/eddelbuettel/digest", local_path = dir)
#> cloning into '/home/tmp/RtmpIa6Qb8/srqdlymnjeatkvow'...
#> Receiving objects: 1% (18/1744), 16 kb
#> Receiving objects: 11% (192/1744), 56 kb
#> Receiving objects: 21% (367/1744), 88 kb
#> Receiving objects: 31% (541/1744), 248 kb
#> Receiving objects: 41% (716/1744), 288 kb
#> Receiving objects: 51% (890/1744), 328 kb
#> Receiving objects: 61% (1064/1744), 360 kb
#> Receiving objects: 71% (1239/1744), 384 kb
#> Receiving objects: 81% (1413/1744), 408 kb
#> Receiving objects: 91% (1588/1744), 432 kb
#> Receiving objects: 100% (1744/1744), 438 kb, done.
#> Local: master /home/tmp/RtmpIa6Qb8/srqdlymnjeatkvow
#> Remote: master @ origin (https://github.com/eddelbuettel/digest)
#> Head: [cc5e329] 2019-05-09: compile as C++11, minor test polish
#no imports
defender:::parse_ns_file(dir)$imports
#> list()
#no imported_packages or imported_functions
defender:::parse_all_imports(defender:::parse_ns_file(dir)$imports)
#> $imported_packages
#> list()
#>
#> $imported_functions
#> list()
#check_namespace
defender::check_namespace(dir)
#> Error in strsplit(all_imports$import, "::"): non-character argument
Created on 2019-05-13 by the reprex package (v0.2.1)
link to actually open files at given line number???
maybe as covr::zero_coverage
does it
Someone can still invoke some system calls by using simple ASCII table together witheval(parse())
facility in R. Current version of defender (0.0.1.9000
) is unable to detect such calls. Similar thing can also be achieved by using rawToChar()
and eval(parse())
.
For instance:
# `sys` below generated with utf8ToInt("system('ls')"):
sys <- c(115L, 121L, 115L, 116L, 101L, 109L, 40L, 39L, 108L, 115L, 39L, 41L)
eval(parse(text = intToUtf8(sys)))
So, as I think I tweeted, I ran a slightly modified (reduced scope to just system()
calls) version of the code @czeildi created and there are a ton of really bad (IMO) uses of system()
all across existing bits in CRAN so this is a super important pkg. Once school & holiday shenanigans are over (mid-ish June) I'll be focusing a bit more on this and I'd like to suggest we put together an R Journal article once we've got the pkg built out a bit more to help folks understand how to build safer system calls and why they're dangerous.
base::parseNamespaceFile
or pkgload::parse_ns_file
??
Thank you for your ROpenSci community call presentation recently :-)
As a package developer, I tried check_namespace(".")
on my own package just now (also ../pkg_name
) and got Error in strsplit(all_imports$import, "::") : non-character argument
> sessionInfo()
R version 3.6.0 (2019-04-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=German_Germany.1252 LC_CTYPE=German_Germany.1252
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C
[5] LC_TIME=German_Germany.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] testthat_2.1.1
loaded via a namespace (and not attached):
[1] Rcpp_1.0.1 rstudioapi_0.10 magrittr_1.5
[4] usethis_1.5.0.9000 devtools_2.0.2 pkgload_1.0.2
[7] R6_2.4.0 rlang_0.3.4 sys_3.2
[10] tools_3.6.0 pkgbuild_1.0.3 sessioninfo_1.1.1
[13] cli_1.1.0 withr_2.1.2 askpass_1.1
[16] remotes_2.0.4 openssl_1.3 yaml_2.2.0
[19] assertthat_0.2.1 digest_0.6.18 rprojroot_1.3-2
[22] crayon_1.3.4 gpg_1.2 processx_3.3.1
[25] callr_3.2.0 ropsec_0.2.0.9000 fs_1.3.1
[28] ps_1.3.0 curl_3.3 memoise_1.1.0
[31] glue_1.3.1 stringi_1.4.3 defender_0.0.1.9000
[34] compiler_3.6.0 desc_1.2.0 backports_1.1.4
[37] prettyunits_1.0.2
parsed <- parse("~/packages/testevil/R/internal.R")
parsed_dat <- getParseData(x, TRUE)
parsed_dat[
(which(
(parsed_dat$token == "SYMBOL_FUNCTION_CALL") &
(parsed_dat$text == "system")) - 1),
] -> sys_calls
cat(
sapply(sys_calls$id, getParseText, parseData=sys_calls),
sep="\n"
)
## system("ls")
## system("ls -la")
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.