From 8609ea82d219292ea4a5e01ed5352537a93f125b Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Wed, 19 Oct 2022 21:25:01 +0200 Subject: [PATCH 01/24] added an XSS example --- database/blogPosts.ts | 12 ++++++ migrations/003-create-table-blog-posts.ts | 7 ++++ pages/_app.tsx | 7 ++++ pages/example-6-xss/common.tsx | 48 +++++++++++++++++++++++ pages/example-6-xss/solution-1.tsx | 41 +++++++++++++++++++ pages/example-6-xss/solution-2.tsx | 41 +++++++++++++++++++ pages/example-6-xss/vulnerable.tsx | 40 +++++++++++++++++++ pages/index.tsx | 5 +++ util/cookies.ts | 2 +- 9 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 pages/example-6-xss/common.tsx create mode 100644 pages/example-6-xss/solution-1.tsx create mode 100644 pages/example-6-xss/solution-2.tsx create mode 100644 pages/example-6-xss/vulnerable.tsx diff --git a/database/blogPosts.ts b/database/blogPosts.ts index b0a7242..06917c9 100644 --- a/database/blogPosts.ts +++ b/database/blogPosts.ts @@ -107,3 +107,15 @@ export async function getBlogPostsBySessionToken(sessionToken: string) { `; return blogPosts; } + +export async function getSpecialBlogPosts() { + const blogPosts = await sql` + SELECT + * + FROM + blog_posts + WHERE + id = 6 + `; + return blogPosts; +} diff --git a/migrations/003-create-table-blog-posts.ts b/migrations/003-create-table-blog-posts.ts index f272395..c4ac4dc 100644 --- a/migrations/003-create-table-blog-posts.ts +++ b/migrations/003-create-table-blog-posts.ts @@ -36,6 +36,13 @@ const blogPosts = [ is_published: true, user_id: 2, }, + { + title: "Special Blogpost", + text_content: + 'This is a special one ', + is_published: true, + user_id: 1, + }, ]; export async function up(sql: Sql>) { diff --git a/pages/_app.tsx b/pages/_app.tsx index fde05f7..54374aa 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -66,6 +66,13 @@ export default function App({ Component, pageProps }: AppProps) { Example 5 + + Example 6 + +
{!user && ( <> diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-xss/common.tsx new file mode 100644 index 0000000..c0b06fb --- /dev/null +++ b/pages/example-6-xss/common.tsx @@ -0,0 +1,48 @@ +import LinkIfNotCurrent from '../../components/LinkIfNotCurrent'; +import { BlogPost } from '../../database/blogPosts'; + +type Props = + | { + error: string; + } + | { + blogPosts: BlogPost[]; + }; + +export function CommonContent(props: Props) { + return ( + <> +

XSS - getServerSideProps

+ +
    +
  • + + Vulnerable + +
  • +
  • + + Solution 1 + +
  • +
  • + + Solution 2 + +
  • +
+ +
+ +
+ The following blog posts should only be visible for logged-in users. +
+
+ If a user is not logged in, an error message should appear. +
+ +

Blog Posts

+ + ); +} + diff --git a/pages/example-6-xss/solution-1.tsx b/pages/example-6-xss/solution-1.tsx new file mode 100644 index 0000000..edbe277 --- /dev/null +++ b/pages/example-6-xss/solution-1.tsx @@ -0,0 +1,41 @@ +import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { CommonContent } from './common'; +import DOMPurify from "dompurify" + +type Props = + | { + error: string; + } + | { + blogPosts: BlogPost[]; + }; + +export default function MissingAuthenticationGssp(props: Props) { + return ( +
+ + + {'error' in props &&
{props.error}
} + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
+

{blogPost.title}

+
Published: {String(blogPost.isPublished)}
+
{blogPost.textContent}
+
+ ); + })} +
+ ); +} + +export async function getServerSideProps() { + const blogPosts = await getSpecialBlogPosts(); + return { + props: { + blogPosts: blogPosts, + }, + }; +} diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx new file mode 100644 index 0000000..f1e5bf6 --- /dev/null +++ b/pages/example-6-xss/solution-2.tsx @@ -0,0 +1,41 @@ +import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { CommonContent } from './common'; +import DOMPurify from "dompurify" + +type Props = + | { + error: string; + } + | { + blogPosts: BlogPost[]; + }; + +export default function MissingAuthenticationGssp(props: Props) { + return ( +
+ + + {'error' in props &&
{props.error}
} + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
+

{blogPost.title}

+
Published: {String(blogPost.isPublished)}
+

+
+ ); + })} +
+ ); +} + +export async function getServerSideProps() { + const blogPosts = await getSpecialBlogPosts(); + return { + props: { + blogPosts: blogPosts, + }, + }; +} diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-xss/vulnerable.tsx new file mode 100644 index 0000000..63b723b --- /dev/null +++ b/pages/example-6-xss/vulnerable.tsx @@ -0,0 +1,40 @@ +import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import {CommonContent} from './common'; + +type Props = + | { + error: string; + } + | { + blogPosts: BlogPost[]; + }; + +export default function MissingAuthenticationGssp(props: Props) { + return ( +
+ + + {'error' in props &&
{props.error}
} + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
+

{blogPost.title} - Vulnerable

+
Published: {String(blogPost.isPublished)}
+

+
+ ); + })} +
+ ); +} + +export async function getServerSideProps() { + const blogPosts = await getSpecialBlogPosts(); + return { + props: { + blogPosts: blogPosts, + }, + }; +} diff --git a/pages/index.tsx b/pages/index.tsx index 8757b9c..b3542d6 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -29,6 +29,11 @@ export default function Home() { Example 5: Data Exposure +
  • + + Example 6: XSS + +
  • ); diff --git a/util/cookies.ts b/util/cookies.ts index 46e55e9..bb03882 100644 --- a/util/cookies.ts +++ b/util/cookies.ts @@ -16,7 +16,7 @@ export function createSerializedSessionTokenCookie(token: string) { // Important for security // Deny cookie access from frontend JavaScript - httpOnly: true, + httpOnly: false, // Important for security // Set secure cookies on production (eg. Heroku) From 7e99792b93ebd70b6011804947532f5434f1c760 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Sun, 23 Oct 2022 15:29:21 +0200 Subject: [PATCH 02/24] Added XSS solution example with markdown --- database/blogPosts.ts | 4 +- migrations/003-create-table-blog-posts.ts | 9 ++++- package.json | 2 + pages/example-6-xss/common.tsx | 5 +++ pages/example-6-xss/solution-1.tsx | 3 +- pages/example-6-xss/solution-2.tsx | 2 +- pages/example-6-xss/solution-3.tsx | 45 +++++++++++++++++++++++ pages/example-6-xss/vulnerable.tsx | 2 +- 8 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 pages/example-6-xss/solution-3.tsx diff --git a/database/blogPosts.ts b/database/blogPosts.ts index 06917c9..cf6e354 100644 --- a/database/blogPosts.ts +++ b/database/blogPosts.ts @@ -108,14 +108,14 @@ export async function getBlogPostsBySessionToken(sessionToken: string) { return blogPosts; } -export async function getSpecialBlogPosts() { +export async function getSpecialBlogPosts(id: number) { const blogPosts = await sql` SELECT * FROM blog_posts WHERE - id = 6 + id = ${id} `; return blogPosts; } diff --git a/migrations/003-create-table-blog-posts.ts b/migrations/003-create-table-blog-posts.ts index c4ac4dc..b4fd95b 100644 --- a/migrations/003-create-table-blog-posts.ts +++ b/migrations/003-create-table-blog-posts.ts @@ -37,12 +37,19 @@ const blogPosts = [ user_id: 2, }, { - title: "Special Blogpost", + title: "Special Blogpost 2", text_content: 'This is a special one ', is_published: true, user_id: 1, }, + { + title: "Special Blogpost", + text_content: + 'This is another **special one** - markdown formatted', + is_published: true, + user_id: 1, + }, ]; export async function up(sql: Sql>) { diff --git a/package.json b/package.json index 94f89b8..9a48642 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/dotenv-safe": "8.1.2", "bcrypt": "5.1.0", "cookie": "0.5.0", + "dompurify": "^2.4.0", "dotenv-cli": "6.0.0", "dotenv-safe": "8.2.0", "ley": "0.8.1", @@ -21,6 +22,7 @@ "postgres": "3.3.1", "react": "18.2.0", "react-dom": "18.2.0", + "react-markdown": "^8.0.3", "sharp": "0.31.1", "tsm": "2.2.2" }, diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-xss/common.tsx index c0b06fb..ebf695e 100644 --- a/pages/example-6-xss/common.tsx +++ b/pages/example-6-xss/common.tsx @@ -30,6 +30,11 @@ export function CommonContent(props: Props) { Solution 2 +
  • + + Solution 3 + +

  • diff --git a/pages/example-6-xss/solution-1.tsx b/pages/example-6-xss/solution-1.tsx index edbe277..72070af 100644 --- a/pages/example-6-xss/solution-1.tsx +++ b/pages/example-6-xss/solution-1.tsx @@ -1,6 +1,5 @@ import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; import { CommonContent } from './common'; -import DOMPurify from "dompurify" type Props = | { @@ -32,7 +31,7 @@ export default function MissingAuthenticationGssp(props: Props) { } export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(); + const blogPosts = await getSpecialBlogPosts(6); return { props: { blogPosts: blogPosts, diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx index f1e5bf6..26c9ea2 100644 --- a/pages/example-6-xss/solution-2.tsx +++ b/pages/example-6-xss/solution-2.tsx @@ -32,7 +32,7 @@ export default function MissingAuthenticationGssp(props: Props) { } export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(); + const blogPosts = await getSpecialBlogPosts(6); return { props: { blogPosts: blogPosts, diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-xss/solution-3.tsx new file mode 100644 index 0000000..d2b2b63 --- /dev/null +++ b/pages/example-6-xss/solution-3.tsx @@ -0,0 +1,45 @@ +import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { CommonContent } from './common'; +import ReactMarkdown from "react-markdown" + +type Props = + | { + error: string; + } + | { + blogPosts: BlogPost[]; + }; + +export default function MissingAuthenticationGssp(props: Props) { + return ( +
    + + + {'error' in props &&
    {props.error}
    } + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + // be careful which markdown library you use and how you use it + // by default the markdown standard supports html tags too + // so never assign markdown directly to innerHTML + // but the default usage of "ReactMarkdown" is safe + return ( +
    +

    {blogPost.title}

    +
    Published: {String(blogPost.isPublished)}
    + +
    + ); + })} +
    + ); +} + +export async function getServerSideProps() { + const blogPosts = await getSpecialBlogPosts(7); + return { + props: { + blogPosts: blogPosts, + }, + }; +} diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-xss/vulnerable.tsx index 63b723b..56e83a9 100644 --- a/pages/example-6-xss/vulnerable.tsx +++ b/pages/example-6-xss/vulnerable.tsx @@ -31,7 +31,7 @@ export default function MissingAuthenticationGssp(props: Props) { } export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(); + const blogPosts = await getSpecialBlogPosts(6); return { props: { blogPosts: blogPosts, From 99f374ef384e73656a52c1905ec58880d85d8a6c Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Mon, 24 Oct 2022 18:30:11 +0200 Subject: [PATCH 03/24] Revert allowing cookie access from JS --- util/cookies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/cookies.ts b/util/cookies.ts index bb03882..46e55e9 100644 --- a/util/cookies.ts +++ b/util/cookies.ts @@ -16,7 +16,7 @@ export function createSerializedSessionTokenCookie(token: string) { // Important for security // Deny cookie access from frontend JavaScript - httpOnly: false, + httpOnly: true, // Important for security // Set secure cookies on production (eg. Heroku) From 552f4e0b08113380fbcd6f870f21872849014798 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Mon, 24 Oct 2022 18:46:10 +0200 Subject: [PATCH 04/24] Lock version, run `yarn` --- package.json | 4 +- yarn.lock | 506 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 503 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d535cf5..6e76088 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@types/dotenv-safe": "8.1.2", "bcrypt": "5.1.0", "cookie": "0.5.0", - "dompurify": "^2.4.0", + "dompurify": "2.4.0", "dotenv-cli": "6.0.0", "dotenv-safe": "8.2.0", "ley": "0.8.1", @@ -22,7 +22,7 @@ "postgres": "3.3.1", "react": "18.2.0", "react-dom": "18.2.0", - "react-markdown": "^8.0.3", + "react-markdown": "8.0.3", "sharp": "0.31.1", "tsm": "2.2.2" }, diff --git a/yarn.lock b/yarn.lock index ac76dbb..8c4e7df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1279,6 +1279,13 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.1.tgz#b29aa1f91a59f35e29ff8f7cb24faf1a3a750554" integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g== +"@types/debug@^4.0.0": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + "@types/dotenv-safe@8.1.2": version "8.1.2" resolved "https://registry.yarnpkg.com/@types/dotenv-safe/-/dotenv-safe-8.1.2.tgz#72f126969f445af5654efd3167deabc2cbc6c24e" @@ -1286,6 +1293,13 @@ dependencies: dotenv "^8.2.0" +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -1296,6 +1310,18 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/ms@*": + version "0.7.31" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + "@types/node@*": version "18.6.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.2.tgz#ffc5f0f099d27887c8d9067b54e55090fcd54126" @@ -1316,7 +1342,7 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.0.0": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== @@ -1356,6 +1382,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== +"@types/unist@*", "@types/unist@^2.0.0": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "@typescript-eslint/eslint-plugin@5.40.1", "@typescript-eslint/eslint-plugin@^5.5.0": version "5.40.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz#3203a6ff396b1194083faaa6e5110c401201d7d5" @@ -1650,6 +1681,11 @@ babel-preset-react-app@^10.0.1: babel-plugin-macros "^3.1.0" babel-plugin-transform-react-remove-prop-types "^0.4.24" +bail@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1755,6 +1791,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -1822,6 +1863,11 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" +comma-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" + integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1892,7 +1938,7 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1913,6 +1959,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decode-named-character-reference@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + dependencies: + character-entities "^2.0.0" + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -1948,11 +2001,21 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + detect-libc@^2.0.0, detect-libc@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== +diff@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1974,6 +2037,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dompurify@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.0.tgz#c9c88390f024c2823332615c9e20a453cf3825dd" + integrity sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA== + dotenv-cli@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-6.0.0.tgz#8a30cbc59d0a8aaa166b2fee0a9a55e23a1223ab" @@ -2563,6 +2631,11 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2869,6 +2942,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hast-util-whitespace@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c" + integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg== + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -2928,6 +3006,11 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -2962,6 +3045,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-builtin-module@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" @@ -3034,6 +3122,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -3144,7 +3237,7 @@ json5@^2.2.1: array-includes "^3.1.5" object.assign "^4.1.2" -kleur@^4.1.0: +kleur@^4.0.3, kleur@^4.1.0: version "4.1.5" resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== @@ -3242,11 +3335,253 @@ make-dir@^3.1.0: dependencies: semver "^6.0.0" +mdast-util-definitions@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" + integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + +mdast-util-from-markdown@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" + integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + +mdast-util-to-hast@^12.1.0: + version "12.2.4" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.4.tgz#34c1ef2b6cf01c27b3e3504e2c977c76f722e7e1" + integrity sha512-a21xoxSef1l8VhHxS1Dnyioz6grrJkoaCUgGzMD/7dWHvboYX3VW53esRUfB5tgTyz4Yos1n25SPcj35dJqmAg== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-definitions "^5.0.0" + micromark-util-sanitize-uri "^1.1.0" + trim-lines "^3.0.0" + unist-builder "^3.0.0" + unist-util-generated "^2.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + +mdast-util-to-string@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" + integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micromark-core-commonmark@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" + integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + +micromark-factory-destination@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" + integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" + integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-space@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" + integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" + integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" + integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" + integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" + integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" + integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" + integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" + integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" + integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-encode@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" + integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== + +micromark-util-html-tag-name@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" + integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== + +micromark-util-normalize-identifier@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" + integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" + integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz#f12e07a85106b902645e0364feb07cf253a85aee" + integrity sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" + integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-util-symbol@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" + integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" + integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== + +micromark@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.1.0.tgz#eeba0fe0ac1c9aaef675157b52c166f125e89f62" + integrity sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -3658,7 +3993,7 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -3667,6 +4002,11 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +property-information@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" + integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -3708,6 +4048,32 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-markdown@8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.3.tgz#e8aba0d2f5a1b2124d476ee1fff9448a2f57e4b3" + integrity sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A== + dependencies: + "@types/hast" "^2.0.0" + "@types/prop-types" "^15.0.0" + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^2.0.0" + prop-types "^15.0.0" + property-information "^6.0.0" + react-is "^18.0.0" + remark-parse "^10.0.0" + remark-rehype "^10.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unified "^10.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + react@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -3810,6 +4176,25 @@ regjsparser@^0.8.2: dependencies: jsesc "~0.5.0" +remark-parse@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" + integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.0.0" + +remark-rehype@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" + integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^12.1.0" + unified "^10.0.0" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3852,7 +4237,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -sade@^1.7.0: +sade@^1.7.0, sade@^1.7.3: version "1.8.1" resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== @@ -3986,6 +4371,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +space-separated-tokens@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" + integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -4094,6 +4484,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + styled-jsx@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48" @@ -4199,6 +4596,16 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + +trough@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" + integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -4300,6 +4707,67 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== +unified@^10.0.0: + version "10.1.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== + dependencies: + "@types/unist" "^2.0.0" + bail "^2.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^4.0.0" + trough "^2.0.0" + vfile "^5.0.0" + +unist-builder@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" + integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-generated@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" + integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== + +unist-util-is@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" + integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + +unist-util-position@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" + integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-stringify-position@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-visit-parents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" + integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + +unist-util-visit@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" + integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + update-browserslist-db@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" @@ -4325,6 +4793,16 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -4333,6 +4811,24 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +vfile-message@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.2.tgz#a2908f64d9e557315ec9d7ea3a910f658ac05f7d" + integrity sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + +vfile@^5.0.0: + version "5.3.5" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.5.tgz#ec2e206b1414f561c85b7972bb1eeda8ab47ee61" + integrity sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" From 547b3983e495f68ef610a18a421f0609aa26eae1 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Mon, 24 Oct 2022 18:51:08 +0200 Subject: [PATCH 05/24] Move error to CommonContent component --- pages/example-6-xss/common.tsx | 3 ++- pages/example-6-xss/solution-1.tsx | 4 +--- pages/example-6-xss/solution-2.tsx | 4 +--- pages/example-6-xss/solution-3.tsx | 4 +--- pages/example-6-xss/vulnerable.tsx | 4 +--- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-xss/common.tsx index ebf695e..629c1e6 100644 --- a/pages/example-6-xss/common.tsx +++ b/pages/example-6-xss/common.tsx @@ -47,7 +47,8 @@ export function CommonContent(props: Props) {

    Blog Posts

    + + {'error' in props &&
    {props.error}
    } ); } - diff --git a/pages/example-6-xss/solution-1.tsx b/pages/example-6-xss/solution-1.tsx index 72070af..8ed8040 100644 --- a/pages/example-6-xss/solution-1.tsx +++ b/pages/example-6-xss/solution-1.tsx @@ -12,9 +12,7 @@ type Props = export default function MissingAuthenticationGssp(props: Props) { return (
    - - - {'error' in props &&
    {props.error}
    } + {'blogPosts' in props && props.blogPosts.map((blogPost) => { diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx index 26c9ea2..cccfed7 100644 --- a/pages/example-6-xss/solution-2.tsx +++ b/pages/example-6-xss/solution-2.tsx @@ -13,9 +13,7 @@ type Props = export default function MissingAuthenticationGssp(props: Props) { return (
    - - - {'error' in props &&
    {props.error}
    } + {'blogPosts' in props && props.blogPosts.map((blogPost) => { diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-xss/solution-3.tsx index d2b2b63..9a12be5 100644 --- a/pages/example-6-xss/solution-3.tsx +++ b/pages/example-6-xss/solution-3.tsx @@ -13,9 +13,7 @@ type Props = export default function MissingAuthenticationGssp(props: Props) { return (
    - - - {'error' in props &&
    {props.error}
    } + {'blogPosts' in props && props.blogPosts.map((blogPost) => { diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-xss/vulnerable.tsx index 56e83a9..1cccd3d 100644 --- a/pages/example-6-xss/vulnerable.tsx +++ b/pages/example-6-xss/vulnerable.tsx @@ -12,9 +12,7 @@ type Props = export default function MissingAuthenticationGssp(props: Props) { return (
    - - - {'error' in props &&
    {props.error}
    } + {'blogPosts' in props && props.blogPosts.map((blogPost) => { From 05a59a11f923d7d8f5f617da9eae1a4878e4a628 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Mon, 24 Oct 2022 18:57:05 +0200 Subject: [PATCH 06/24] Make example 4 files easier to compare --- .../common.tsx | 23 ++----------------- .../solution-1.tsx | 19 +++++++++++++-- .../solution-2.tsx | 19 +++++++++++++-- .../vulnerable-1.tsx | 19 +++++++++++++-- .../vulnerable-2.tsx | 4 +--- 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/pages/example-4-missing-authorization-gssp/common.tsx b/pages/example-4-missing-authorization-gssp/common.tsx index c3378ff..81a6255 100644 --- a/pages/example-4-missing-authorization-gssp/common.tsx +++ b/pages/example-4-missing-authorization-gssp/common.tsx @@ -9,7 +9,7 @@ type Props = blogPosts: BlogPost[]; }; -export function CommonContent() { +export function CommonContent(props: Props) { return ( <>

    Missing Authorization - getServerSideProps

    @@ -49,27 +49,8 @@ export function CommonContent() {

    Unpublished Blog Posts

    - - ); -} - -export default function Common(props: Props) { - return ( -
    - {'error' in props &&
    {props.error}
    } - - {'blogPosts' in props && - props.blogPosts.map((blogPost) => { - return ( -
    -

    {blogPost.title}

    -
    Published: {String(blogPost.isPublished)}
    -
    {blogPost.textContent}
    -
    - ); - })} -
    + ); } diff --git a/pages/example-4-missing-authorization-gssp/solution-1.tsx b/pages/example-4-missing-authorization-gssp/solution-1.tsx index ceddf3e..352334f 100644 --- a/pages/example-4-missing-authorization-gssp/solution-1.tsx +++ b/pages/example-4-missing-authorization-gssp/solution-1.tsx @@ -3,7 +3,7 @@ import { BlogPost, getUnpublishedBlogPostsBySessionToken, } from '../../database/blogPosts'; -import Common from './common'; +import { CommonContent } from './common'; type Props = | { @@ -14,7 +14,22 @@ type Props = }; export default function MissingAuthorizationGssp(props: Props) { - return ; + return ( +
    + + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
    +

    {blogPost.title}

    +
    Published: {String(blogPost.isPublished)}
    +
    {blogPost.textContent}
    +
    + ); + })} +
    + ); } export async function getServerSideProps(context: GetServerSidePropsContext) { diff --git a/pages/example-4-missing-authorization-gssp/solution-2.tsx b/pages/example-4-missing-authorization-gssp/solution-2.tsx index e7185b0..0bf0941 100644 --- a/pages/example-4-missing-authorization-gssp/solution-2.tsx +++ b/pages/example-4-missing-authorization-gssp/solution-2.tsx @@ -4,7 +4,7 @@ import { getUnpublishedBlogPostsByUserId, } from '../../database/blogPosts'; import { getUserByValidSessionToken } from '../../database/users'; -import Common from './common'; +import { CommonContent } from './common'; type Props = | { @@ -15,7 +15,22 @@ type Props = }; export default function MissingAuthorizationGssp(props: Props) { - return ; + return ( +
    + + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
    +

    {blogPost.title}

    +
    Published: {String(blogPost.isPublished)}
    +
    {blogPost.textContent}
    +
    + ); + })} +
    + ); } export async function getServerSideProps(context: GetServerSidePropsContext) { diff --git a/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx b/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx index bde2b71..fe1e2e2 100644 --- a/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx +++ b/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx @@ -1,5 +1,5 @@ import { BlogPost, getUnpublishedBlogPosts } from '../../database/blogPosts'; -import Common from './common'; +import { CommonContent } from './common'; type Props = | { @@ -10,7 +10,22 @@ type Props = }; export default function MissingAuthorizationGssp(props: Props) { - return ; + return ( +
    + + + {'blogPosts' in props && + props.blogPosts.map((blogPost) => { + return ( +
    +

    {blogPost.title}

    +
    Published: {String(blogPost.isPublished)}
    +
    {blogPost.textContent}
    +
    + ); + })} +
    + ); } export async function getServerSideProps() { diff --git a/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx b/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx index 8e7d188..74ef3f5 100644 --- a/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx +++ b/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx @@ -15,9 +15,7 @@ type Props = export default function MissingAuthorizationGssp(props: Props) { return (
    - - - {'error' in props &&
    {props.error}
    } + {'blogPosts' in props && props.blogPosts.map((blogPost) => { From 3e83c886e7da5350ffd00aa25140ec5330b59761 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 12:18:33 +0200 Subject: [PATCH 07/24] Add dompurify types, fix import style --- package.json | 1 + pages/example-6-xss/solution-2.tsx | 2 +- pages/example-6-xss/solution-3.tsx | 2 +- yarn.lock | 12 ++++++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6e76088..8113fe2 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@babel/eslint-parser": "7.19.1", "@next/eslint-plugin-next": "12.3.1", "@types/bcrypt": "5.0.0", + "@types/dompurify": "2.3.4", "@types/node": "18.11.3", "@types/react": "18.0.21", "@types/react-dom": "18.0.6", diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx index cccfed7..e543256 100644 --- a/pages/example-6-xss/solution-2.tsx +++ b/pages/example-6-xss/solution-2.tsx @@ -1,6 +1,6 @@ +import DOMPurify from 'dompurify'; import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; import { CommonContent } from './common'; -import DOMPurify from "dompurify" type Props = | { diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-xss/solution-3.tsx index 9a12be5..6b090ec 100644 --- a/pages/example-6-xss/solution-3.tsx +++ b/pages/example-6-xss/solution-3.tsx @@ -1,6 +1,6 @@ +import ReactMarkdown from 'react-markdown'; import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; import { CommonContent } from './common'; -import ReactMarkdown from "react-markdown" type Props = | { diff --git a/yarn.lock b/yarn.lock index 8c4e7df..db79341 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1286,6 +1286,13 @@ dependencies: "@types/ms" "*" +"@types/dompurify@2.3.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.3.4.tgz#94e997e30338ea24d4c8d08beca91ce4dd17a1b4" + integrity sha512-EXzDatIb5EspL2eb/xPGmaC8pePcTHrkDCONjeisusLFrVfl38Pjea/R0YJGu3k9ZQadSvMqW0WXPI2hEo2Ajg== + dependencies: + "@types/trusted-types" "*" + "@types/dotenv-safe@8.1.2": version "8.1.2" resolved "https://registry.yarnpkg.com/@types/dotenv-safe/-/dotenv-safe-8.1.2.tgz#72f126969f445af5654efd3167deabc2cbc6c24e" @@ -1382,6 +1389,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== +"@types/trusted-types@*": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" + integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" From 976cdccf694e4ad30a3da723106214f8eb12b1d7 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 12:19:58 +0200 Subject: [PATCH 08/24] Format code, remove extra p element --- pages/example-6-xss/solution-2.tsx | 6 +++++- pages/example-6-xss/solution-3.tsx | 2 +- pages/example-6-xss/vulnerable.tsx | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx index e543256..e26d3d0 100644 --- a/pages/example-6-xss/solution-2.tsx +++ b/pages/example-6-xss/solution-2.tsx @@ -21,7 +21,11 @@ export default function MissingAuthenticationGssp(props: Props) {

    {blogPost.title}

    Published: {String(blogPost.isPublished)}
    -

    +
    ); })} diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-xss/solution-3.tsx index 6b090ec..5d98c81 100644 --- a/pages/example-6-xss/solution-3.tsx +++ b/pages/example-6-xss/solution-3.tsx @@ -25,7 +25,7 @@ export default function MissingAuthenticationGssp(props: Props) {

    {blogPost.title}

    Published: {String(blogPost.isPublished)}
    - +
    ); })} diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-xss/vulnerable.tsx index 1cccd3d..41e7ba4 100644 --- a/pages/example-6-xss/vulnerable.tsx +++ b/pages/example-6-xss/vulnerable.tsx @@ -1,5 +1,5 @@ import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; -import {CommonContent} from './common'; +import { CommonContent } from './common'; type Props = | { @@ -20,7 +20,7 @@ export default function MissingAuthenticationGssp(props: Props) {

    {blogPost.title} - Vulnerable

    Published: {String(blogPost.isPublished)}
    -

    +
    ); })} From c8c0d8da0eb8fce36fd7bf2360eeff13d8704e27 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 13:02:14 +0200 Subject: [PATCH 09/24] Set NODE_ENV to production --- .github/workflows/lint-check-types-build.yml | 2 ++ database/connect.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint-check-types-build.yml b/.github/workflows/lint-check-types-build.yml index 3ed39e2..c6e96d2 100644 --- a/.github/workflows/lint-check-types-build.yml +++ b/.github/workflows/lint-check-types-build.yml @@ -5,6 +5,8 @@ jobs: lint-and-check-types-and-build: name: Lint, Check Types, Build runs-on: ubuntu-latest + env: + NODE_ENV: production steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 diff --git a/database/connect.ts b/database/connect.ts index 1d0e254..e76bd67 100644 --- a/database/connect.ts +++ b/database/connect.ts @@ -1,7 +1,7 @@ import { config } from 'dotenv-safe'; import postgres from 'postgres'; -config(); +if (process.env.NODE_ENV !== 'production') config(); // Type needed for the connection function below declare module globalThis { From 3d5e89f5b236d5531aba0495b25ed1485c5fcb14 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 13:04:05 +0200 Subject: [PATCH 10/24] Move NODE_ENV to only build step --- .github/workflows/lint-check-types-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/lint-check-types-build.yml b/.github/workflows/lint-check-types-build.yml index c6e96d2..83fdd85 100644 --- a/.github/workflows/lint-check-types-build.yml +++ b/.github/workflows/lint-check-types-build.yml @@ -5,8 +5,6 @@ jobs: lint-and-check-types-and-build: name: Lint, Check Types, Build runs-on: ubuntu-latest - env: - NODE_ENV: production steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -19,6 +17,7 @@ jobs: - run: yarn build env: API_KEY: ${{ secrets.API_KEY }} + NODE_ENV: production PGHOST: localhost PGDATABASE: security_vulnerability_examples PGUSERNAME: security_vulnerability_examples From 2b7662b313b23588ef11f3b95a72a59d8f95194f Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 13:07:23 +0200 Subject: [PATCH 11/24] Export null-returning component for Next.js build --- pages/example-4-missing-authorization-gssp/common.tsx | 5 +++++ pages/example-6-xss/common.tsx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/pages/example-4-missing-authorization-gssp/common.tsx b/pages/example-4-missing-authorization-gssp/common.tsx index 81a6255..074c24f 100644 --- a/pages/example-4-missing-authorization-gssp/common.tsx +++ b/pages/example-4-missing-authorization-gssp/common.tsx @@ -54,3 +54,8 @@ export function CommonContent(props: Props) { ); } + +// Export component for Next.js page build +export default function Common() { + return null; +} diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-xss/common.tsx index 629c1e6..2397e88 100644 --- a/pages/example-6-xss/common.tsx +++ b/pages/example-6-xss/common.tsx @@ -52,3 +52,8 @@ export function CommonContent(props: Props) { ); } + +// Export component for Next.js page build +export default function Common() { + return null; +} From b6df2840ef458f9ec0c7451a865adcfe06f3bd96 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 16:37:47 +0200 Subject: [PATCH 12/24] Add missing ESLint dependencies, fix problems --- database/blogPosts.ts | 2 +- migrations/001-create-table-users.ts | 15 +- migrations/003-create-table-blog-posts.ts | 63 +- package.json | 23 +- yarn.lock | 774 +++++++++++++++++++--- 5 files changed, 740 insertions(+), 137 deletions(-) diff --git a/database/blogPosts.ts b/database/blogPosts.ts index cf6e354..61dbe51 100644 --- a/database/blogPosts.ts +++ b/database/blogPosts.ts @@ -5,7 +5,7 @@ export type BlogPost = { title: string; textContent: string; isPublished: boolean; - userId: number; + userId: number | null; }; export async function getBlogPosts() { diff --git a/migrations/001-create-table-users.ts b/migrations/001-create-table-users.ts index d7eb10f..1996d1c 100644 --- a/migrations/001-create-table-users.ts +++ b/migrations/001-create-table-users.ts @@ -5,14 +5,14 @@ const users = [ // id: 1, username: 'alice', // password: abc - password_hash: + passwordHash: '$2b$12$rip3gbockwavRttTaMZa.u5JKY1542MOLBI7YGkRXaj83rtocfl3a', }, { // id: 2, username: 'bob', // password: def - password_hash: + passwordHash: '$2b$12$0N14zwm7.gFNB9UriJpo9eHqCBSezv1zdvbLL7ql79KYJM50fvo6q', }, ]; @@ -26,9 +26,14 @@ export async function up(sql: Sql>) { ); `; - await sql` - INSERT INTO users ${sql(users, 'username', 'password_hash')} - `; + for (const user of users) { + await sql` + INSERT INTO users + (username, password_hash) + VALUES + (${user.username}, ${user.passwordHash}) + `; + } } export async function down(sql: Sql>) { diff --git a/migrations/003-create-table-blog-posts.ts b/migrations/003-create-table-blog-posts.ts index b4fd95b..f99ce34 100644 --- a/migrations/003-create-table-blog-posts.ts +++ b/migrations/003-create-table-blog-posts.ts @@ -3,52 +3,52 @@ import { Sql } from 'postgres'; const blogPosts = [ { title: "Alice's first post (published)", - text_content: + textContent: "This is Alice's first post. It's published, so this is data that all logged-in users are allowed to view.", - is_published: true, - user_id: 1, + isPublished: true, + userId: 1, }, { title: "Alice's second post (unpublished)", - text_content: + textContent: "This is Alice's second post. It's not published, so this is private data that only Alice should be able to view and edit.", - is_published: false, - user_id: 1, + isPublished: false, + userId: 1, }, { title: "Alice's third post (published)", - text_content: + textContent: "This is Alice's third post. It's published, so this is data that all logged-in users are allowed to view.", - is_published: true, - user_id: 1, + isPublished: true, + userId: 1, }, { title: "Bob's first post (unpublished)", - text_content: + textContent: "This is Bob's first post. It's not published, so this is data only Bob should be able to view and edit.", - is_published: false, - user_id: 2, + isPublished: false, + userId: 2, }, { title: "Bob's second post (published)", - text_content: + textContent: "This is Bob's second post. It's published, so this is data that all logged-in users are allowed to view.", - is_published: true, - user_id: 2, + isPublished: true, + userId: 2, }, { - title: "Special Blogpost 2", - text_content: + title: 'Special Blogpost 2', + textContent: 'This is a special one ', - is_published: true, - user_id: 1, + isPublished: true, + userId: 1, }, { - title: "Special Blogpost", - text_content: + title: 'Special Blogpost', + textContent: 'This is another **special one** - markdown formatted', - is_published: true, - user_id: 1, + isPublished: true, + userId: 1, }, ]; @@ -63,15 +63,14 @@ export async function up(sql: Sql>) { ) `; - await sql` - INSERT INTO blog_posts ${sql( - blogPosts, - 'title', - 'text_content', - 'is_published', - 'user_id', - )} - `; + for (const blogPost of blogPosts) { + await sql` + INSERT INTO blog_posts + (title, text_content, is_published, user_id) + VALUES + (${blogPost.title}, ${blogPost.textContent}, ${blogPost.isPublished}, ${blogPost.userId}) + `; + } } export async function down(sql: Sql>) { diff --git a/package.json b/package.json index 8113fe2..4ee436c 100644 --- a/package.json +++ b/package.json @@ -29,41 +29,44 @@ "devDependencies": { "@babel/eslint-parser": "7.19.1", "@next/eslint-plugin-next": "12.3.1", + "@ts-safeql/eslint-plugin": "0.0.18", "@types/bcrypt": "5.0.0", "@types/dompurify": "2.3.4", - "@types/node": "18.11.3", + "@types/eslint": "8.4.6", + "@types/node": "18.8.5", "@types/react": "18.0.21", "@types/react-dom": "18.0.6", - "@typescript-eslint/eslint-plugin": "5.40.1", - "@typescript-eslint/parser": "5.40.1", + "@typescript-eslint/eslint-plugin": "5.40.0", + "@typescript-eslint/parser": "5.40.0", "@upleveled/eslint-config-upleveled": "3.0.1", "@upleveled/eslint-plugin-upleveled": "2.1.6", "eslint": "8.25.0", "eslint-config-next": "12.3.1", "eslint-config-react-app": "7.0.1", - "eslint-import-resolver-typescript": "3.5.2", + "eslint-import-resolver-typescript": "3.5.1", "eslint-plugin-cypress": "2.12.1", "eslint-plugin-flowtype": "8.0.3", "eslint-plugin-import": "2.26.0", - "eslint-plugin-jest": "27.1.3", + "eslint-plugin-jest": "27.1.1", "eslint-plugin-jsx-a11y": "6.6.1", "eslint-plugin-jsx-expressions": "1.3.1", "eslint-plugin-react": "7.31.10", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-security": "1.5.0", "eslint-plugin-sonarjs": "0.16.0", - "eslint-plugin-testing-library": "5.9.0", + "eslint-plugin-testing-library": "5.7.2", "eslint-plugin-unicorn": "44.0.2", + "libpg-query": "13.2.5", "typescript": "4.8.4" }, "resolutions": { - "@typescript-eslint/eslint-plugin": "5.40.1", - "@typescript-eslint/parser": "5.40.1", + "@typescript-eslint/eslint-plugin": "5.40.0", + "@typescript-eslint/parser": "5.40.0", "eslint-plugin-import": "2.26.0", - "eslint-plugin-jest": "27.1.3", + "eslint-plugin-jest": "27.1.1", "eslint-plugin-jsx-a11y": "6.6.1", "eslint-plugin-react": "7.31.10", "eslint-plugin-react-hooks": "4.6.0", - "@typescript-eslint/utils": "5.40.1" + "@typescript-eslint/utils": "5.40.0" } } diff --git a/yarn.lock b/yarn.lock index db79341..9ddd04a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1049,6 +1049,11 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@esbuild/linux-loong64@0.15.7": + version "0.15.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz#1ec4af4a16c554cbd402cc557ccdd874e3f7be53" + integrity sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw== + "@eslint/eslintrc@^1.3.3": version "1.3.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95" @@ -1064,6 +1069,11 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + "@humanwhocodes/config-array@^0.10.5": version "0.10.7" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc" @@ -1123,7 +1133,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@mapbox/node-pre-gyp@^1.0.10": +"@mapbox/node-pre-gyp@^1.0.10", "@mapbox/node-pre-gyp@^1.0.8": version "1.0.10" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== @@ -1243,6 +1253,22 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + "@pkgr/utils@^2.3.1": version "2.3.1" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03" @@ -1267,6 +1293,60 @@ dependencies: tslib "^2.4.0" +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@ts-safeql/eslint-plugin@0.0.18": + version "0.0.18" + resolved "https://registry.yarnpkg.com/@ts-safeql/eslint-plugin/-/eslint-plugin-0.0.18.tgz#21481945156d4876ba2eedb5e04a1a32f3ce7e0f" + integrity sha512-/S4RT4EhOh086bwjAvaF0AEyQ4ICAhm0njjCaTz8tRcUfpfdRDktlj2oWZr6UCfkW8OIRkaI35iBSgqRIxhxVw== + dependencies: + "@ts-safeql/generate" "0.0.6" + "@ts-safeql/shared" "0.0.5" + "@ts-safeql/test-utils" "0.0.5" + "@typescript-eslint/utils" "^5.36.2" + esbuild "0.15.7" + fp-ts "^2.12.3" + pg-connection-string "2.5.0" + postgres "^3.3.0" + recast "^0.21.2" + source-map-support "^0.5.21" + synckit "^0.8.4" + ts-pattern "^4.0.5" + zod "^3.19.0" + zod-to-json-schema "^3.17.1" + +"@ts-safeql/generate@0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@ts-safeql/generate/-/generate-0.0.6.tgz#c8ed41586be2c5cf1e82ff4d9a057ae8fd5ea927" + integrity sha512-vKuZKipxYbCOo1waRCNtIif7+47sdVa321aod+UbRDzhjZowtQ0cNtdFu32NlQFI3deiozT2dpZvZC37hb1iAA== + dependencies: + "@ts-safeql/shared" "0.0.5" + "@ts-safeql/test-utils" "0.0.5" + fp-ts "^2.12.3" + pg-connection-string "^2.5.0" + postgres "^3.3.0" + source-map-support "^0.5.21" + +"@ts-safeql/shared@0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@ts-safeql/shared/-/shared-0.0.5.tgz#c4b12fad80144a167b5154dbd75e0d5c3f4156fe" + integrity sha512-xsjqvn0HtNDk1U+yaCF3eDrXVcp8hkE/NI1CMPt+RAqffG1VwBSkfXKsGwjv9b/mbR4joDf081rhd7A1oHc4+A== + dependencies: + postgres "^3.3.0" + +"@ts-safeql/test-utils@0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@ts-safeql/test-utils/-/test-utils-0.0.5.tgz#4e7fcf39a745ed91d1a50392a6f5c86951f3fba0" + integrity sha512-O3f0xleJTdqMpiU0QSEQDx1TXDUqbB01lhfvJRk8lINhHu564WW/lSxp6Dkhm7LsiWEwOxsl3VaPKMAi1rrq8Q== + dependencies: + "@ts-safeql/shared" "0.0.5" + nanoid "^4.0.0" + pg-connection-string "^2.5.0" + postgres "^3.3.0" + "@types/bcrypt@5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.0.tgz#a835afa2882d165aff5690893db314eaa98b9f20" @@ -1300,6 +1380,19 @@ dependencies: dotenv "^8.2.0" +"@types/eslint@8.4.6": + version "8.4.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207" + integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -1307,7 +1400,7 @@ dependencies: "@types/unist" "*" -"@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -1334,10 +1427,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.2.tgz#ffc5f0f099d27887c8d9067b54e55090fcd54126" integrity sha512-KcfkBq9H4PI6Vpu5B/KoPeuVDAbmi+2mDBqGPGUgoL7yXQtcWGu2vJWmmRkneWK3Rh0nIAX192Aa87AqKHYChQ== -"@types/node@18.11.3": - version "18.11.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" - integrity sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A== +"@types/node@18.8.5": + version "18.8.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.5.tgz#6a31f820c1077c3f8ce44f9e203e68a176e8f59e" + integrity sha512-Bq7G3AErwe5A/Zki5fdD3O6+0zDChhg671NfPjtIcbtzDNZTv4NPKMRFr7gtYPG7y+B8uTiNK4Ngd9T0FTar6Q== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -1384,11 +1477,6 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== -"@types/semver@^7.3.12": - version "7.3.12" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" - integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== - "@types/trusted-types@*": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" @@ -1399,14 +1487,14 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@typescript-eslint/eslint-plugin@5.40.1", "@typescript-eslint/eslint-plugin@^5.5.0": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz#3203a6ff396b1194083faaa6e5110c401201d7d5" - integrity sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg== +"@typescript-eslint/eslint-plugin@5.40.0", "@typescript-eslint/eslint-plugin@^5.5.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz#0159bb71410eec563968288a17bd4478cdb685bd" + integrity sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q== dependencies: - "@typescript-eslint/scope-manager" "5.40.1" - "@typescript-eslint/type-utils" "5.40.1" - "@typescript-eslint/utils" "5.40.1" + "@typescript-eslint/scope-manager" "5.40.0" + "@typescript-eslint/type-utils" "5.40.0" + "@typescript-eslint/utils" "5.40.0" debug "^4.3.4" ignore "^5.2.0" regexpp "^3.2.0" @@ -1420,72 +1508,71 @@ dependencies: "@typescript-eslint/utils" "5.39.0" -"@typescript-eslint/parser@5.40.1", "@typescript-eslint/parser@^5.21.0", "@typescript-eslint/parser@^5.5.0": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.40.1.tgz#e7f8295dd8154d0d37d661ddd8e2f0ecfdee28dd" - integrity sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg== +"@typescript-eslint/parser@5.40.0", "@typescript-eslint/parser@^5.21.0", "@typescript-eslint/parser@^5.5.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.40.0.tgz#432bddc1fe9154945660f67c1ba6d44de5014840" + integrity sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw== dependencies: - "@typescript-eslint/scope-manager" "5.40.1" - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/typescript-estree" "5.40.1" + "@typescript-eslint/scope-manager" "5.40.0" + "@typescript-eslint/types" "5.40.0" + "@typescript-eslint/typescript-estree" "5.40.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz#a7a5197dfd234622a2421ea590ee0ccc02e18dfe" - integrity sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg== +"@typescript-eslint/scope-manager@5.40.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz#d6ea782c8e3a2371ba3ea31458dcbdc934668fc4" + integrity sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw== dependencies: - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/visitor-keys" "5.40.1" + "@typescript-eslint/types" "5.40.0" + "@typescript-eslint/visitor-keys" "5.40.0" -"@typescript-eslint/type-utils@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz#091e4ce3bebbdb68f4980bae9dee2e4e1725f601" - integrity sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q== +"@typescript-eslint/type-utils@5.40.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz#4964099d0158355e72d67a370249d7fc03331126" + integrity sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw== dependencies: - "@typescript-eslint/typescript-estree" "5.40.1" - "@typescript-eslint/utils" "5.40.1" + "@typescript-eslint/typescript-estree" "5.40.0" + "@typescript-eslint/utils" "5.40.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.1.tgz#de37f4f64de731ee454bb2085d71030aa832f749" - integrity sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw== +"@typescript-eslint/types@5.40.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.0.tgz#8de07e118a10b8f63c99e174a3860f75608c822e" + integrity sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw== -"@typescript-eslint/typescript-estree@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz#9a7d25492f02c69882ce5e0cd1857b0c55645d72" - integrity sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA== +"@typescript-eslint/typescript-estree@5.40.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz#e305e6a5d65226efa5471ee0f12e0ffaab6d3075" + integrity sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg== dependencies: - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/visitor-keys" "5.40.1" + "@typescript-eslint/types" "5.40.0" + "@typescript-eslint/visitor-keys" "5.40.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.39.0", "@typescript-eslint/utils@5.40.1", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.13.0": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.40.1.tgz#3204fb73a559d3b7bab7dc9d3c44487c2734a9ca" - integrity sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw== +"@typescript-eslint/utils@5.39.0", "@typescript-eslint/utils@5.40.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.13.0", "@typescript-eslint/utils@^5.36.2": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.40.0.tgz#647f56a875fd09d33c6abd70913c3dd50759b772" + integrity sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA== dependencies: "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.40.1" - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/typescript-estree" "5.40.1" + "@typescript-eslint/scope-manager" "5.40.0" + "@typescript-eslint/types" "5.40.0" + "@typescript-eslint/typescript-estree" "5.40.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz#f3d2bf5af192f4432b84cec6fdcb387193518754" - integrity sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw== +"@typescript-eslint/visitor-keys@5.40.0": + version "5.40.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz#dd2d38097f68e0d2e1e06cb9f73c0173aca54b68" + integrity sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ== dependencies: - "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/types" "5.40.0" eslint-visitor-keys "^3.3.0" "@upleveled/eslint-config-upleveled@3.0.1": @@ -1513,13 +1600,30 @@ acorn@^8.8.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== -agent-base@6: +agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" +agentkeepalive@^4.1.3: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" + integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== + dependencies: + debug "^4.1.0" + depd "^1.1.2" + humanize-ms "^1.2.1" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1562,6 +1666,14 @@ are-we-there-yet@^2.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1616,6 +1728,13 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +ast-types@0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d" + integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== + dependencies: + tslib "^2.0.1" + axe-core@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f" @@ -1750,6 +1869,11 @@ browserslist@^4.20.2, browserslist@^4.21.2: node-releases "^2.0.6" update-browserslist-db "^1.0.5" +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -1763,6 +1887,30 @@ builtin-modules@^3.3.0: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== +cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1830,6 +1978,11 @@ clean-regexp@^1.0.0: dependencies: escape-string-regexp "^1.0.5" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1862,7 +2015,7 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.2: +color-support@^1.1.2, color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== @@ -1950,7 +2103,7 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2013,6 +2166,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== +depd@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + dequal@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -2101,6 +2259,13 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encoding@^0.1.12: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -2116,6 +2281,16 @@ enhanced-resolve@^5.10.0: graceful-fs "^4.2.4" tapable "^2.2.0" +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -2173,101 +2348,228 @@ esbuild-android-64@0.14.51: resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz#414a087cb0de8db1e347ecca6c8320513de433db" integrity sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ== +esbuild-android-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz#a521604d8c4c6befc7affedc897df8ccde189bea" + integrity sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w== + esbuild-android-arm64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz#55de3bce2aab72bcd2b606da4318ad00fb9c8151" integrity sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A== +esbuild-android-arm64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz#307b81f1088bf1e81dfe5f3d1d63a2d2a2e3e68e" + integrity sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ== + esbuild-darwin-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz#4259f23ed6b4cea2ec8a28d87b7fb9801f093754" integrity sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA== +esbuild-darwin-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz#270117b0c4ec6bcbc5cf3a297a7d11954f007e11" + integrity sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg== + esbuild-darwin-arm64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz#d77b4366a71d84e530ba019d540b538b295d494a" integrity sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow== +esbuild-darwin-arm64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz#97851eacd11dacb7719713602e3319e16202fc77" + integrity sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ== + esbuild-freebsd-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz#27b6587b3639f10519c65e07219d249b01f2ad38" integrity sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g== +esbuild-freebsd-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz#1de15ffaf5ae916aa925800aa6d02579960dd8c4" + integrity sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ== + esbuild-freebsd-arm64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz#63c435917e566808c71fafddc600aca4d78be1ec" integrity sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg== +esbuild-freebsd-arm64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz#0f160dbf5c9a31a1d8dd87acbbcb1a04b7031594" + integrity sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q== + esbuild-linux-32@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz#c3da774143a37e7f11559b9369d98f11f997a5d9" integrity sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w== +esbuild-linux-32@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz#422eb853370a5e40bdce8b39525380de11ccadec" + integrity sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg== + esbuild-linux-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz#5d92b67f674e02ae0b4a9de9a757ba482115c4ae" integrity sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA== +esbuild-linux-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz#f89c468453bb3194b14f19dc32e0b99612e81d2b" + integrity sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ== + esbuild-linux-arm64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz#dac84740516e859d8b14e1ecc478dd5241b10c93" integrity sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw== +esbuild-linux-arm64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz#68a79d6eb5e032efb9168a0f340ccfd33d6350a1" + integrity sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw== + esbuild-linux-arm@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz#b3ae7000696cd53ed95b2b458554ff543a60e106" integrity sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg== +esbuild-linux-arm@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz#2b7c784d0b3339878013dfa82bf5eaf82c7ce7d3" + integrity sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ== + esbuild-linux-mips64le@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz#dad10770fac94efa092b5a0643821c955a9dd385" integrity sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A== +esbuild-linux-mips64le@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz#bb8330a50b14aa84673816cb63cc6c8b9beb62cc" + integrity sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw== + esbuild-linux-ppc64le@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz#b68c2f8294d012a16a88073d67e976edd4850ae0" integrity sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ== +esbuild-linux-ppc64le@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz#52544e7fa992811eb996674090d0bc41f067a14b" + integrity sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw== + esbuild-linux-riscv64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz#608a318b8697123e44c1e185cdf6708e3df50b93" integrity sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA== +esbuild-linux-riscv64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz#a43ae60697992b957e454cbb622f7ee5297e8159" + integrity sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g== + esbuild-linux-s390x@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz#c9e7791170a3295dba79b93aa452beb9838a8625" integrity sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw== +esbuild-linux-s390x@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz#8c76a125dd10a84c166294d77416caaf5e1c7b64" + integrity sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ== + esbuild-netbsd-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz#0abd40b8c2e37fda6f5cc41a04cb2b690823d891" integrity sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A== +esbuild-netbsd-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz#19b2e75449d7d9c32b5d8a222bac2f1e0c3b08fd" + integrity sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ== + esbuild-openbsd-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz#4adba0b7ea7eb1428bb00d8e94c199a949b130e8" integrity sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA== +esbuild-openbsd-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz#1357b2bf72fd037d9150e751420a1fe4c8618ad7" + integrity sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ== + esbuild-sunos-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz#4b8a6d97dfedda30a6e39607393c5c90ebf63891" integrity sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA== +esbuild-sunos-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz#87ab2c604592a9c3c763e72969da0d72bcde91d2" + integrity sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag== + esbuild-windows-32@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz#d31d8ca0c1d314fb1edea163685a423b62e9ac17" integrity sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg== +esbuild-windows-32@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz#c81e688c0457665a8d463a669e5bf60870323e99" + integrity sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA== + esbuild-windows-64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz#7d3c09c8652d222925625637bdc7e6c223e0085d" integrity sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA== +esbuild-windows-64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz#2421d1ae34b0561a9d6767346b381961266c4eff" + integrity sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q== + esbuild-windows-arm64@0.14.51: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz#0220d2304bfdc11bc27e19b2aaf56edf183e4ae9" integrity sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g== +esbuild-windows-arm64@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz#7d5e9e060a7b454cb2f57f84a3f3c23c8f30b7d2" + integrity sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw== + +esbuild@0.15.7: + version "0.15.7" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.7.tgz#8a1f1aff58671a3199dd24df95314122fc1ddee8" + integrity sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw== + optionalDependencies: + "@esbuild/linux-loong64" "0.15.7" + esbuild-android-64 "0.15.7" + esbuild-android-arm64 "0.15.7" + esbuild-darwin-64 "0.15.7" + esbuild-darwin-arm64 "0.15.7" + esbuild-freebsd-64 "0.15.7" + esbuild-freebsd-arm64 "0.15.7" + esbuild-linux-32 "0.15.7" + esbuild-linux-64 "0.15.7" + esbuild-linux-arm "0.15.7" + esbuild-linux-arm64 "0.15.7" + esbuild-linux-mips64le "0.15.7" + esbuild-linux-ppc64le "0.15.7" + esbuild-linux-riscv64 "0.15.7" + esbuild-linux-s390x "0.15.7" + esbuild-netbsd-64 "0.15.7" + esbuild-openbsd-64 "0.15.7" + esbuild-sunos-64 "0.15.7" + esbuild-windows-32 "0.15.7" + esbuild-windows-64 "0.15.7" + esbuild-windows-arm64 "0.15.7" + esbuild@^0.14.0: version "0.14.51" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.51.tgz#1c8ecbc8db3710da03776211dc3ee3448f7aa51e" @@ -2352,10 +2654,10 @@ eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" -eslint-import-resolver-typescript@3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.2.tgz#9431acded7d898fd94591a08ea9eec3514c7de91" - integrity sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ== +eslint-import-resolver-typescript@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.1.tgz#c72634da072eebd04fe73007fa58a62c333c8147" + integrity sha512-U7LUjNJPYjNsHvAUAkt/RU3fcTSpbllA0//35B4eLYTX74frmOepbt7F7J3D1IGtj9k21buOpaqtDd4ZlS/BYQ== dependencies: debug "^4.3.4" enhanced-resolve "^5.10.0" @@ -2363,7 +2665,7 @@ eslint-import-resolver-typescript@3.5.2: globby "^13.1.2" is-core-module "^2.10.0" is-glob "^4.0.3" - synckit "^0.8.4" + synckit "^0.8.3" eslint-import-resolver-typescript@^2.7.1: version "2.7.1" @@ -2418,10 +2720,10 @@ eslint-plugin-import@2.26.0, eslint-plugin-import@^2.25.3, eslint-plugin-import@ resolve "^1.22.0" tsconfig-paths "^3.14.1" -eslint-plugin-jest@27.1.3, eslint-plugin-jest@^25.3.0: - version "27.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.3.tgz#9f359eeac0c720a825f658e7e261a9eef869dc8d" - integrity sha512-7DrIfYRQPa7JQd1Le8G/BJsfYHVUKQdJQ/6vULSp/4NjKZmSMJ/605G2hhScEra++SiH68zPEjLnrO74nHrMLg== +eslint-plugin-jest@27.1.1, eslint-plugin-jest@^25.3.0: + version "27.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.1.tgz#60f68dee15d4ffd9cdff65158d7fa46a65dbaaf5" + integrity sha512-vuSuXGKHHi/UAffIM46QKm4g0tQP+6n52nRxUpMq6x6x9rhnv5WM7ktSu3h9cTnXE4b0Y0ODQTgRlCm9rdRLvg== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -2489,10 +2791,10 @@ eslint-plugin-sonarjs@0.16.0: resolved "https://registry.yarnpkg.com/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.16.0.tgz#227651fea8a7c82b40156a1d70d52d64ea058dba" integrity sha512-al8ojAzcQW8Eu0tWn841ldhPpPcjrJ59TzzTfAVWR45bWvdAASCmrGl8vK0MWHyKVDdC0i17IGbtQQ1KgxLlVA== -eslint-plugin-testing-library@5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.9.0.tgz#772243d6848c9ac1a22ca4f742a1fe5fd378a052" - integrity sha512-iwPz6KNf/qc4rHMGaxn2vmS5snzuOqtia00D0FC2Wcp1xWM3J9w0/YzzrPv/UFHhLG0CwfQodyKmqL5+c6hGgg== +eslint-plugin-testing-library@5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.7.2.tgz#c1b2112a40aab61f93e10859e8b2d81e54f0ce84" + integrity sha512-0ZmHeR/DUUgEzW8rwUBRWxuqntipDtpvxK0hymdHnLlABryJkzd+CAHr+XnISaVsTisZ5MLHp6nQF+8COHLLTA== dependencies: "@typescript-eslint/utils" "^5.13.0" @@ -2609,6 +2911,11 @@ espree@^9.4.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -2731,6 +3038,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== +fp-ts@^2.12.3: + version "2.13.1" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.13.1.tgz#1bf2b24136cca154846af16752dc29e8fa506f2a" + integrity sha512-0eu5ULPS2c/jsa1lGFneEFFEdTbembJv8e4QKXeVJ3lm/5hyve06dlKZrpxmMwJt6rYen7sxmHHK2CLaXvWuWQ== + fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -2783,6 +3095,20 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -2841,7 +3167,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.2.0: +glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -2898,7 +3224,7 @@ globrex@^0.1.2: resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== -graceful-fs@^4.2.4: +graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -2964,6 +3290,20 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +http-cache-semantics@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -2972,6 +3312,20 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -3000,6 +3354,11 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3032,6 +3391,11 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3117,6 +3481,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: dependencies: is-extglob "^2.1.1" +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -3284,6 +3653,15 @@ ley@0.8.1: sade "^1.7.0" totalist "^2.0.0" +libpg-query@13.2.5: + version "13.2.5" + resolved "https://registry.yarnpkg.com/libpg-query/-/libpg-query-13.2.5.tgz#f3d93f21b64caa904e67bbad767b7f039b951c87" + integrity sha512-Y0IHcZyxbX4WHwWNa5KFDufYSiVIb+uPyZQDdom1ODxCfqko/ubLj+rzHeSDeaRRsEzgKc22x/jBRka7BMT2vQ== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.8" + node-addon-api "^1.6.3" + node-gyp "^8.0.0" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -3347,6 +3725,28 @@ make-dir@^3.1.0: dependencies: semver "^6.0.0" +make-fetch-happen@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + mdast-util-definitions@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" @@ -3624,14 +4024,53 @@ minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== -minipass@^3.0.0: +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-fetch@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== + dependencies: + minipass "^3.1.0" + minipass-sized "^1.0.3" + minizlib "^2.0.0" + optionalDependencies: + encoding "^0.1.12" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: version "3.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== dependencies: yallist "^4.0.0" -minizlib@^2.1.1: +minizlib@^2.0.0, minizlib@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -3649,7 +4088,7 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^1.0.3: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -3669,7 +4108,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -3679,6 +4118,11 @@ nanoid@^3.3.4: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.0.tgz#6e144dee117609232c3f415c34b0e550e64999a5" + integrity sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg== + napi-build-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" @@ -3689,6 +4133,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + next@12.3.1: version "12.3.1" resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1" @@ -3722,6 +4171,11 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" +node-addon-api@^1.6.3: + version "1.7.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + node-addon-api@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501" @@ -3734,6 +4188,22 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-gyp@^8.0.0: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + node-releases@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -3766,6 +4236,16 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" +npmlog@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -3896,6 +4376,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -3953,6 +4440,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pg-connection-string@2.5.0, pg-connection-string@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" + integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -3977,7 +4469,7 @@ postcss@8.4.14: picocolors "^1.0.0" source-map-js "^1.0.2" -postgres@3.3.1: +postgres@3.3.1, postgres@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postgres/-/postgres-3.3.1.tgz#1d9b5e8f01ee325df13b6db14f38ae2b8f6fe912" integrity sha512-ak/xXToZYwRvQlZIUtLgPUIggz62eIIbPTgxl/Yl4oTu0TgNOd1CrzTCifsvZ89jBwLvnX6+Ky5frp5HzIBoaw== @@ -4005,6 +4497,19 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + prop-types@^15.0.0, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -4121,6 +4626,16 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +recast@^0.21.2: + version "0.21.5" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495" + integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== + dependencies: + ast-types "0.15.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" @@ -4230,6 +4745,11 @@ resolve@^2.0.0-next.3: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -4273,6 +4793,11 @@ safe-regex@^2.1.1: dependencies: regexp-tree "~0.1.1" +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -4342,7 +4867,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -4378,11 +4903,46 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== + dependencies: + agent-base "^6.0.2" + debug "^4.3.3" + socks "^2.6.2" + +socks@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + space-separated-tokens@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" @@ -4414,6 +4974,13 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== +ssri@^8.0.0, ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + string-natural-compare@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" @@ -4527,7 +5094,7 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.8.4: +synckit@^0.8.3, synckit@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.4.tgz#0e6b392b73fafdafcde56692e3352500261d64ec" integrity sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw== @@ -4561,7 +5128,7 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^6.1.11: +tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -4618,6 +5185,11 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== +ts-pattern@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/ts-pattern/-/ts-pattern-4.0.5.tgz#8e87db265b890ddb0dfc10deda36568296ebd5c3" + integrity sha512-Bq44KCEt7JVaNLa148mBCJkcQf4l7jtLEBDuDdeuLynWDA+1a60P4D0rMkqSM9mOKLQbIWUddE9h3XKyKwBeqA== + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -4633,7 +5205,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.4.0: +tslib@^2.0.1, tslib@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -4732,6 +5304,20 @@ unified@^10.0.0: trough "^2.0.0" vfile "^5.0.0" +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + unist-builder@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" @@ -4865,14 +5451,14 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which@^2.0.1: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.2: +wide-align@^1.1.2, wide-align@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== @@ -4903,3 +5489,13 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod-to-json-schema@^3.17.1: + version "3.18.1" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.18.1.tgz#ba6aa9ca4a53c0ed18ad6c0d4f85b957d9500c11" + integrity sha512-YFP4dAZR2GHDkTOZL7E7p2E3/yoUZeB5RD797JEpJTyh/L+9WvIK/tEMuF+MhzDPhQWXlkSugxmO8nbdXjJKYA== + +zod@^3.19.0: + version "3.19.1" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.19.1.tgz#112f074a97b50bfc4772d4ad1576814bd8ac4473" + integrity sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA== From 2cd00ff811a8271caf49267d45595e2cc523cbd0 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 17:06:46 +0200 Subject: [PATCH 13/24] Make blog_posts.user_id NOT NULL --- database/blogPosts.ts | 2 +- migrations/003-create-table-blog-posts.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/blogPosts.ts b/database/blogPosts.ts index 61dbe51..cf6e354 100644 --- a/database/blogPosts.ts +++ b/database/blogPosts.ts @@ -5,7 +5,7 @@ export type BlogPost = { title: string; textContent: string; isPublished: boolean; - userId: number | null; + userId: number; }; export async function getBlogPosts() { diff --git a/migrations/003-create-table-blog-posts.ts b/migrations/003-create-table-blog-posts.ts index f99ce34..c3b72c5 100644 --- a/migrations/003-create-table-blog-posts.ts +++ b/migrations/003-create-table-blog-posts.ts @@ -59,7 +59,7 @@ export async function up(sql: Sql>) { title varchar(100) NOT NULL, text_content varchar(2000) NOT NULL, is_published boolean NOT NULL DEFAULT false, - user_id integer REFERENCES users (id) ON DELETE CASCADE + user_id integer NOT NULL REFERENCES users (id) ON DELETE CASCADE ) `; From 24971a9ec848ea3a8b4b748ab7b5163240485748 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 17:26:22 +0200 Subject: [PATCH 14/24] Improve clarity of naming, prose and types --- database/blogPosts.ts | 24 +++++++-------- pages/example-6-xss/common.tsx | 10 +++--- pages/example-6-xss/solution-1.tsx | 41 ++++++++++++++++--------- pages/example-6-xss/solution-2.tsx | 49 ++++++++++++++++++------------ pages/example-6-xss/solution-3.tsx | 49 ++++++++++++++++++------------ pages/example-6-xss/vulnerable.tsx | 45 ++++++++++++++++++--------- 6 files changed, 132 insertions(+), 86 deletions(-) diff --git a/database/blogPosts.ts b/database/blogPosts.ts index cf6e354..3af6f89 100644 --- a/database/blogPosts.ts +++ b/database/blogPosts.ts @@ -15,6 +15,18 @@ export async function getBlogPosts() { return blogPosts; } +export async function getBlogPostById(id: number) { + const [blogPost] = await sql` + SELECT + * + FROM + blog_posts + WHERE + id = ${id} + `; + return blogPost; +} + export async function getPublishedBlogPosts() { const blogPosts = await sql` SELECT @@ -107,15 +119,3 @@ export async function getBlogPostsBySessionToken(sessionToken: string) { `; return blogPosts; } - -export async function getSpecialBlogPosts(id: number) { - const blogPosts = await sql` - SELECT - * - FROM - blog_posts - WHERE - id = ${id} - `; - return blogPosts; -} diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-xss/common.tsx index 2397e88..feedb2f 100644 --- a/pages/example-6-xss/common.tsx +++ b/pages/example-6-xss/common.tsx @@ -6,7 +6,7 @@ type Props = error: string; } | { - blogPosts: BlogPost[]; + blogPost: BlogPost; }; export function CommonContent(props: Props) { @@ -40,13 +40,11 @@ export function CommonContent(props: Props) {
    - The following blog posts should only be visible for logged-in users. -
    -
    - If a user is not logged in, an error message should appear. + The following blog post should not cause any arbitrary JavaScript to + run.
    -

    Blog Posts

    +

    Blog Post

    {'error' in props &&
    {props.error}
    } diff --git a/pages/example-6-xss/solution-1.tsx b/pages/example-6-xss/solution-1.tsx index 8ed8040..6aefefe 100644 --- a/pages/example-6-xss/solution-1.tsx +++ b/pages/example-6-xss/solution-1.tsx @@ -1,4 +1,5 @@ -import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; +import { BlogPost, getBlogPostById } from '../../database/blogPosts'; import { CommonContent } from './common'; type Props = @@ -6,7 +7,7 @@ type Props = error: string; } | { - blogPosts: BlogPost[]; + blogPost: BlogPost; }; export default function MissingAuthenticationGssp(props: Props) { @@ -14,25 +15,35 @@ export default function MissingAuthenticationGssp(props: Props) {
    - {'blogPosts' in props && - props.blogPosts.map((blogPost) => { - return ( -
    -

    {blogPost.title}

    -
    Published: {String(blogPost.isPublished)}
    -
    {blogPost.textContent}
    -
    - ); - })} + {'blogPost' in props && ( + <> +

    {props.blogPost.title}

    +
    Published: {String(props.blogPost.isPublished)}
    + +
    {props.blogPost.textContent}
    + + )}
    ); } -export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(6); +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { + const blogPost = await getBlogPostById(6); + + if (!blogPost) { + context.res.statusCode = 404; + return { + props: { + error: 'Blog post not found', + }, + }; + } + return { props: { - blogPosts: blogPosts, + blogPost: blogPost, }, }; } diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-xss/solution-2.tsx index e26d3d0..b4d3f25 100644 --- a/pages/example-6-xss/solution-2.tsx +++ b/pages/example-6-xss/solution-2.tsx @@ -1,5 +1,6 @@ import DOMPurify from 'dompurify'; -import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; +import { BlogPost, getBlogPostById } from '../../database/blogPosts'; import { CommonContent } from './common'; type Props = @@ -7,7 +8,7 @@ type Props = error: string; } | { - blogPosts: BlogPost[]; + blogPost: BlogPost; }; export default function MissingAuthenticationGssp(props: Props) { @@ -15,29 +16,39 @@ export default function MissingAuthenticationGssp(props: Props) {
    - {'blogPosts' in props && - props.blogPosts.map((blogPost) => { - return ( -
    -

    {blogPost.title}

    -
    Published: {String(blogPost.isPublished)}
    -
    -
    - ); - })} + {'blogPost' in props && ( + <> +

    {props.blogPost.title}

    +
    Published: {String(props.blogPost.isPublished)}
    + +
    + + )}
    ); } -export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(6); +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { + const blogPost = await getBlogPostById(6); + + if (!blogPost) { + context.res.statusCode = 404; + return { + props: { + error: 'Blog post not found', + }, + }; + } + return { props: { - blogPosts: blogPosts, + blogPost: blogPost, }, }; } diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-xss/solution-3.tsx index 5d98c81..6bfd056 100644 --- a/pages/example-6-xss/solution-3.tsx +++ b/pages/example-6-xss/solution-3.tsx @@ -1,5 +1,6 @@ +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import ReactMarkdown from 'react-markdown'; -import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { BlogPost, getBlogPostById } from '../../database/blogPosts'; import { CommonContent } from './common'; type Props = @@ -7,37 +8,47 @@ type Props = error: string; } | { - blogPosts: BlogPost[]; + blogPost: BlogPost; }; export default function MissingAuthenticationGssp(props: Props) { return (
    + {'blogPost' in props && ( + <> +

    {props.blogPost.title}

    +
    Published: {String(props.blogPost.isPublished)}
    - {'blogPosts' in props && - props.blogPosts.map((blogPost) => { - // be careful which markdown library you use and how you use it - // by default the markdown standard supports html tags too - // so never assign markdown directly to innerHTML - // but the default usage of "ReactMarkdown" is safe - return ( -
    -

    {blogPost.title}

    -
    Published: {String(blogPost.isPublished)}
    - -
    - ); - })} + {/* be careful which markdown library you use and how you use it + by default the markdown standard supports html tags too + so never assign markdown directly to innerHTML + but the default usage of "ReactMarkdown" is safe */} + + + )}
    ); } -export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(7); +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { + // Different blog post text_content including Markdown + const blogPost = await getBlogPostById(7); + + if (!blogPost) { + context.res.statusCode = 404; + return { + props: { + error: 'Blog post not found', + }, + }; + } + return { props: { - blogPosts: blogPosts, + blogPost: blogPost, }, }; } diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-xss/vulnerable.tsx index 41e7ba4..950dbbf 100644 --- a/pages/example-6-xss/vulnerable.tsx +++ b/pages/example-6-xss/vulnerable.tsx @@ -1,4 +1,5 @@ -import { BlogPost, getSpecialBlogPosts } from '../../database/blogPosts'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; +import { BlogPost, getBlogPostById } from '../../database/blogPosts'; import { CommonContent } from './common'; type Props = @@ -6,7 +7,7 @@ type Props = error: string; } | { - blogPosts: BlogPost[]; + blogPost: BlogPost; }; export default function MissingAuthenticationGssp(props: Props) { @@ -14,25 +15,39 @@ export default function MissingAuthenticationGssp(props: Props) {
    - {'blogPosts' in props && - props.blogPosts.map((blogPost) => { - return ( -
    -

    {blogPost.title} - Vulnerable

    -
    Published: {String(blogPost.isPublished)}
    -
    -
    - ); - })} + {'blogPost' in props && ( + <> +

    {props.blogPost.title} - Vulnerable

    +
    Published: {String(props.blogPost.isPublished)}
    + +
    + + )}
    ); } -export async function getServerSideProps() { - const blogPosts = await getSpecialBlogPosts(6); +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { + const blogPost = await getBlogPostById(6); + + if (!blogPost) { + context.res.statusCode = 404; + return { + props: { + error: 'Blog post not found', + }, + }; + } + return { props: { - blogPosts: blogPosts, + blogPost: blogPost, }, }; } From 4a3f632ee332d51dc792508e162ee3a7810db0b7 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 17:27:41 +0200 Subject: [PATCH 15/24] Use tsconfig from UpLeveled ESLint config --- tsconfig.json | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 2c35996..1de6b9d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,41 +1,4 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "display": "UpLeveled Node + React TSConfig", - "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "module": "esnext", - "target": "es2015", - "moduleResolution": "node", - "resolveJsonModule": true, - "esModuleInterop": true, - "isolatedModules": true, - "allowJs": true, - "allowSyntheticDefaultImports": true, - "downlevelIteration": true, - "forceConsistentCasingInFileNames": true, - "jsx": "preserve", - "noEmit": true, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - "strict": true, - "incremental": true - }, - "include": [ - "**/.eslintrc.cjs", - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - "**/*.js", - "**/*.jsx", - "**/*.cjs", - "**/*.mjs" - ], - "exclude": [ - "node_modules", - "build" - ] + "extends": "@upleveled/eslint-config-upleveled/tsconfig.base.json" } From f5fea9d2fafb8170c9d419aa43785ddb0090176e Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 18:05:08 +0200 Subject: [PATCH 16/24] Add jsx: preserve to tsconfig.json for Next.js --- tsconfig.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 1de6b9d..c261154 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,7 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@upleveled/eslint-config-upleveled/tsconfig.base.json" + "extends": "@upleveled/eslint-config-upleveled/tsconfig.base.json", + "compilerOptions": { + "jsx": "preserve" + } } From da3dbe4650b34f61f283b935520e29f90a77f3de Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 18:07:45 +0200 Subject: [PATCH 17/24] Make blog post title and content more descriptive --- migrations/003-create-table-blog-posts.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migrations/003-create-table-blog-posts.ts b/migrations/003-create-table-blog-posts.ts index c3b72c5..bc5aff7 100644 --- a/migrations/003-create-table-blog-posts.ts +++ b/migrations/003-create-table-blog-posts.ts @@ -37,16 +37,16 @@ const blogPosts = [ userId: 2, }, { - title: 'Special Blogpost 2', + title: "Bob's HTML post (published)", textContent: - 'This is a special one ', + 'This is Bob\'s blog post using HTML and an image: ', isPublished: true, userId: 1, }, { - title: 'Special Blogpost', + title: "Bob's Markdown post (published)", textContent: - 'This is another **special one** - markdown formatted', + 'This is Bob\'s blog post using **Markdown** and an image in HTML: ', isPublished: true, userId: 1, }, From 87e7fcf9bcc0f63a263c5d9cd4988be11b085af3 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 18:50:50 +0200 Subject: [PATCH 18/24] Add new screenshot and figcaptions to readme --- 6-cross-site-scripting.png | Bin 0 -> 35228 bytes readme.md | 30 ++++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 6-cross-site-scripting.png diff --git a/6-cross-site-scripting.png b/6-cross-site-scripting.png new file mode 100644 index 0000000000000000000000000000000000000000..7de07864107bdf4e1f43d9dccbc0ec2e841f88a2 GIT binary patch literal 35228 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 Q{wgC4lJ#lApZIg&e{AKwaR2}S literal 0 HcmV?d00001 diff --git a/readme.md b/readme.md index 560ed96..65c507f 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,34 @@ # Examples of Broken Security with Next.js + Postgres.js -Examples of common security mistakes causing broken authentication, broken authorization, secrets exposure, etc. +Examples of common security mistakes causing broken authentication, broken authorization, secrets exposure, cross-site scripting and more. -

    +
    + +
    Screenshot of the missing authentication example, where blog post content is incorrectly being shown to a user who is not logged in (all blog post content should be only visible to logged-in users)
    +
    -

    +

    -

    +
    + +
    Screenshot of the missing authorization example, where unpublished, private blog post content is incorrectly being exposed in the HTML to a user who is not the owner
    +
    + +

    + +
    + +
    Screenshot of the secrets exposure example, showing an API key being exposed
    +
    + +

    + +
    + +
    Screenshot of cross-site scripting example, showing an alert() triggered from an image with a broken src and an onerror attribute
    +
    + +

    ## Database Setup From 7b9d1e698830b237728e36bd3ee4cb273bd919d0 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 18:51:53 +0200 Subject: [PATCH 19/24] Fix paths and naming --- pages/_app.tsx | 4 ++-- .../solution-2.ts | 0 .../common.tsx | 18 +++++++----------- .../solution-1.tsx | 0 .../solution-2.tsx | 4 +++- .../vulnerable.tsx | 0 pages/index.tsx | 2 +- 7 files changed, 13 insertions(+), 15 deletions(-) rename pages/api/{example-5-secret-exposure => example-5-secrets-exposure}/solution-2.ts (100%) rename pages/{example-5-secrets-exposure-gssp => example-5-secrets-exposure}/common.tsx (64%) rename pages/{example-5-secrets-exposure-gssp => example-5-secrets-exposure}/solution-1.tsx (100%) rename pages/{example-5-secrets-exposure-gssp => example-5-secrets-exposure}/solution-2.tsx (87%) rename pages/{example-5-secrets-exposure-gssp => example-5-secrets-exposure}/vulnerable.tsx (100%) diff --git a/pages/_app.tsx b/pages/_app.tsx index b9fcc5a..8de162d 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -56,8 +56,8 @@ export default function App({ Component, pageProps }: AppProps) { Example 4 Example 5 diff --git a/pages/api/example-5-secret-exposure/solution-2.ts b/pages/api/example-5-secrets-exposure/solution-2.ts similarity index 100% rename from pages/api/example-5-secret-exposure/solution-2.ts rename to pages/api/example-5-secrets-exposure/solution-2.ts diff --git a/pages/example-5-secrets-exposure-gssp/common.tsx b/pages/example-5-secrets-exposure/common.tsx similarity index 64% rename from pages/example-5-secrets-exposure-gssp/common.tsx rename to pages/example-5-secrets-exposure/common.tsx index 0819f37..12276aa 100644 --- a/pages/example-5-secrets-exposure-gssp/common.tsx +++ b/pages/example-5-secrets-exposure/common.tsx @@ -10,29 +10,25 @@ type Props = { export default function Common(props: Props) { return (
    -

    Secrets Exposure - getServerSideProps

    +

    Secrets Exposure

    • - + Vulnerable - {' '} - - API code:{' '} - pages/api/example-5-secrets-exposure-gssp/vulnerable.ts +
    • - + Solution 1 - {' '} - - API code:{' '} - pages/api/example-5-secrets-exposure-gssp/solution-1.ts +
    • - + Solution 2 {' '} - API code:{' '} - pages/api/example-5-secrets-exposure-gssp/solution-2.ts + pages/api/example-5-secrets-exposure/solution-2.ts
    diff --git a/pages/example-5-secrets-exposure-gssp/solution-1.tsx b/pages/example-5-secrets-exposure/solution-1.tsx similarity index 100% rename from pages/example-5-secrets-exposure-gssp/solution-1.tsx rename to pages/example-5-secrets-exposure/solution-1.tsx diff --git a/pages/example-5-secrets-exposure-gssp/solution-2.tsx b/pages/example-5-secrets-exposure/solution-2.tsx similarity index 87% rename from pages/example-5-secrets-exposure-gssp/solution-2.tsx rename to pages/example-5-secrets-exposure/solution-2.tsx index 11f8720..87127ee 100644 --- a/pages/example-5-secrets-exposure-gssp/solution-2.tsx +++ b/pages/example-5-secrets-exposure/solution-2.tsx @@ -11,7 +11,9 @@ export default function SecretsExposureGssp(props: Props) { useEffect(() => { const fetchData = async () => { - const response = await fetch('/api/example-5-secret-exposure/solution-2'); + const response = await fetch( + '/api/example-5-secrets-exposure/solution-2', + ); const data = await response.json(); diff --git a/pages/example-5-secrets-exposure-gssp/vulnerable.tsx b/pages/example-5-secrets-exposure/vulnerable.tsx similarity index 100% rename from pages/example-5-secrets-exposure-gssp/vulnerable.tsx rename to pages/example-5-secrets-exposure/vulnerable.tsx diff --git a/pages/index.tsx b/pages/index.tsx index b3542d6..db18fff 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -25,7 +25,7 @@ export default function Home() {
  • - + Example 5: Data Exposure
  • From 758e29851e025c92bf24d2ae4fda59c8aba5f36f Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Tue, 25 Oct 2022 18:54:47 +0200 Subject: [PATCH 20/24] Fix naming and paths for Cross-Site Scripting --- pages/_app.tsx | 4 ++-- .../common.tsx | 10 +++++----- .../solution-1.tsx | 0 .../solution-2.tsx | 0 .../solution-3.tsx | 0 .../vulnerable.tsx | 0 pages/index.tsx | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) rename pages/{example-6-xss => example-6-cross-site-scripting}/common.tsx (72%) rename pages/{example-6-xss => example-6-cross-site-scripting}/solution-1.tsx (100%) rename pages/{example-6-xss => example-6-cross-site-scripting}/solution-2.tsx (100%) rename pages/{example-6-xss => example-6-cross-site-scripting}/solution-3.tsx (100%) rename pages/{example-6-xss => example-6-cross-site-scripting}/vulnerable.tsx (100%) diff --git a/pages/_app.tsx b/pages/_app.tsx index 8de162d..6850f20 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -63,8 +63,8 @@ export default function App({ Component, pageProps }: AppProps) { Example 6 diff --git a/pages/example-6-xss/common.tsx b/pages/example-6-cross-site-scripting/common.tsx similarity index 72% rename from pages/example-6-xss/common.tsx rename to pages/example-6-cross-site-scripting/common.tsx index feedb2f..39180d7 100644 --- a/pages/example-6-xss/common.tsx +++ b/pages/example-6-cross-site-scripting/common.tsx @@ -12,26 +12,26 @@ type Props = export function CommonContent(props: Props) { return ( <> -

    XSS - getServerSideProps

    +

    Cross-Site Scripting (XSS)

    • - + Vulnerable
    • - + Solution 1
    • - + Solution 2
    • - + Solution 3
    • diff --git a/pages/example-6-xss/solution-1.tsx b/pages/example-6-cross-site-scripting/solution-1.tsx similarity index 100% rename from pages/example-6-xss/solution-1.tsx rename to pages/example-6-cross-site-scripting/solution-1.tsx diff --git a/pages/example-6-xss/solution-2.tsx b/pages/example-6-cross-site-scripting/solution-2.tsx similarity index 100% rename from pages/example-6-xss/solution-2.tsx rename to pages/example-6-cross-site-scripting/solution-2.tsx diff --git a/pages/example-6-xss/solution-3.tsx b/pages/example-6-cross-site-scripting/solution-3.tsx similarity index 100% rename from pages/example-6-xss/solution-3.tsx rename to pages/example-6-cross-site-scripting/solution-3.tsx diff --git a/pages/example-6-xss/vulnerable.tsx b/pages/example-6-cross-site-scripting/vulnerable.tsx similarity index 100% rename from pages/example-6-xss/vulnerable.tsx rename to pages/example-6-cross-site-scripting/vulnerable.tsx diff --git a/pages/index.tsx b/pages/index.tsx index db18fff..f13dbb9 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -30,8 +30,8 @@ export default function Home() {
    • - - Example 6: XSS + + Example 6: Cross-Site Scripting (XSS)
    • From 2c42e6e587b748f59512b042d0fb6f8ebd40f60e Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 26 Oct 2022 14:55:36 +0200 Subject: [PATCH 21/24] Fix component names --- pages/example-5-secrets-exposure/solution-1.tsx | 2 +- pages/example-5-secrets-exposure/solution-2.tsx | 2 +- pages/example-5-secrets-exposure/vulnerable.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/example-5-secrets-exposure/solution-1.tsx b/pages/example-5-secrets-exposure/solution-1.tsx index eba15d2..1f6176c 100644 --- a/pages/example-5-secrets-exposure/solution-1.tsx +++ b/pages/example-5-secrets-exposure/solution-1.tsx @@ -7,7 +7,7 @@ type Props = { users: User[]; }; -export default function SecretsExposureGssp(props: Props) { +export default function SecretsExposure(props: Props) { return ; } diff --git a/pages/example-5-secrets-exposure/solution-2.tsx b/pages/example-5-secrets-exposure/solution-2.tsx index 87127ee..2d48c9a 100644 --- a/pages/example-5-secrets-exposure/solution-2.tsx +++ b/pages/example-5-secrets-exposure/solution-2.tsx @@ -6,7 +6,7 @@ type Props = { users: User[]; }; -export default function SecretsExposureGssp(props: Props) { +export default function SecretsExposure(props: Props) { const [apiResults, setApiResults] = useState([]); useEffect(() => { diff --git a/pages/example-5-secrets-exposure/vulnerable.tsx b/pages/example-5-secrets-exposure/vulnerable.tsx index 6ee9772..3635df4 100644 --- a/pages/example-5-secrets-exposure/vulnerable.tsx +++ b/pages/example-5-secrets-exposure/vulnerable.tsx @@ -7,7 +7,7 @@ type Props = { users: User[]; }; -export default function SecretsExposureGssp(props: Props) { +export default function SecretsExposure(props: Props) { const [apiResults, setApiResults] = useState([]); useEffect(() => { From c77f4a71677cc9f9cab98f845422df73dd39f843 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 26 Oct 2022 14:55:46 +0200 Subject: [PATCH 22/24] Fix component names --- pages/example-6-cross-site-scripting/solution-1.tsx | 2 +- pages/example-6-cross-site-scripting/solution-2.tsx | 2 +- pages/example-6-cross-site-scripting/solution-3.tsx | 2 +- pages/example-6-cross-site-scripting/vulnerable.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/example-6-cross-site-scripting/solution-1.tsx b/pages/example-6-cross-site-scripting/solution-1.tsx index 6aefefe..c48f62b 100644 --- a/pages/example-6-cross-site-scripting/solution-1.tsx +++ b/pages/example-6-cross-site-scripting/solution-1.tsx @@ -10,7 +10,7 @@ type Props = blogPost: BlogPost; }; -export default function MissingAuthenticationGssp(props: Props) { +export default function CrossSiteScripting(props: Props) { return (
      diff --git a/pages/example-6-cross-site-scripting/solution-2.tsx b/pages/example-6-cross-site-scripting/solution-2.tsx index b4d3f25..0cc36f0 100644 --- a/pages/example-6-cross-site-scripting/solution-2.tsx +++ b/pages/example-6-cross-site-scripting/solution-2.tsx @@ -11,7 +11,7 @@ type Props = blogPost: BlogPost; }; -export default function MissingAuthenticationGssp(props: Props) { +export default function CrossSiteScripting(props: Props) { return (
      diff --git a/pages/example-6-cross-site-scripting/solution-3.tsx b/pages/example-6-cross-site-scripting/solution-3.tsx index 6bfd056..a05180c 100644 --- a/pages/example-6-cross-site-scripting/solution-3.tsx +++ b/pages/example-6-cross-site-scripting/solution-3.tsx @@ -11,7 +11,7 @@ type Props = blogPost: BlogPost; }; -export default function MissingAuthenticationGssp(props: Props) { +export default function CrossSiteScripting(props: Props) { return (
      diff --git a/pages/example-6-cross-site-scripting/vulnerable.tsx b/pages/example-6-cross-site-scripting/vulnerable.tsx index 950dbbf..43742d1 100644 --- a/pages/example-6-cross-site-scripting/vulnerable.tsx +++ b/pages/example-6-cross-site-scripting/vulnerable.tsx @@ -10,7 +10,7 @@ type Props = blogPost: BlogPost; }; -export default function MissingAuthenticationGssp(props: Props) { +export default function CrossSiteScripting(props: Props) { return (
      From 1ee625495afa8aea9417a92e57a3fb9a32729e4c Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 26 Oct 2022 15:00:53 +0200 Subject: [PATCH 23/24] Improve clarity of comment --- .../solution-3.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pages/example-6-cross-site-scripting/solution-3.tsx b/pages/example-6-cross-site-scripting/solution-3.tsx index a05180c..88ac600 100644 --- a/pages/example-6-cross-site-scripting/solution-3.tsx +++ b/pages/example-6-cross-site-scripting/solution-3.tsx @@ -20,10 +20,19 @@ export default function CrossSiteScripting(props: Props) {

      {props.blogPost.title}

      Published: {String(props.blogPost.isPublished)}
      - {/* be careful which markdown library you use and how you use it - by default the markdown standard supports html tags too - so never assign markdown directly to innerHTML - but the default usage of "ReactMarkdown" is safe */} + {/* + Markdown alone is not safe by default. Many Markdown + libraries will also support full usage of HTML tags, + which opens up XSS attack vectors: + https://www.markdownguide.org/basic-syntax/#html + + react-markdown is safe against XSS by default: + https://github.com/remarkjs/react-markdown#security + + If you decide to use a different Markdown library, + make sure that it is secure or you enable any + configuration options to make it secure + */} )} From b89d8a8d2031f842ee21fdb77279112ba5c4cb67 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 26 Oct 2022 15:10:49 +0200 Subject: [PATCH 24/24] Add type to getServerSideProps return values --- pages/example-2-missing-authentication-gssp/solution-1.tsx | 6 ++++-- pages/example-2-missing-authentication-gssp/solution-2.tsx | 6 ++++-- pages/example-2-missing-authentication-gssp/vulnerable.tsx | 5 ++++- pages/example-4-missing-authorization-gssp/solution-1.tsx | 6 ++++-- pages/example-4-missing-authorization-gssp/solution-2.tsx | 6 ++++-- .../example-4-missing-authorization-gssp/vulnerable-1.tsx | 5 ++++- .../example-4-missing-authorization-gssp/vulnerable-2.tsx | 5 ++++- pages/example-5-secrets-exposure/solution-1.tsx | 5 ++++- pages/example-5-secrets-exposure/solution-2.tsx | 5 ++++- pages/example-5-secrets-exposure/vulnerable.tsx | 7 +++++-- pages/login.tsx | 6 ++++-- 11 files changed, 45 insertions(+), 17 deletions(-) diff --git a/pages/example-2-missing-authentication-gssp/solution-1.tsx b/pages/example-2-missing-authentication-gssp/solution-1.tsx index a191b69..b8abd3f 100644 --- a/pages/example-2-missing-authentication-gssp/solution-1.tsx +++ b/pages/example-2-missing-authentication-gssp/solution-1.tsx @@ -1,4 +1,4 @@ -import { GetServerSidePropsContext } from 'next'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import { BlogPost, getPublishedBlogPostsBySessionToken, @@ -17,7 +17,9 @@ export default function MissingAuthenticationGssp(props: Props) { return ; } -export async function getServerSideProps(context: GetServerSidePropsContext) { +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { const sessionToken = context.req.cookies.sessionToken; if (!sessionToken) { diff --git a/pages/example-2-missing-authentication-gssp/solution-2.tsx b/pages/example-2-missing-authentication-gssp/solution-2.tsx index 15c58c2..6d4fbbd 100644 --- a/pages/example-2-missing-authentication-gssp/solution-2.tsx +++ b/pages/example-2-missing-authentication-gssp/solution-2.tsx @@ -1,4 +1,4 @@ -import { GetServerSidePropsContext } from 'next'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import { BlogPost, getPublishedBlogPostsBySessionToken, @@ -18,7 +18,9 @@ export default function MissingAuthenticationGssp(props: Props) { return ; } -export async function getServerSideProps(context: GetServerSidePropsContext) { +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { const sessionToken = context.req.cookies.sessionToken; if (!sessionToken) { diff --git a/pages/example-2-missing-authentication-gssp/vulnerable.tsx b/pages/example-2-missing-authentication-gssp/vulnerable.tsx index 3a680b9..3ed4501 100644 --- a/pages/example-2-missing-authentication-gssp/vulnerable.tsx +++ b/pages/example-2-missing-authentication-gssp/vulnerable.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { BlogPost, getPublishedBlogPosts } from '../../database/blogPosts'; import Common from './common'; @@ -13,7 +14,9 @@ export default function MissingAuthenticationGssp(props: Props) { return ; } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult +> { const blogPosts = await getPublishedBlogPosts(); return { props: { diff --git a/pages/example-4-missing-authorization-gssp/solution-1.tsx b/pages/example-4-missing-authorization-gssp/solution-1.tsx index 352334f..bff40b8 100644 --- a/pages/example-4-missing-authorization-gssp/solution-1.tsx +++ b/pages/example-4-missing-authorization-gssp/solution-1.tsx @@ -1,4 +1,4 @@ -import { GetServerSidePropsContext } from 'next'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import { BlogPost, getUnpublishedBlogPostsBySessionToken, @@ -32,7 +32,9 @@ export default function MissingAuthorizationGssp(props: Props) { ); } -export async function getServerSideProps(context: GetServerSidePropsContext) { +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { const sessionToken = context.req.cookies.sessionToken; if (!sessionToken) { diff --git a/pages/example-4-missing-authorization-gssp/solution-2.tsx b/pages/example-4-missing-authorization-gssp/solution-2.tsx index 0bf0941..a80e451 100644 --- a/pages/example-4-missing-authorization-gssp/solution-2.tsx +++ b/pages/example-4-missing-authorization-gssp/solution-2.tsx @@ -1,4 +1,4 @@ -import { GetServerSidePropsContext } from 'next'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import { BlogPost, getUnpublishedBlogPostsByUserId, @@ -33,7 +33,9 @@ export default function MissingAuthorizationGssp(props: Props) { ); } -export async function getServerSideProps(context: GetServerSidePropsContext) { +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise> { const sessionToken = context.req.cookies.sessionToken; if (!sessionToken) { diff --git a/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx b/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx index fe1e2e2..8b2247b 100644 --- a/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx +++ b/pages/example-4-missing-authorization-gssp/vulnerable-1.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { BlogPost, getUnpublishedBlogPosts } from '../../database/blogPosts'; import { CommonContent } from './common'; @@ -28,7 +29,9 @@ export default function MissingAuthorizationGssp(props: Props) { ); } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult +> { const blogPosts = await getUnpublishedBlogPosts(); return { props: { diff --git a/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx b/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx index 74ef3f5..be0f411 100644 --- a/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx +++ b/pages/example-4-missing-authorization-gssp/vulnerable-2.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { BlogPost, getUnpublishedBlogPosts } from '../../database/blogPosts'; import { User } from '../../database/users'; import { CommonContent } from './common'; @@ -35,7 +36,9 @@ export default function MissingAuthorizationGssp(props: Props) { ); } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult> +> { const blogPosts = await getUnpublishedBlogPosts(); return { props: { diff --git a/pages/example-5-secrets-exposure/solution-1.tsx b/pages/example-5-secrets-exposure/solution-1.tsx index 1f6176c..01d82b7 100644 --- a/pages/example-5-secrets-exposure/solution-1.tsx +++ b/pages/example-5-secrets-exposure/solution-1.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { getUsers, User } from '../../database/users'; import Common from './common'; @@ -11,7 +12,9 @@ export default function SecretsExposure(props: Props) { return ; } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult +> { const users = await getUsers(); const response = await fetch( diff --git a/pages/example-5-secrets-exposure/solution-2.tsx b/pages/example-5-secrets-exposure/solution-2.tsx index 2d48c9a..2840df1 100644 --- a/pages/example-5-secrets-exposure/solution-2.tsx +++ b/pages/example-5-secrets-exposure/solution-2.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { useEffect, useState } from 'react'; import { getUsers, User } from '../../database/users'; import Common from './common'; @@ -26,7 +27,9 @@ export default function SecretsExposure(props: Props) { return ; } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult +> { const users = await getUsers(); return { props: { diff --git a/pages/example-5-secrets-exposure/vulnerable.tsx b/pages/example-5-secrets-exposure/vulnerable.tsx index 3635df4..7c0981d 100644 --- a/pages/example-5-secrets-exposure/vulnerable.tsx +++ b/pages/example-5-secrets-exposure/vulnerable.tsx @@ -1,3 +1,4 @@ +import { GetServerSidePropsResult } from 'next'; import { useEffect, useState } from 'react'; import { getUsersWithPasswordHash, User } from '../../database/users'; import Common from './common'; @@ -27,11 +28,13 @@ export default function SecretsExposure(props: Props) { return ; } -export async function getServerSideProps() { +export async function getServerSideProps(): Promise< + GetServerSidePropsResult +> { const users = await getUsersWithPasswordHash(); return { props: { - apiKey: process.env.API_KEY, + apiKey: process.env.API_KEY!, users: users, }, }; diff --git a/pages/login.tsx b/pages/login.tsx index af6ea62..f7794d5 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,4 +1,4 @@ -import { GetServerSidePropsContext } from 'next'; +import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { useState } from 'react'; @@ -101,7 +101,9 @@ username: bob / password: def`} ); } -export async function getServerSideProps(context: GetServerSidePropsContext) { +export async function getServerSideProps( + context: GetServerSidePropsContext, +): Promise>> { const token = context.req.cookies.sessionToken; if (token) {