# RUSTSEC-2025-0173: `PamHandle::get_user` can cause an authentication bypass


- **Severity:** Not scored
- **Exploited in the wild:** Not known
- **Fix available:** Yes
- **Published:** 2 Jun 2025

## What is RUSTSEC-2025-0173?

RUSTSEC-2025-0173 is a vulnerability in pam-bindings, published on 2 Jun 2025. 

### Official description

In affected versions, `PamHandle::get_user` can return `Err(PAM_SUCCESS)` after it gets the username successfully.
PAM modules that return this "error" code from `sm_authenticate` or `sm_acct_mgmt` early-return a success code to PAM without doing any further verification.
This means a user could log in when they shouldn't be able to (e.g., if the module is `sufficient`).

The `pam_try!` macro of this crate early-returns the code in this exact way:

```rust
fn sm_authenticate(pamh: &mut PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode {
    let user = pam_try!(pamh.get_user(None)); // Can return PAM_SUCCESS here.
    // If it does, the module does not get to this line.
}
```

The root cause is an [incorrect FFI declaration][ffi-decl] for [`pam_get_user(3)`][pam-get-user].
This C function writes a pointer to the username through its `user` argument (of type `const char **user`).
This crate's binding declared this argument as a shared reference (`&*mut c_char`).
Writing through a shared reference is [undefined behavior][ub-immutable].

Thus, the compiler can assume that the local pointer, whose address is passed as `user`, is still null after the call.
After the call, the affected code [returns `Ok`][null-check] only if the return code is `PAM_SUCCESS` *and* this pointer is not null.
Otherwise, it returns the return code as an error.
If the compiler assumes that the pointer is null, `get_user` returns an error even when the return code is `PAM_SUCCESS`.
Release builds have been [observed to do this][observed-irl].
Debug builds usually work correctly, so tests in debug mode can miss the problem.

Version 0.1.2 changes the declaration to `&mut *const c_char`.
The fix is in commit [401c961](https://github.com/lvkv/pam-rs/commit/401c961800c4dde356464b6a7d455af844a3954a).

If a module cannot upgrade, do not return the error code from `get_user`.
Return a failure code instead, for example `pam_try!(pamh.get_user(None), PamResultCode::PAM_AUTH_ERR)`.
This makes the module deny access instead of allowing it, but the undefined behavior remains.

[pam-get-user]: https://github.com/linux-pam/linux-pam/blob/28fce1fd55b003fec90f34e5bc785e9439b216f2/libpam/include/security/pam_modules.h#L30-L31
[ffi-decl]: https://github.com/lvkv/pam-rs/blob/3d9318b5b812d9142595928deec23e5843a60995/pam/src/module.rs#L49-L53
[ub-immutable]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html#r-undefined.immutable
[null-check]: https://github.com/lvkv/pam-rs/blob/3d9318b5b812d9142595928deec23e5843a60995/pam/src/module.rs#L196-L202
[observed-irl]: https://github.com/lvkv/pam-rs/issues/16#issuecomment-3693665220

## Which versions are affected by RUSTSEC-2025-0173?

1 open source package ship an affected version, including pam-bindings.


| Package | Ecosystem | Affected | Fixed in |
| --- | --- | --- | --- |
| `pam-bindings` | crates.io | From 0.0.0-0 | 0.1.2 |

## How do I fix RUSTSEC-2025-0173?

Upgrade pam-bindings to 0.1.2 or later.

## Is RUSTSEC-2025-0173 being exploited?

There is no known exploitation of RUSTSEC-2025-0173 in the wild and no public exploit code.

## Fix prompt for AI coding agents

```text
Check this codebase for RUSTSEC-2025-0173 and fix it if it is affected.

What it is: RUSTSEC-2025-0173 is a vulnerability in pam-bindings, published on 2 Jun 2025. 
Exploitation: There is no known exploitation of RUSTSEC-2025-0173 in the wild and no public exploit code.

Affected packages and fixed versions:
- pam-bindings (crates.io): affected from 0.0.0-0; fixed in 0.1.2

Task:
1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.
2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.
3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.
4. Run the tests and summarise what changed and why.
5. If nothing in the project is affected, say so and change nothing.

Reference: https://insights.sbomify.com/RUSTSEC-2025-0173/ (Markdown: https://insights.sbomify.com/RUSTSEC-2025-0173/index.md)
```

## Sources

- OSV: https://osv.dev/vulnerability/RUSTSEC-2025-0173

---
From sbomify Insights: https://insights.sbomify.com/RUSTSEC-2025-0173/
Summaries are generated and may contain mistakes; the official description above is the record.
