Skip to content

AES decrypt() ignores the supplied mode option, resulting in inconsistent CBC behavior #227

Description

@krishna28004

Description

The AES decrypt() API accepts a CipherOptions object containing a mode field, but the supplied mode is never used during decryption.

As a result, calling:

decrypt(input, key, { mode: "CBC" })

follows the same execution path as any other mode, leading to behavior that differs from what callers expect when requesting CBC.

This affects downstream functionality that relies on the mode option, including the Padding Oracle Simulator.


Evidence

Public API

decrypt() accepts a CipherOptions object:

export function decrypt(
  input: string,
  key: string,
  options: CipherOptions = {}
)

CipherOptions defines:

mode?: string

Current Execution Flow

The decryption path receives the options object but never checks or forwards options.mode.

if (options.instrument) {
  result = aesInstrumented(inputBytes, keyBytes, true)
} else {
  result = aesFast(inputBytes, keyBytes, true)
}

Both execution paths ignore the supplied mode.


Reproduction

  1. Call:
decrypt(ciphertext, key, {
  mode: "CBC",
  encoding: "hex"
})
  1. Trace execution through aes.ts.

  2. Observe that options.mode is never read or propagated.


Expected Behavior

The supplied mode should either:

  • be honored during decryption, or
  • be explicitly rejected if unsupported.

Ignoring a supported API option silently produces behavior that differs from caller expectations.


Actual Behavior

The supplied mode value is ignored without warning, and all requests follow the same decryption path.

This leads to inconsistent behavior for features that rely on CBC semantics, including the Padding Oracle Simulator.


Files

  • lib/cipher/symmetric/aes.ts
  • lib/attacks/paddingOracle.ts

Metadata

Metadata

Assignees

Labels

ECSoC26Elite Coders Summer of Code 2026

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions