phone-homeCovers 0.0.1, 0.0.2, 0.0.3, 0.0.4 and 0.0.5Reviewed by BitbisonUpdated 2026-11-06
A `.yardopts` `--load ./script.rb` makes `yard doc` execute a script that POSTs the hostname, uid, Ruby version and paths to webhook.site and rewrites files in the gem's directory; 0.0.2 also carries a `../../../../../../public/` path-traversal entry.
w002yardprobe is a Ruby gem published to RubyGems by "w002-research" on November 3, 2026, in five versions (0.0.1 to 0.0.5) within about 100 minutes. It describes itself as a "minimal probe gem used to verify YARD doc generation behavior on documentation hosting services". Every version ships a .yardopts file that makes YARD load the gem's script.rb whenever documentation is generated for it. That script reports the machine's hostname, user id, Ruby version and working directory to a webhook.site collection URL, and rewrites files in the gem's directory. Version 0.0.2 also carries an archive entry that tries to write outside the gem's directory. OSV lists 0.0.4 and 0.0.5 as MAL-2026-18599. The same code is in 0.0.1 to 0.0.3. All five versions are still on RubyGems.
What the package does
Installing the gem or requiring it does nothing beyond defining an empty W002yardprobe::Probe class. Generating its documentation with YARD (yard doc in the gem's directory, which is what documentation hosts such as RubyDoc.info do) executes script.rb inside the yard process:
yard sends an HTTPS POST to webhook.site (https://webhook.site/97fa3c6a-3fad-4d2d-8312-15dc37e41e66). The form carries the marker r002-y7Kp9Qz, the hostname, the user id, the Ruby version, the current directory and the absolute path of script.rb.
- It creates
W002SCRIPT_RAN.txt next to .yardopts and records the outcome of the POST in W002EGRESS_OK.txt (or W002EGRESS_ERR.txt).
- From 0.0.4 on, it points YARD's parsed database (
.yardoc) at a fixed top-level directory named in the script when that directory holds a .yardopts, and otherwise at the gem's own directory.
Nothing reads credentials, starts a second process or stays on the machine after yard exits.
What the code does
The published archives are w002yardprobe-<version>.gem on RubyGems. Their sha256 values match the index's sha: 0.0.5 879a53a3403eb1f8c44c9d2948ebf0ef43466063f93db0f672bdd7b80f1c4f95, 0.0.4 2c92205c8a1ecbffe953de63a4308e7de19bff714f6b01a67f1780bd38f39794, 0.0.3 bb70ebaf37180964c51c57913e33c868803e18f5d096bbed79e1e8c44a917b1a, 0.0.2 79c7daf9b01f75e551392a77d533accd564f7d89d35151b09ed646641b95de1d, 0.0.1 4c679d3e6a1294a3fdb55858130584d0e52208ae6253d6cc90ec2dbb871c9cd7. Line numbers below are for 0.0.5, whose script.rb (sha256 1a9aaf4ada6ff1225a0c9066bcc9ba27f91ce8eaf928fcfed5e32939e21a4f89, 64 lines) is byte-identical to 0.0.4's. The script.rb of 0.0.1 to 0.0.3 (sha256 4c264432e2c63ac2982b83618bbc136205975e462fb1ab064e223a8c3411c4c9, 36 lines) is the same script without the .yardoc redirect.
.yardopts line 1 is --load ./script.rb. YARD documents --load as requiring a Ruby file before it parses sources, so script.rb executes as Ruby in every yard doc or yardoc invocation that reads this .yardopts. The gemspec's require_paths is lib, and lib/w002yardprobe.rb never loads script.rb, so gem install and require do not execute it.
script.rb lines 9–17 pick a base directory: a fixed top-level directory named on line 10, if it holds a .yardopts, otherwise the directory of script.rb, otherwise the current directory.
- Lines 21–25 set
YARD::Registry.yardoc_file to <base>/.yardoc. The comment says this makes the parsed database "land in library source_path for serving", that is, on the documentation host's served copy.
- Lines 28–32 replace
MARKSLOT in lib/w002yardprobe.rb with a stamp of the time and process id (line 6), so that the stamp appears in the published documentation. The lib/w002yardprobe.rb shipped in 0.0.2 to 0.0.5 already carries a stamp, R002EXEC-20261103T113643-705, and no MARKSLOT, so this rewrite only takes effect in 0.0.1.
- Line 35 writes
W002SCRIPT_RAN.txt to the base directory. The comment says it is "served via /file/ when library ready".
- Lines 41–51 assemble
info from Dir.pwd, the base directory, Socket.gethostname, RUBY_VERSION and Process.uid. They POST it with Net::HTTP.post_form to https://webhook.site/97fa3c6a-3fad-4d2d-8312-15dc37e41e66, as the fields m (r002-y7Kp9Qz), info (JSON) and file (the path of script.rb). Lines 52–57 write the HTTP status to W002EGRESS_OK.txt or the error to W002EGRESS_ERR.txt. Lines 59–63 swallow every error, so documentation generation never fails.
- 0.0.2 only: the gem's
data.tar.gz holds a sixth entry, ../../../../../../public/w002probe_r002.html, which the gemspec's file list does not name. It is a one-line HTML page titled "r002 tar-slip probe". The entry is aimed at a tool that unpacks the gem without checking paths, which would write it six directories up into a public/ directory. It carries no script.
The script sends no environment variables, files or credentials. The data it sends identifies the host and proves that code executed there. Its comments and the gem's description say the target is documentation generation on hosting services (script.rb line 1 names "RubyDoc.info docparse generate stage"). On a developer's machine or a CI runner that generates the gem's documentation, the same code executes with that user's rights.
Timeline (UTC)
| When | What |
| 11/03/26 15:37:57 | w002yardprobe 0.0.1 is published to RubyGems |
| 11/03/26 15:38:01 | 0.0.2 is published, with the ../../../../../../public/ entry |
| 11/03/26 15:54:51 | 0.0.3 is published |
| 11/03/26 17:09:47 | 0.0.4 is published, adding the .yardoc redirect |
| 11/03/26 17:16:33 | 0.0.5 is published |
| 11/04/26 02:58:21 | OSV publishes MAL-2026-18599 for 0.0.4 and 0.0.5 |
If you installed it
Installing or requiring the gem alone executes none of this. If you generated its documentation (with yard doc, yardoc or a documentation host), assume webhook.site's collector received your hostname, user id, Ruby version and paths. Delete W002SCRIPT_RAN.txt, W002EGRESS_OK.txt, W002EGRESS_ERR.txt, W002SCRIPT_ERR.txt and any .yardoc it left, and remove the gem. If you unpacked 0.0.2 with a tool other than RubyGems, look for w002probe_r002.html in a public/ directory above where you unpacked it. Block POSTs to webhook.site from documentation tooling.
Indicators
- hosts
webhook.site- requests
POST https://webhook.site/97fa3c6a-3fad-4d2d-8312-15dc37e41e66form fields m=r002-y7Kp9Qz, info=<JSON>, file=<path of script.rb>- files
.yardopts (--load ./script.rb)script.rbW002SCRIPT_RAN.txtW002EGRESS_OK.txtW002EGRESS_ERR.txtW002SCRIPT_ERR.txt<base directory>/.yardoc../../../../../../public/w002probe_r002.html- markers
r002-y7Kp9QzR002EXEC-<UTC time>-<pid>R002EXEC-20261103T113643-705- processes
yard doc (loading ./script.rb through .yardopts)
Examined
- 0.0.1
sha256:4c679d3e6a1294a3fdb55858130584d0e52208ae6253d6cc90ec2dbb871c9cd7- 0.0.2
sha256:79c7daf9b01f75e551392a77d533accd564f7d89d35151b09ed646641b95de1d- 0.0.3
sha256:bb70ebaf37180964c51c57913e33c868803e18f5d096bbed79e1e8c44a917b1a- 0.0.4
sha256:2c92205c8a1ecbffe953de63a4308e7de19bff714f6b01a67f1780bd38f39794- 0.0.5
sha256:879a53a3403eb1f8c44c9d2948ebf0ef43466063f93db0f672bdd7b80f1c4f95
Links