sequelize / sequelize/sequelize

[Reopen] Mismatch date value sql injection checking due to timezone problem in moment.js and moment-timezone.js when using oracle dialect for DataTypes.DATE

Open
#18,062 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

pending-approval
Dominant language
TypeScript
Stars
30.4k
Forks
4.3k
Avg merge
1d 6h
Merged PRs (30d)
68

Description

/<!--
If you don't follow the issue template, your issue may be closed.

Remember to properly format your code in code blocks.

Please note this is an issue tracker, not a support forum.
For general questions, please use one of these:

Issue Creation Checklist

  • I understand that my issue will be automatically closed if I don't fill in the requested information
  • I have read the contribution guidelines

Bug Description

In the "src/sql-string.js", found the mismatch of using "moment" for formatting date as compare to using "moment-timezone" in "src/dialects/oracle/data-types.js".

In "src/sql-string.js":

...
        // Validate the date value using Moment.js with the expected format
        const formattedDate = moment(dateValue).format('YYYY-MM-DD HH:mm:ss.SSS Z');
      
        // If the formatted date doesn't match the input date value, throw an error
        if (formattedDate !== dateValue) {
          throw new Error("Invalid date value for TO_TIMESTAMP_TZ. Expected format: 'YYYY-MM-DD HH:mm:ss.SSS Z'");
...

In "src/dialects/oracle/data-types.js":

...
    _stringify(date, options) {
      const format = 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM';

      date = this._applyTimezone(date, options);

      const formatedDate = date.format('YYYY-MM-DD HH:mm:ss.SSS Z');

      return `TO_TIMESTAMP_TZ('${formatedDate}','${format}')`;
    }

    _applyTimezone(date, options) {
      if (options.timezone) {
        if (momentTz.tz.zone(options.timezone)) {
          date = momentTz(date).tz(options.timezone);
        } else {
          date = moment(date).utcOffset(options.timezone);
        }
      } else {
        date = momentTz(date);
      }
      return date;
    }
...

The stringify in oracle dialect data type "DATE" would use the "moment-timezone" for applying timezone, while in the "sql-string.js" checking of using "TO_TIMESTAMP_TZ" to prevent sql injection, it use "moment" with the default timezone in the environment.

There is some problem related to applying timezone for "Asia/Hong_Kong", below is the tested code:

import moment from "moment";
import momentTz from "moment-timezone";

const date = new Date("1904-01-01T00:00:00");
const date1 = moment(date).utcOffset("+00:00");
const date2 = momentTz(date).tz("+00:00");
const date3 = momentTz(date);
const date4 = moment(date).format("YYYY-MM-DD HH:mm:ss.SSS Z");
console.log("Date 1: " + date1.format("YYYY-MM-DD HH:mm:ss.SSS Z"));
console.log("Date 2: " + date2.format("YYYY-MM-DD HH:mm:ss.SSS Z"));
console.log("Date 3: " + date3.format("YYYY-MM-DD HH:mm:ss.SSS Z"));
console.log("Date 4: " + date4);

Outputs:

Date 1: 1903-12-31 16:23:18.000 +00:00
Date 2: 1904-01-01 00:00:00.000 +07:36
Date 3: 1904-01-01 00:00:00.000 +07:36
Date 4: 1904-01-01 00:00:00.000 +07:30

The problem lies into that there is 6 minutes difference between "moment" and "moment-timezone" when applying timezone for "Asia/Hong_Kong" for early dates. With these 6 minutes difference, the above "sql-string.js", "formattedDate" and "dateValue" will never match and throw exception.

You may try the above testing code located in the below link:
moment & moment-timezone test code

Reproducible Example

Here is the link to the SSCCE for this issue:

What do you expect to happen?
What is actually happening?
Environment
  • Sequelize version: 6.37.7
  • Node.js version: 22.16.0
  • If TypeScript related: TypeScript version:
  • Database & Version: Oracle DB EE 19c 19.18
  • Connector library & Version: oracledb (6.10.0)

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time and I know how to start.
  • Yes, I have the time but I will need guidance.
  • No, I don't have the time, but my company or I are supporting Sequelize through donations on OpenCollective.
  • No, I don't have the time, and I understand that I will need to wait until someone from the community or maintainers is interested in resolving my issue.

Indicate your interest in the resolution of this issue by adding the 👍 reaction. Comments such as "+1" will be removed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by comparing the date formatting and validation paths in src/sql-string.js and src/dialects/oracle/data-types.js, then run the linked moment and moment-timezone test code with the reported Oracle environment. Reproduce the early-date Asia/Hong_Kong mismatch and verify that valid Oracle DATE values no longer fail the TO_TIMESTAMP_TZ validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.