{"id":20816634,"url":"https://github.com/alisharify7/flask-security-tips","last_synced_at":"2026-05-08T03:04:44.505Z","repository":{"id":223461438,"uuid":"760304356","full_name":"alisharify7/flask-security-tips","owner":"alisharify7","description":"top 10 security tips for flask application you should know. ","archived":false,"fork":false,"pushed_at":"2024-02-20T16:32:30.000Z","size":213,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-18T15:54:34.135Z","etag":null,"topics":["blog","flask","flask-security","flask-session","flask-web","python","security-tips","virgool"],"latest_commit_sha":null,"homepage":"https://vrgl.ir/d2xsv","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alisharify7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-20T06:59:57.000Z","updated_at":"2024-10-17T06:00:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"6b79003e-f30b-4bcd-a2ba-7d225e8f9407","html_url":"https://github.com/alisharify7/flask-security-tips","commit_stats":null,"previous_names":["alisharify7/flask-security-tips"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisharify7%2Fflask-security-tips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisharify7%2Fflask-security-tips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisharify7%2Fflask-security-tips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisharify7%2Fflask-security-tips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alisharify7","download_url":"https://codeload.github.com/alisharify7/flask-security-tips/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243165502,"owners_count":20246721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blog","flask","flask-security","flask-session","flask-web","python","security-tips","virgool"],"created_at":"2024-11-17T21:35:46.945Z","updated_at":"2025-12-28T06:19:09.057Z","avatar_url":"https://github.com/alisharify7.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 10 security flask tips\n\u003cp dir=\"rtl\"\u003e\n 10 توصیه امنیتی که برنامه فلسک شما را امن می کند\n\u003c/p\u003e\n\npost in virgool: https://vrgl.ir/d2xsv\n\n\u003cimg src=\"./media/index.webp\"\u003e\n\n\n\u003cdiv dir=\"rtl\"\u003e\n فلسک (Flask) یکی از فریمورک های قوی و محبوب Python هست که در ایرانم بسیار محبوبه نسبتا و هر روز هم داره محبوب تر میشه و برنامه های بیشتری باهاش نوشته میشه اما در این بین همیشه بحث امنیت (web security) یه مشکل اساسی بود.\n\n\n چون فلسک یه میکروفریمورک حساب میشه عملا با خیلی از ابزار ها نمی یاد و برنامه نویس باید یا خودش اونها رو پیاده سازی کنه یا از ابزار های سوم شخصی که توسعه دادن میشه و متن باز هستن استفاده کنه که خیلی از مواقع چون برنامه نویس درست بعضی از موارد رو کانفیگ نکرده باعث بروز مشکلات جدی میشه\n برعکس خیلی از فریمورک هایی مثل لاراول (PHP.laravel) - جنگو (Python.Django) - سی شارپ (CSHARP.ASP .NET)  و ... که عملا خیلی از موارد امنیتی و غیر توی خودشون دارن و از قبل هم یه کانفیگ اولیه شدن و آماده استفاده هستن ولی توی فلسک اینجوری نیست !\n\n\n  برای مثال یه برنامه ساده Hello World ساده رو توی فلسک رو میشه توی یک فایل (app.py) ساده با همین چند خط زیر نوشت :) !\n\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` python\nfrom flask import Flask\napp = Flask(__name__) \n\n@app.route(/,  methods=[GET]) \ndef index_view_page():\n     # index view return Hello World Text\n      return Hello World\n\nif __name__ == __main__:\n  app.run() # run flask application \n```\n\u003c/div\u003e\n\nو بعدش برای اجرای برنامه کافیه یا برنامه رو به صورت مستقیم با Python ران کنیم یا با دستور flask run اجرا کنیم\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` bash\n$ python3 app.py\n or \nflask run\n```\n``` bash \n* Debug mode: off WARNING: This is a development server. Do not use it in a production \n  deployment. Use a production WSGI server instead. \n * Running on http://127.0.0.1:5000\n Press CTRL+C to quit\n```\n\u003c/div\u003e\n\n\n\nخب حالا برای اینکه برنامه ما امن باشه باید چند تا چیز رو همیشه رعایت کنیم\n\n\u003cimg src=\"./media/46p0wegyolxt.webp\"\u003e\n\u003cimg src=\"./media/wnpx4etaobn9.webp\"\u003e\n\u003cimg src=\"./media/jakajpzt6pgz.webp\"\u003e\n\n\n\n\u003cdiv dir=\"ltr\"\u003e\n\n# 01.SECRET_KEY\n\n\u003c/div\u003e\n\nهمیشه برای برنامه اتون سعی کند یه SECRET_KEY قوی بزارید, به این دلیل که فلسک از این SECRET_KEY خیلی جاها استفاده میکنه مثال برای رمزنگاری داده ها و ....\n یه مثال ساده اش میشه SESSION ها که توی cookie سمت کاربر ذخیره میشه اما رمز (رمزنگاری) میشه که کاربر نتونه دستکاریش کنه\nبرای تنظیم secret_key هم میتونید به روش های مختلفی عمل کنید یه روش معمولیش اینه از طریق آبجکت اصلی app این کارو انجام بدید\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` python\napp.config[SECRET_KEY] = os.urandom(24) or 'string Secret key'\n```\n\u003c/div\u003e\n\nبرای درست کردن رشته های تصادفی هم میتونید از کتابخونه های زیادی استفاده کنید ولی من خودم os, secrets رو یشنهاد میکنم چون build in (داخلی - دیفالت در خود Python قرار دارند) هستند \n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` bash\nIn [1]: import os\nIn [2]: import secrets\nIn [3]: os.urandom(6)\nOut[3]: b iI3C\\x9c8\nIn [4]: secrets.token_hex(6)\nOut[4]: 1c918c95737f\nIn [5]:\n```\n\u003c/div\u003e\n\n\u003cdiv dir=\"ltr\"\u003e\n\n# 02.DEBUG MODE\n\n\u003c/div\u003e\n\nیکی از اشتباهات رایج برنامه نویس ها اینکه که فراموش می کنند DEBUG رو توی برنامه اشون FALSE کنند و برنامه رو روی حالت production قرار بدن که معمولا سبب میشه یه سری اطلاعات محرمانه گاهی افشا بشن\nحتما حواستون باشه که برنامه اتون در حالت production قرار داشته باشه \nمن خودم معمولا یه sccript دارم که در background اجرا میشه و چک میکنه اگر توی سرور debug = True بود خودش میاد debug رو False میکنه \n\n\n\n\u003cdiv dir=\"ltr\"\u003e\n\n# 03.Don’t Store Sensitive Data in Cookies\n\n\u003c/div\u003e\n\nاطلاعات حساس رو در session کاربر قرار ندید چون session ها در سمت کاربر توی cookie ذخیره میشن امن نیست اطلاعات حساس رو در session ذخیره کنید \nاگر نیاز دارید اطلاعات رو session کاربر ذخیره کنید بهتره session ها server side ذخیره بشن \n\n\u003cimg src=\"./media/lcgtr4djgpke.png\"\u003e\n\n\nدر حالت خلاصه session server side جای اینکه اطلاعات رو در session در سمت کاربر ذخیره کنه میاد اطلاعات رو در سمت سرور ذخیره می کنه و به جاش یه ID منtحصر به فرد به کاربر میده (در session کاربر ذخیره میکنه ) و اطلاعات رو در سمت سرور توی فایل یا یه دیتابیس (mysql-redis-postgres , ...) ذخیره میکنه\nو با هر بار درخواست کاربر میاد با توجه به ID کاربر اطلاعات رو از دیتابیس فراخوانی میکنه \n\nبرای این کار میتونید از افزونه flask-session استفاده کنید. به علت اینکه این بحث طولانیه و خودش یه post دیگه می طلبه شمارو راهنمایی می کنم به داکیومنت flask-session برای کسب اطلاعات بیشتر\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` bash\n$ pip install flask-session\nflask-session doc: \nhttps://flask-session.readthedocs.io/en/latest/\n```\n\n\u003c/div\u003e\n\n\n\u003cdiv dir=\"ltr\"\u003e\n\n# 04.CSRF TOKEN PROTECTION\n\n\u003c/div\u003e\n\nبرای جلوگیری از اینکه درخواست غیرمجازی از سمت هکر ها به سمت سرور های ما (Flask Application) ارسال بشه باید از csrf token استفاده کنیم \n\n\u003cimg src=\"./media/pzkr3bohfwcr.webp\"\u003e\n\n\nدر یه تعریف انتزاعی و سطح بالا این توکن میاد صحت سنجی میکنه که درخواست از سمت کاربر اصلی ما ارسال شده و به طور فرعی یا غیرمستقیم ارسال نشده (خیلی ساده شده توضیح دادم ولی برای کسب اطلاعات بیشتر به این لینک برید)\nکتابخونه های زیادی برای این کار وجود داره ولی یکی از معروف ترینشون کتابخونه flask-wtf هست که میاد این قابلیت رو به برنامه ما اضافه می کنه\nما ابتدا با دستور زیر این کتابخونه رو نصب می کنیم\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` bash\n$ pip install flask-wtf\n```\n\n\u003c/div\u003e\n\nو بعدش میاییم مثل هر کتابخونه دیگه فلسکی یه آبجکت از کلاس اصلیش می سازیم \n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` python\nfrom flask import Flask\nfrom flask_wtf.csrf import CSRFProtect\n\napp = Flask(__name__)\napp.config[SECRET_KEY] = os.urandom(24) or Secret key\n\n# after configuration process\ncsrf = CSRFProtect(app=app)\n```\n\n\u003c/div\u003e\n\nبا این کار به صورت خودکار این قابلیت به برنامه ما اضافه شد و حالا هر درخواست از نوع POST به سمت برنامه ما بیاد این افزونه اول چک میکنه که csrf token درسته یا نه و اگر درست بود اجازه میده درخواست به view برسه و انجام بشه در غیراین صورت ارور 400 برمیگردونه \n\n\u003cimg src=\"./media/qnsx4zhxyciv.webp\"\u003e\n\nبرای  اضافه کردن csrf token به فرم هاتون میتونید از فرم های wtf استفاده کنید یا به صورت دستی به هر فرمی که داشتید بیایید یه input با type=Hidden و name=csrf_token بدید دقت کنید اسم باید دقیقا یکی باشه!\nو بعد توی value اون input بیایید و فیلتر csrf_token رو صدا بزنید \n\n\n\u003cimg src=\"./media/poxm3zkwc2vo.webp\"\u003e\n\n\u003cimg src=\"./media/emxxwpitckgn.webp\"\u003e\n\nاین input با هر بار درخواست یه مقدار تصادفی داره که برای هر کاربر متفاوته و سرور میاد این درخواست هارو بر اساس این مقدار صحت سنجی می کنه\n\n\n\u003cdiv dir=\"ltr\"\u003e\n\n# 05. Broken Authentication\n\n\u003c/div\u003e\n\n\n\nبهتره برای احراز هویت کاربر از افزونه های سوم شخص (معتبر و رسمی) استفاده کنید و خودتون کل این فرایند رو پیاده سازی نکنید. چون هم گاهی یه سری edge case وجود داره که از زیر دستتون در میره و باعث باگ میشه و اینکه این فرایند نیازمند بروزرسانی های  دائم و دقیقی داره \nبرای این فرایند میتونید از افزونه flask-login استفاده کنید و دوباره چون این افزونه دنیای خودش رو داره و نمیشه توی همین post کامل راجبش نوشته شمارو هدایت می کنم به داکیومنت رسمی flask-login\n\n\u003cdiv dir=\"ltr\"\u003e\n\n```bash\n$ pip install flask-login\nflask-login doc:\nhttps://flask-login.readthedocs.io/en/latest/\n```\n\u003c/div\u003e\n\n\n\n# 06.Validate Inputs and Outputs\nبرای برنامه اتون ورودی و خروجی هارو حتما بررسی کنید و اعتبار سنجی کنید این ورودی ها میتونن شامل اطلاعات ذخیره شده در request باشند یا حتی اطلاعات ارسال شده از طریق form یا ...\nکه خود این مشکل میتونه باعت مشکلات اساسی مثل sql injection , xss ... میشه\nبرای این کار بهتره فرم هارو خودتون دستی نسازید و از کتابخونه هایی که برای این کار هستند استفاده کنید مثل flask-wtf برای ساخت فرم ها و flask-sqlachemy برای ارتباط با دیتابیس (CRUD)(ORM) و ...\n\n\n    اگه دوست دارید بیشتر راجب flask-sqlalchemy بدونید و بخونید این نوشته قبلی من رو یه سری بزنید \n     https://vrgl.ir/wfO4E\n\n\n\n\n# 07.Use the Latest Version of Flask\nهمیشه سعی کنید از آخرین ورژن بروز فلسک و افزونه هایی که استفاده می کنید استفاده کنید\n این یکی از مهم ترین شاخصه هاست. اصلا از نسخه های قدیمی یا Deprecate استفاده نکنید \nبعضی از برنامه از یه افزونه های خاصی استفاده می کنند که خیلی وقته که بروز نشدن در نتیجه با یه ورژن خاصی از فلسک سازگارن که معمولا قدیمیه و این بشدت خطرناکه \nبرای همین همیشه بروز باشید و سعی کنید در بروزترین حالت ممکن باشه package هاتون\n\n\n\n\n# 08.don't comment Sensitive information in templates\nگاهی اوقات خیلی از افراد بی تجربه میان و توی template هاشون یه سری اطلاعات رو comment می کنند و فراموش می کنن که روی production این کامنت هارو حذف کنن و باعث ایجاد خیلی از مشکلات میشن \n+ حتی گاهی دیده شده که رمز دیتابیس رو هم توی template بوده :)\n پیشنهاد من اینکه که حد الامکان اصلا کامنتی چیزی ندازید چون بعدا یادتون میره حذفش کنید‌(هر چند ابزار هایی هم برای این مورد هست که کدتون رو review می کنه و اگر توکن یا چیز مهمی رو گزاشته باشید بین کد بهتون هشدار میده) ولی تجربه ثابت کرده که نکنید بهتره \nولی اگر می کنید با استفاده از jinja این کارو کنید. خود فلسک برای هندل کردن template هاش از template engine jinja2 استفاده می کنه که قبل از این که هر template ای به سمت کاربر ارسال بشه اول به این engine داده میشه تا parse (یه جورایی انگار compile میکنه ولی در اصل میاد یه سری مقادیر رو جای گذاری میکنه و یه سری حلقه یا شرط هارو چک میکنه)‌ بشه و مقادیری یا هر کاری هست توش انجام بشه و بعد به سمت کاربر ارسال بشه\nبرای کامنت گذاشتن حداقلش با jinja کامنت بزارید چون هنگام parse کردن این کامنت هارو نادیده میگیره و ازشون رد میشه ولی در کد همچنان باقی میمونه (هر چند این روشم پیشنهاد نمیشه ولی خب :) )\nبرای کامنت گذاشتن توی خود html باید طبق زیر عمل کنیم :\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` html\n\u003c!-- Write your comments here --\u003e\n```\n\n\u003c/div\u003e\n\nاما توی jinja باید طبق زیر عمل کنیم \n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` python\n{# Write your comments here  #}\n```\n\n\u003c/div\u003e\n\n\nیعنی اگر توی کد ما طبق زیر کامنت بزارید و بعد با مرورگر صفحه رو ببینیم (source code ,   ctrl+U)\n\n\n\u003cimg src=\"./media/d8dyxhi84cqc.webp\"\u003e\n\n\nچیزی که در اصل می بینیم چیزی مثل زیره:\n\n\n\u003cimg src=\"./media/ukjkyrqyopwy.webp\"\u003e\n\n\nو همینطور که میبینم کامنتی که با jinja گزاشتیم به صورت خودکار از template حذف شده و بعد template به سمت کاربر ارسال شده\n\n\n\n\n# 09.Use an ORM (Object–relational mapping)\nبرای ساخت جداول دیتابیس و عملیات های درج و ویرایش و ... بهتره از یه ORM استفاده بشه تا اینکه به صورت خام (raw) خودمون بین کدامون کد sql بنویسیم \nچون گاهی هکر ها از این وضعیت استفاده می کنن و کد های مخربی رو به فرم ما اضافه و ارسال می کنن که در عمل درسته مثال برای یه کوثری ساده که میخواییم یه کاربر رو توی دیتابیس جستجو کنیم یه چیزی مثل زیره در حالت عادی:\nتوجه: در مثال زیر حالاتی که بین دو تا  علامت % قرار دارند متغییر هستند و از معنی مستقلشون در sql جدا هستند \n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` sql\n SELECT * FROM users WHERE username = '%username%' AND password = '%password%';\n```\n\n\u003c/div\u003e\n\nکه برنامه ما میاد و username  و password رو جای این متغییر ها قرار میده و یه درخواست میزنه به دیتابیس \nاما اما اما یه هکری زرنگ میاد و داده رو طوری که ما میخواییم ارسال نمی کنه و این فرایند رو دور میزنه یا در اصل میپیچونه چجوری؟\nمیاد و مقادیری username  و password رو به صورت زیر برای ما ارسال میکنه \n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` bash\nusername = 'admin --'\npassword = '   '\n```\n\n\u003c/div\u003e\n\nو برنامه ما درخواستی اصلی (query) رو به صورت زیر در نهایت به دست میاره\n\n\u003cdiv dir=\"ltr\"\u003e\n\n``` sql\n SELECT * FROM users WHERE username = 'admin' -- AND password = ' ';\n```\n\n\u003c/div\u003e\n\nهمینطور که میدونید علامت -- برای کامنت کردن در sql استفاده میشه یعنی عبارت بالا تنها یه درخواست میزنه و میبینه که آیا کاربری تحت نام کاربری admin هست یا نه و دیگه گذرواژه کاربر رو چک نمی کنه ;)\n\n\n\u003cimg src=\"./media/u4loqqjcbt6y.webp\"\u003e\n\n\ncomment in sql\n\n     و به این صورت هکری میتونه به حساب کاربری ادمین وارد بشه. اما با استفاده از ORM ها ما جلوی این اتفاق رو می گیریم به صورت دیفالت (استفاده از ORM مزایای خیلی بیشتری نسبت به این داره و این تنها یکی از خوبیای استفاده از ORM هست)\n    چون در این رابطه یه نوشته کامل در ویرگول نوشتم زیاد نمی پردازم بهش اینجا و شمارو هدایت می کنم به اون نوشته از طریق این لینک \n     https://vrgl.ir/wfO4E\n\n\n\n\n\n\n# 10. http security header\nبه صورت کلی مرورگر و کاربر با استفاده از http header ها یک سری اطلاعات رو بین خودشون انتقال میدن \nمثال برای اینکه سرور طول محتوای ارسالی رو به مرورگر بگه توی یه http header ای به اسم content-length میاد و این طول رو قرار میده و برای مرورگر ارسال میکنه(client)(صرفا مرورگر نه کلا هر برنامه یا کلاینتی که درخواست رو میزنه) یا مثلا برای اینکه سرور به کلاینت بگه نوع سند ارسالیش چیه اون رو توی یه http header خاصی به اسم Content-Type قرار میده \n\n\n\u003cimg src=\"./media/xf72xnl5yx1x.webp\"\u003e\n\n\nمثال اگر همین الان روی همین صفحه دکمه f12 رو بزنید و به تب Network برید و اولین درخواست رو باز کنید و به سربرگ headers برید میتونید http header هایی که سرور های ویرگول برای مرورگرتون ارسال کرده رو ببینید‌(در این مورد خاص چون ویرگول پشت CDN ابراروان هست یه بخشی از هدر ها توسط ابراروان تنظیم میشه )\nمثال نوع برگشتی این سند از نوع text/html; charset=UTF-8 هست و اینکه تاریخ ارسال سند Tue, 20 Feb 2024 08:45:54 GMT هست و تاریخ انقضای این سند Tue, 20 Feb 2024 08:45:54 GMT هست \n\n     و یا اینکه سروری که این پاسخ رو به من داده ArvanCloud هست (ابرآروان یه ارایه دهنده سرویس CDN در ایرانه )\n     ما یک سری http header استاندار داریم که تمام مرورگر ها اونها رو میفهنن و متوجه میشن که لیستش رو میتونید در این لینک بخونید \n      https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n\n\u003cimg src=\"./media/08o397pwly6d.webp\"\u003e\n\n\n\nاما یه سری هدر هم خود برنامه نویس به صورت اختیاری قرار میده و ارسال میکنه برای کلاینت (معمولا همون برنامه سمت کاربر که میشه react app یا vue و ...) که با x معمولا شروع میشه \nبرای دیدن لیست تمام http security header ها میتونید به لینک زیر برید:\nhttps://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html\n\n# سخن نهایی\n\nدر انتها اینکه امنیت به طور کامل نیست و همیشه یه نقطه ای هست که از دست شما در رفته و امن نیست ولی شما باید تلاش کنید که همیشه بروز باشید :) \nامیدوارم این نوشته به دردتون بخوره و براتون مفید باشه اگر مشکلی یا سوالی هم داشتید میتونید توی قسمت کامنت ها برام بنویسید\n \n\n\n\n ## منابع مورد استفاده در این نوشته :\n\n- https://climbtheladder.com/10-flask-security-best-practices/\n- https://flask-login.readthedocs.io/en/latest/\n- https://portswigger.net/web-security/csrf\n- https://www.javatpoint.com/session-vs-cookies\n- https://medium.com/@tiff.sage/client-side-session-vs-server-side-session-d506f5408e8c\n- https://testdriven.io/tips/topics/flask\n- https://www.invicti.com/blog/web-security/http-security-headers/\n- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n- https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falisharify7%2Fflask-security-tips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falisharify7%2Fflask-security-tips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falisharify7%2Fflask-security-tips/lists"}