jackson-inject-security · git:20260424.d50cf5a · 2026-04-24 · sha256 e60f574ccbe14ddf

jackson-inject-security git:20260424.d50cf5aA

Immutable. This exact content never changes and is served at /api/v1/blob/e60f574ccbe14ddf.

---
name: jackson-inject-security
description: Preventing Jackson @JacksonInject override attacks where JSON input can replace server-side injected values.
---

# Jackson @JacksonInject Security

## The Vulnerability

When using `@JacksonInject` in Jackson `@JsonCreator` constructors, JSON input can override server-side injected values by default. This happens because `@JacksonInject` defaults to `useInput = OptBoolean.DEFAULT`, which allows JSON properties to take precedence over injected values.

## Attack Mechanism

If a class has:
```java
@JsonCreator
public MyClass(@JacksonInject MyConfig config) { ... }
```

An attacker can send JSON with `"": {"enabled": true}` to override the injected `config` value. The empty string key `""` maps to inject parameters that have no explicit ID.

Combined with `FAIL_ON_UNKNOWN_PROPERTIES = false` (common in many frameworks), the attack payload passes silently.

## Fix: useInput = OptBoolean.FALSE

Jackson 2.9+ introduced `OptBoolean` for `@JacksonInject`:

```java
import com.fasterxml.jackson.annotation.OptBoolean;

@JsonCreator
public MyClass(
    @JacksonInject(useInput = OptBoolean.FALSE) MyConfig config
) { ... }
```

This prevents JSON input from overriding the injected value entirely.

## Additional Defense: Constructor Validation

Add validation in the constructor to check the config before storing it:

```java
@JsonCreator
public MyClass(
    @JacksonInject(useInput = OptBoolean.FALSE) MyConfig config
) {
    Preconditions.checkState(config.isEnabled(), "Feature is disabled");
    this.config = config;
}
```

## Jackson Version Compatibility

- `OptBoolean.FALSE` for `@JacksonInject(useInput=...)` requires Jackson 2.9+
- Check with: `<jackson.version>` in `pom.xml`