Skip to content

Commit 3a2b06d

Browse files
fix(maven): send the official Maven CLI user agent to the maven2 registry; refresh npm wrapper lock for published 4.0.0 platform packages (#233)
* fix(maven): send the official Maven CLI user agent to the maven2 registry Maven Central blocks/rate-limits user agents containing "socket", so the fallback pom download in the maven vendor backend (acquire_upstream_pom → fetch_pom_bytes) was refused when sent as SocketPatchCLI/x.y.z — the only CLI code path that talks to Maven Central. maven2 registry requests now identify exactly as the official Maven CLI (Apache-Maven/<v> (Java <v>; <os> <ver>), pinned per-OS so the string stays deterministic). Socket API requests keep the honest CLI UA. Tests: shape + no-"socket" guard on the constant, and a wiremock test that only serves the pom when the Maven CLI UA actually goes out on the wire. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(release): refresh the npm wrapper lockfile with the published 4.0.0 platform packages The lock was committed while the 4.0.0 @socketsecurity/socket-patch-* platform packages were still unpublished (npm publish was pending 2FA at release time), so npm silently omitted their node_modules entries. Now that they are live on the registry, version-sync's `npm install --package-lock-only` re-adds them, making the sync a non-no-op and failing release-readiness on every PR. Committing the refreshed lock restores the no-op invariant. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent dcebffa commit 3a2b06d

2 files changed

Lines changed: 262 additions & 2 deletions

File tree

crates/socket-patch-core/src/vendor/maven_repo.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ use serde_json::Value;
6363
use sha1::Sha1;
6464
use sha2::{Digest as _, Sha256};
6565

66-
use crate::constants::USER_AGENT;
6766
use crate::manifest::schema::{PatchFileInfo, PatchRecord};
6867
use crate::patch::apply::{ApplyResult, PatchSources};
6968
use crate::patch::copy_tree::remove_tree;
@@ -95,6 +94,21 @@ const REPO_WIRING_KIND: &str = "maven_pom_repository";
9594
/// (small XML); a multi-MB response is a mirror serving the wrong thing.
9695
const MAX_POM_BYTES: usize = 8 * 1024 * 1024;
9796

97+
/// User-Agent for maven2 registry requests. Maven Central blocks/rate-limits
98+
/// user agents containing "socket", so the CLI's own `SocketPatchCLI/x.y.z`
99+
/// UA (`constants.rs`) gets the pom fallback download refused. These requests
100+
/// instead identify exactly as the official Maven CLI —
101+
/// `Apache-Maven/<maven> (Java <jdk>; <os.name> <os.version>)`, the shape
102+
/// maven-resolver sends — pinned to fixed Maven/JDK/OS versions so the string
103+
/// stays deterministic (no runtime probing). Only maven2 registry traffic
104+
/// uses this; Socket API requests keep the honest UA.
105+
#[cfg(target_os = "macos")]
106+
const MAVEN_USER_AGENT: &str = "Apache-Maven/3.9.11 (Java 17.0.16; Mac OS X 15.5)";
107+
#[cfg(target_os = "windows")]
108+
const MAVEN_USER_AGENT: &str = "Apache-Maven/3.9.11 (Java 17.0.16; Windows 11 10.0)";
109+
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
110+
const MAVEN_USER_AGENT: &str = "Apache-Maven/3.9.11 (Java 17.0.16; Linux 6.8.0)";
111+
98112
/// The maven2 registry base for the (fallback) pom download, overridable with
99113
/// `SOCKET_MAVEN_REGISTRY` (the private-mirror / test escape hatch). Default is
100114
/// Maven Central's maven2 endpoint.
@@ -730,7 +744,7 @@ async fn acquire_upstream_pom(
730744
/// Bounded HTTP GET of a pom from the maven2 registry.
731745
async fn fetch_pom_bytes(url: &str) -> Result<Vec<u8>, String> {
732746
let client = reqwest::Client::builder()
733-
.user_agent(USER_AGENT)
747+
.user_agent(MAVEN_USER_AGENT)
734748
.timeout(Duration::from_secs(60))
735749
.build()
736750
.map_err(|e| format!("build http client: {e}"))?;
@@ -2304,6 +2318,46 @@ mod tests {
23042318
);
23052319
}
23062320

2321+
/// Maven Central blocks/rate-limits user agents containing "socket" —
2322+
/// the maven2 registry client must identify as the official Maven CLI,
2323+
/// never as `SocketPatchCLI/…`.
2324+
#[test]
2325+
fn maven_user_agent_is_the_maven_cli_shape() {
2326+
assert!(
2327+
MAVEN_USER_AGENT.starts_with("Apache-Maven/"),
2328+
"maven2 registry UA must lead with the Maven CLI product token: {MAVEN_USER_AGENT}"
2329+
);
2330+
assert!(
2331+
!MAVEN_USER_AGENT.to_ascii_lowercase().contains("socket"),
2332+
"a UA containing \"socket\" is blocked by Maven Central: {MAVEN_USER_AGENT}"
2333+
);
2334+
}
2335+
2336+
/// The Maven-CLI UA must actually go out on the wire: the mock only
2337+
/// serves the pom when the request carries `MAVEN_USER_AGENT`, so a
2338+
/// regression back to `SocketPatchCLI/…` misses the matcher and fails
2339+
/// the fetch.
2340+
#[tokio::test]
2341+
async fn pom_fetch_sends_the_maven_cli_user_agent() {
2342+
use wiremock::matchers::{header, method, path};
2343+
use wiremock::{Mock, MockServer, ResponseTemplate};
2344+
2345+
let pom_route = "/org/apache/commons/commons-text/1.10.0/commons-text-1.10.0.pom";
2346+
let server = MockServer::start().await;
2347+
Mock::given(method("GET"))
2348+
.and(path(pom_route))
2349+
.and(header("user-agent", MAVEN_USER_AGENT))
2350+
.respond_with(ResponseTemplate::new(200).set_body_bytes(UPSTREAM_POM.to_vec()))
2351+
.expect(1)
2352+
.mount(&server)
2353+
.await;
2354+
2355+
let bytes = fetch_pom_bytes(&format!("{}{pom_route}", server.uri()))
2356+
.await
2357+
.expect("pom fetch under the Maven CLI UA succeeds");
2358+
assert_eq!(bytes, UPSTREAM_POM);
2359+
}
2360+
23072361
/// A FIFO planted as `pom.xml` must fail the revert fast and loudly —
23082362
/// keeping the uuid dir for a retry — instead of wedging `--revert`
23092363
/// forever.

npm/socket-patch/package-lock.json

Lines changed: 206 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)