Feature/xray 144147 onboard yarn v4#778
Conversation
V4 operates in native mode: registry URL and auth token come from .yarnrc.yml (local or ~/.yarnrc.yml written by yarn config set --home) instead of requiring jf yarn-config / yarn.yaml. Key changes: yarn.go - Remove V4 rejection from verifyYarnVersionSupportedForCuration and configureYarnResolutionServerAndRunInstall (only V1 is now rejected). - resolveCurationLockfileDir: copy project to temp dir before running install (mirrors pnpm), so the customer's checkout is never modified. - For V4 curation: yarnCurationRegistry() rewrites api/npm/ → api/curation/audit/, then runYarnConfigSet sets a global npmAuthToken in the temp .yarnrc.yml so the rewritten URL authenticates correctly (the original token is scoped to api/npm/ and does not match the curation endpoint). - GetNativeYarnV4RegistryConfig: reads npmRegistryServer via yarn config get; reads npmAuthToken via direct YAML parsing of .yarnrc.yml and ~/.yarnrc.yml (yarn config get is unreliable for nested keys). - runYarnCommandQuiet: capture stdout+stderr on failure and emit as Debug log so failed-install diagnosis is visible. curationaudit.go - setRepoFromYarnrcForYarnV4: calls SetDepsRepo(repoName) in addition to setPackageManagerConfig. Both are required — PackageManagerConfig drives auth; SetDepsRepo populates params.DependenciesRepository so the curation endpoint URL is constructed in configureYarnResolutionServerAndRunInstall (was always "" before, causing the V4 branch to be skipped and the install to hit api/npm/ instead of api/curation/audit/). - resolveNpmYarnTech: detect V4 projects that have .yarnrc.yml (created by yarn set version 4) without a pre-existing yarn.lock, and projects using a global ~/.yarnrc.yml (--home setup); guard with package-lock.json absence to avoid npm misidentification. - validateRunNativeForTech: accept --run-native for Yarn as a no-op (V4 is always native; flag has no effect but should not error). - SetRepo: detect V4 via version check and route to setRepoFromYarnrcForYarnV4; make version-detection failures explicit errors instead of silent fallbacks. Co-authored-by: Cursor <cursoragent@cursor.com>
bd9988b to
0e05c1e
Compare
0e05c1e to
fd5de28
Compare
c5097ad to
ef1823e
Compare
ef1823e to
e29283f
Compare
ab03730 to
d07e8b3
Compare
d07e8b3 to
d615404
Compare
d615404 to
9fd40e0
Compare
9fd40e0 to
8981284
Compare
8981284 to
79d1ae5
Compare
79d1ae5 to
d9e1352
Compare
…param refactor Co-authored-by: Cursor <cursoragent@cursor.com>
10b8a8e to
a904623
Compare
|
I have read the CLA Document and I hereby sign the CLA |
attiasas
left a comment
There was a problem hiding this comment.
Nice work!, check out my comments
In addition, please add integration tests at: curation_test.go
a8f884d to
298fe3e
Compare
📗 Scan Summary
|
| } | ||
| // npm packument lookup (resolve-only plugin); tarball GETs contain "/-/". | ||
| if body := yarnPackument(r); body != "" { | ||
| _, err := w.Write([]byte(body)) |
There was a problem hiding this comment.
🎯 Static Application Security Testing (SAST) Vulnerability
Full description
Vulnerability Details
| Rule ID: | go-xss |
Overview
Cross-Site Scripting (XSS) is a vulnerability that allows attackers to inject
malicious scripts into web pages viewed by other users. These scripts can steal
sensitive information, hijack user sessions, deface websites, or redirect users
to malicious sites.
Vulnerable example
func displayMessage(w http.ResponseWriter, r *http.Request) {
message := r.URL.Query().Get("message")
fmt.Fprintf(w, "<h1>%s</h1>", message)
}In this example, the displayMessage function retrieves a message from the
query parameters and directly embeds it into an HTML response without any
escaping. This makes it vulnerable to XSS attacks as an attacker could craft
a malicious message containing JavaScript code.
Remediation
To mitigate XSS vulnerabilities, always sanitize and encode user input before
embedding it into HTML responses:
func displayMessage(w http.ResponseWriter, r *http.Request) {
message := r.URL.Query().Get("message")
tpl.Execute(w, html.EscapeString(message))
}In the remediation, we've introduced the html/template package to properly
escape and sanitize the message before embedding it into the HTML response.
We use html.EscapeString to mark the message as safe HTML content, ensuring it's
not escaped by the template engine.
Code Flows
Vulnerable data flow analysis result
r.Host (at curation_test.go line 274)
"http://" + r.Host (at curation_test.go line 274)
"http://" + r.Host + "/api/npm/npms/" (at curation_test.go line 274)
base (at curation_test.go line 277)
fmt.Sprintf({"name":"xml","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.1":{"name":"xml","version":"1.0.1","dist":{"shasum":"97e0d0e9603c6ffd00fbf5419b3f48a6f4e0c7d9","tarball":"%sxml/-/xml-1.0.1.tgz"}}}}, base) (at curation_test.go line 277)
yarnPackument(r) (at curation_test.go line 256)
body (at curation_test.go line 257)
| Dependencies map[string]string `json:"dependencies"` | ||
| DevDependencies map[string]string `json:"devDependencies"` | ||
| OptionalDependencies map[string]string `json:"optionalDependencies"` | ||
| PeerDependencies map[string]string `json:"peerDependencies"` |


devbranch.go vet ./....go fmt ./....What
Onboards Yarn V4 (Berry, native
.yarnrc.ymlmode) tojf curation-audit(jf ca),and unifies Yarn V3 + V4 curation on a metadata-only lockfile resolution path.
Why / Design
jf camust build a completeyarn.lockto enumerate the dependency graph, withoutdownloading tarballs (curation blocks blocked tarballs with a 403, which aborts a normal
install before the lockfile is written).
Approaches considered:
yarn install --mode=update-lockfile(previous V3 behavior): rejected — it stillfetches uncached tarballs to compute checksums, so a curation 403 on a blocked uncached
package aborts before
yarn.lockis written.yarn plugin import <url>: rejected — adds a runtime networkdependency, breaks air-gapped CI.
.yarnrc.ymlflags (enableNetwork: false, etc.): rejected — doesn't produce acomplete lockfile for uncached packages.
jfrog-yarn-resolve-lockfile.cjs,//go:embed).It calls
project.resolveEverything()+project.persistLockfile()— resolving the fullgraph from registry metadata only (no tarball fetch), so blocked packages never abort
the lockfile. The plugin is written into the per-run temp dir, never the customer's project.
V3 behavior change (intentional): V3 curation previously used
--mode=update-lockfile;it now uses the same embedded plugin as V4. V3 had the identical tarball-fetch abort problem,
so this gives V3 strictly better behavior and keeps V3/V4 on one code path.
Highlights
.yarnrc.yml(nojf yarn-configstep).is bumping
yarn.lockmtime so the next run can skip re-resolution.attachWorkspaceMembersToRootaudits every workspace member'sdependencies from the root, matching npm/pnpm.
--run-nativeis a no-op for Yarn V4 (always native) with a deferred warning.Tests
TestRegisterYarnPluginInYarnrc,TestAttachWorkspaceMembersToRoot(yarn package)TestPromoteYarnWorkspaceMemberincl. the$HOME-stop case (curation package)