Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

harden datetime verification #1702

Merged
merged 12 commits into from
Dec 1, 2023
Merged

harden datetime verification #1702

merged 12 commits into from
Dec 1, 2023

Conversation

bnewbold
Copy link
Collaborator

@bnewbold bnewbold commented Oct 3, 2023

This adds stronger datetime verification in the syntax package, including a bunch of interop test cases, and swaps that in during Lexicon verification.

The prior verification was pretty lax, so I suspect this might cause some problems to other devs, or with existing records, when we roll it out.

@bnewbold
Copy link
Collaborator Author

Some updates after discussing with @devinivy earlier in the week.

This keeps a proper ensureValid, and that is what we should use for, eg, new record creation.

It also has normalizeDatetime which has the dual role of normalizing even valid datetimes for sorting in a database column; and being somewhat more lenient for existing createdAt records, but will still throw on totally bogus stuff (eg, empty string or "asfd"). And then normalizeDatetimeAlways if we need a drop-in for toSimplifiedISOSafe, which returns UNIX epoch time if normalizeDatetime would have thrown.

Also rebased on top of main.

The review or feedback i'm still not sure about is whether the full strict validation will only happen on record creation. If that is true, great! Otherwise, if it is also validated when deserializing existing records, maybe we need special logic to distinguish between "new record creation" and "existing record parsing" for this corner-case. A test for this would probably be good.

if (!isValidISODateString(value)) {
throw new Error()
}
ensureValidDatetime(value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah this will happen everywhere - on new record creations & when validating existing records

I think we leave this code path as-is for now, and I can add in the more rigorous validation into the pds indexing path

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, makes sense. The normalizeDatetime function here would have pretty similar behavior to isValidISODateString, throwing a more specific error when a totally-not-a-datetime is encountered. But just sticking with exactly the current code would be less risky.

Copy link
Collaborator

@dholms dholms left a comment

Choose a reason for hiding this comment

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

Looks great!

Left a note about where the validation happens & what I think we should do there. I'm happy to tackle that

@bnewbold
Copy link
Collaborator Author

If you could tackle that, would be much appreciated!

Noticed tests failed on this branch, I think just flakey, trying a re-run of failed.

return
}
try {
ensureValidDatetime(createdAt)
Copy link
Collaborator

Choose a reason for hiding this comment

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

added the extra check here

This means records with bad timestamps will still pass "lexicon validation" (which we want so that old records don't break application views), but they will no longer be able to be created on the pds

this specific approach only works as is because the only datetimes on our records are createdAt times & every createdAt property is a datetime. if we get other datetimes, we'll need to tweak this logic

Comment on lines +70 to +71
describe('normalization', () => {
it('normalizes datetimes', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe this fun vector originally seen from retr0.id still makes it through, where the normalized date ends-up before year zero, which is invalid:

> normalizeDatetime('0000-01-01T00:00:00+01:00')
'-000001-12-31T23:00:00.000Z'

In toSimplifiedISOSafe() you'll find an extra validation check on the normalized output, which is what currently catches this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

just added a test for that, lmk how it looks 👍

Copy link
Collaborator

@devinivy devinivy left a comment

Choose a reason for hiding this comment

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

Feels nice to have this nailed down.

@bnewbold
Copy link
Collaborator Author

I didn't see @dholms small patch, and added a bigger patch which verifies that the output of the normalization function is itself valid. And also just disallows dates starting 000 (aka, before year 0010) to ward off more trickery. The specs somewhat disclaim the ability to do very old dates already.

If Dan's fix is simpler/better we can just revert my patches. I resolved a merge conflict.

@dholms
Copy link
Collaborator

dholms commented Dec 1, 2023

Yup yup I think that looks fine! finally gonna get this in 💪

@dholms dholms merged commit c17971a into main Dec 1, 2023
10 checks passed
@dholms dholms deleted the bnewbold/harden-datetime branch December 1, 2023 00:19
estrattonbailey added a commit that referenced this pull request Dec 5, 2023
…tab-should-show-own-threads

* origin/main: (59 commits)
  Config to start notifications daemon from a specific did (#1922)
  Feature branch: PDS v2 (#1789)
  Cleanup outdated notifications in appview, add daemon for similar tasks (#1893)
  Add flag for running db migrations on appview (#1913)
  Do not generate notifs when post violates threadgate (#1901)
  Version packages (#1909)
  Additional @atproto/api 0.6.24 changeset (#1912)
  Fix snapshots for list items (#1911)
  Attach record URI to listItemView (#1758)
  helpers for rkey and tid syntax; validate rkey at record creation time (#1738)
  harden datetime verification (#1702)
  fix(debug): properly type debugCatch wrapper result (#1817)
  style(xrpc-server): avoid un-neccessary "if" statement (#1826)
  perf(bsky): avoid re-creating auth functions on every request (#1822)
  Don't create unnecessary error objects (#1908)
  fix(pds): include aspectRatio on read-sticky posts (#1824)
  Handle missing creator on lists and feed generators (#1906)
  ✨ Expose labels attached with legacy actions when events are queried and fix email event builder (#1905)
  Evented architecture for moderation system (#1617)
  Put canReply state on post viewer state instead of thread viewer state (#1882)
  ...
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.

None yet

3 participants