Skip to content

apimock: Path traversal in apimock-server's file-serving fallback - #3176

Open
nabbisen wants to merge 2 commits into
rustsec:mainfrom
nabbisen:apimock-4_8_1-5_19_1
Open

apimock: Path traversal in apimock-server's file-serving fallback#3176
nabbisen wants to merge 2 commits into
rustsec:mainfrom
nabbisen:apimock-4_8_1-5_19_1

Conversation

@nabbisen

Copy link
Copy Markdown

Affected crate(s)

  • apimock (62,580 downloads all-time; 947 recent per crates.io)
  • apimock-server (653 downloads all-time; 408 recent per crates.io)

Links to upstream issue(s) or PR(s)

Filed by the crate maintainers — reported, fixed and disclosed by us, so
there is no third-party upstream report to link.

Severity

Path traversal allowing unauthenticated remote file disclosure: a
request carrying a raw .. segment escaped the configured response
directory, and the file was returned with HTTP 200. Read-only — no
write, no code execution.

Exposure is conditional on deployment, which is why we rate it modestly:

  • The default bind is 127.0.0.1, where an attacker must already be able
    to run a process on the machine.
  • Browsers and most HTTP clients and proxies normalise .. away before
    sending, so a malicious web page cannot reach it.
  • The genuinely exposed deployments bind 0.0.0.0 or a LAN address —
    most commonly a container, where binding loopback would make the port
    unreachable from the host. Multi-user machines are also affected on the
    loopback default.

CVSS v4.0: AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
AT:P records the non-default-bind requirement.

apimock is a development and testing mock server, not intended for
production or as a public listener; that context bounds the impact but
does not remove it, which is why it was fixed rather than documented.

Two crates, two version ranges

apimock spans both supported lines — 4.x ships as that single crate,
5.x as a workspace — so it carries two ranges with separate fixes:
< 4.8.1 (patched 4.8.1) and >= 5.0.0, < 5.19.1 (patched 5.19.1).
Both lines are supported; neither requires a major-version change.

apimock-server only exists post-split (first published 5.0.0), so its
range is >= 5.0.0, < 5.19.1, patched 5.19.1. It is filed separately
because it is published independently and carries the vulnerable serving
code — a dependent embedding it directly is affected without depending
on apimock.

Versions before 4.0.0 were not assessed and are therefore treated as
affected rather than claimed unaffected.

Checklist

  • Advisory filename(s) starts with RUSTSEC-0000-0000 as the ID
  • date field is set to the public disclosure date
  • Contains a concise and descriptive title after advisory metadata
  • Asked maintainer(s) if publishing an advisory is appropriate

@djc djc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reporting!

The advisory contents read like a fair amount of LLM slop. Suggest you edit it down to something more concise with only information that is directly relevant to downstream consumers.

id = "RUSTSEC-0000-0000"
package = "apimock-server"
date = "2026-08-26"
url = "https://github.com/apimokka/apimock-rs/security/advisories/GHSA-72g6-wgrg-vhm7"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not much point in linking the GHSA in the url when it's already used in aliases -- please link to an issue/PR/commit instead.

Comment on lines +24 to +28
This is the same issue as the advisory for the `apimock` crate. It is
recorded separately because `apimock-server` is published independently,
so a dependent embedding the server directly is affected without
depending on `apimock` at all.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see much point in having two advisories for the same thing? If apimock inherits the problem because it uses apimock-server under the covers, having just an advisory for apimock-server should be sufficient.

Review feedback on rustsec#3176.

Trimmed to what a downstream consumer acts on: the flaw, that it is
read-only, what affects reachability, and the fixed versions.
apimock-server goes from 67 lines to 33. Removed a paragraph describing
what apimock-server is, one justifying why two advisories were filed,
one about operator-authored respond.file_path and Rhai middleware paths
which are not the reported vulnerability, and the 4.x/5.x version-line
history.

url now points at the fixing commit on each line rather than repeating
the GHSA already present in aliases.

Version ranges are unchanged and remain correct.
@nabbisen

nabbisen commented Aug 31, 2026

Copy link
Copy Markdown
Author

@djc
Thanks — all three are fair, and the first one especially.

On the prose: you're right. I wrote these in the register we use for our own design documents, where explaining why is the point. That's the wrong register for an advisory, whose reader is triaging cargo audit output. Both are cut to what a downstream consumer acts on: what the flaw is, that it's read-only, what affects reachability, and the fixed versions. apimock-server goes from 67 lines to 33. What I removed was context about us rather than about the vulnerability — including, ironically, a paragraph explaining why I'd filed two advisories.

On the url: agreed, changed to the fixing commit on each line.

On having two advisories: I'd like to check one thing before acting, because I think the inheritance holds for one line and not the other.

apimock-server was first published at 5.0.0. The 4.x line predates the workspace split — apimock 4.x is a single crate with the serving code inside it and no apimock-server dependency at all. So an advisory on apimock-server alone would leave 4.x uncovered, and 4.x is still supported (4.8.1 and 4.8.2 both shipped this month).

For 5.x and later you're plainly right: apimock is a front-end over apimock-server and inherits the flaw through it.

I drafted a version that scoped the apimock advisory to 4.x only, then backed it out — expressing "this advisory covers 4.x, the other covers 5.x" via unaffected would have declared 5.0.0–5.19.0 unaffected, which isn't true. So the apimock advisory here keeps its original, correct ranges (patched = [">= 4.8.1, < 5.0.0", ">= 5.19.1"]), which does mean 5.x is described by both advisories.

Rather than invent a convention in your database: how would you prefer this expressed? Options I can see are to keep both as they are and accept that 5.x matches twice, or to drop the apimock advisory and accept that 4.x users aren't flagged. Happy to do either — I just didn't want to silently drop a supported line, or assert something false to avoid the overlap.

@djc

djc commented Aug 31, 2026

Copy link
Copy Markdown
Member

I would say it is true that apimock 5.x is unaffected by the apimock advisory, because it is covered by the apimock-server API. I think that would be the best way to express things -- so still two advisories, and add a line that clarifies the situation for both.

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

Successfully merging this pull request may close these issues.

2 participants