moriarty-project 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- moriarty/__init__.py +5 -0
- moriarty/adapters/__init__.py +0 -0
- moriarty/agent/__init__.py +0 -0
- moriarty/assets/modules/.gitkeep +0 -0
- moriarty/assets/modules/asia/douban.yaml +19 -0
- moriarty/assets/modules/asia/kakao.yaml +19 -0
- moriarty/assets/modules/asia/line.yaml +19 -0
- moriarty/assets/modules/asia/mixi.yaml +19 -0
- moriarty/assets/modules/asia/naver.yaml +19 -0
- moriarty/assets/modules/asia/qq.yaml +19 -0
- moriarty/assets/modules/asia/vk.yaml +19 -0
- moriarty/assets/modules/asia/wechat.yaml +19 -0
- moriarty/assets/modules/asia/weibo.yaml +19 -0
- moriarty/assets/modules/asia/xiaohongshu.yaml +19 -0
- moriarty/assets/modules/behance.yaml +47 -0
- moriarty/assets/modules/business/crunchbase.yaml +27 -0
- moriarty/assets/modules/business/fiverr.yaml +32 -0
- moriarty/assets/modules/business/freelancer.yaml +27 -0
- moriarty/assets/modules/business/glassdoor.yaml +27 -0
- moriarty/assets/modules/business/guru.yaml +26 -0
- moriarty/assets/modules/business/indeed.yaml +25 -0
- moriarty/assets/modules/business/monster.yaml +25 -0
- moriarty/assets/modules/business/peopleperhour.yaml +26 -0
- moriarty/assets/modules/business/toptal.yaml +28 -0
- moriarty/assets/modules/business/upwork.yaml +27 -0
- moriarty/assets/modules/business/ziprecruiter.yaml +25 -0
- moriarty/assets/modules/content/buymeacoffee.yaml +27 -0
- moriarty/assets/modules/content/gumroad.yaml +27 -0
- moriarty/assets/modules/content/ko-fi.yaml +32 -0
- moriarty/assets/modules/content/onlyfans.yaml +27 -0
- moriarty/assets/modules/content/patreon.yaml +33 -0
- moriarty/assets/modules/content/substack.yaml +32 -0
- moriarty/assets/modules/creative/500px.yaml +31 -0
- moriarty/assets/modules/creative/artstation.yaml +33 -0
- moriarty/assets/modules/creative/deviantart.yaml +32 -0
- moriarty/assets/modules/creative/flickr.yaml +31 -0
- moriarty/assets/modules/creative/pexels.yaml +26 -0
- moriarty/assets/modules/creative/unsplash.yaml +26 -0
- moriarty/assets/modules/creative/vimeo.yaml +31 -0
- moriarty/assets/modules/crypto/binance.yaml +27 -0
- moriarty/assets/modules/crypto/bitcointalk.yaml +33 -0
- moriarty/assets/modules/crypto/coinbase.yaml +26 -0
- moriarty/assets/modules/crypto/etherscan.yaml +32 -0
- moriarty/assets/modules/crypto/foundation.yaml +28 -0
- moriarty/assets/modules/crypto/kraken.yaml +27 -0
- moriarty/assets/modules/crypto/mirror.yaml +27 -0
- moriarty/assets/modules/crypto/niftygateway.yaml +26 -0
- moriarty/assets/modules/crypto/opensea.yaml +32 -0
- moriarty/assets/modules/crypto/rarible.yaml +27 -0
- moriarty/assets/modules/crypto/superrare.yaml +29 -0
- moriarty/assets/modules/dating/bumble.yaml +25 -0
- moriarty/assets/modules/dating/grindr.yaml +27 -0
- moriarty/assets/modules/dating/happn.yaml +25 -0
- moriarty/assets/modules/dating/her.yaml +27 -0
- moriarty/assets/modules/dating/hinge.yaml +25 -0
- moriarty/assets/modules/dating/match.yaml +25 -0
- moriarty/assets/modules/dating/meetme.yaml +27 -0
- moriarty/assets/modules/dating/okcupid.yaml +25 -0
- moriarty/assets/modules/dating/pof.yaml +25 -0
- moriarty/assets/modules/dating/tinder.yaml +25 -0
- moriarty/assets/modules/dating-nsfw/adultfriendfinder.yaml +28 -0
- moriarty/assets/modules/dating-nsfw/ashley-madison.yaml +26 -0
- moriarty/assets/modules/design/adobe-portfolio.yaml +27 -0
- moriarty/assets/modules/design/carbonmade.yaml +27 -0
- moriarty/assets/modules/design/cgsociety.yaml +27 -0
- moriarty/assets/modules/design/coroflot.yaml +27 -0
- moriarty/assets/modules/design/figma.yaml +27 -0
- moriarty/assets/modules/design/sketch.yaml +26 -0
- moriarty/assets/modules/dev/bitbucket.yaml +35 -0
- moriarty/assets/modules/dev/codeforces.yaml +32 -0
- moriarty/assets/modules/dev/codepen.yaml +34 -0
- moriarty/assets/modules/dev/hackerone.yaml +32 -0
- moriarty/assets/modules/dev/hackthebox.yaml +27 -0
- moriarty/assets/modules/dev/huggingface.yaml +27 -0
- moriarty/assets/modules/dev/kaggle.yaml +32 -0
- moriarty/assets/modules/dev/leetcode.yaml +32 -0
- moriarty/assets/modules/dev/replit.yaml +31 -0
- moriarty/assets/modules/dribbble.yaml +53 -0
- moriarty/assets/modules/ecommerce/etsy.yaml +32 -0
- moriarty/assets/modules/education/duolingo.yaml +32 -0
- moriarty/assets/modules/education/edx.yaml +26 -0
- moriarty/assets/modules/education/khanacademy.yaml +26 -0
- moriarty/assets/modules/education/lynda.yaml +27 -0
- moriarty/assets/modules/education/memrise.yaml +27 -0
- moriarty/assets/modules/education/pluralsight.yaml +27 -0
- moriarty/assets/modules/education/skillshare.yaml +27 -0
- moriarty/assets/modules/education/udacity.yaml +27 -0
- moriarty/assets/modules/email/github_email.yaml +40 -0
- moriarty/assets/modules/email/gravatar.yaml +23 -0
- moriarty/assets/modules/europe/badoo.yaml +19 -0
- moriarty/assets/modules/europe/lovoo.yaml +19 -0
- moriarty/assets/modules/europe/myspace.yaml +19 -0
- moriarty/assets/modules/europe/netlog.yaml +19 -0
- moriarty/assets/modules/europe/ok.yaml +19 -0
- moriarty/assets/modules/europe/skyrock.yaml +19 -0
- moriarty/assets/modules/europe/studivz.yaml +19 -0
- moriarty/assets/modules/europe/tuenti.yaml +19 -0
- moriarty/assets/modules/europe/viadeo.yaml +19 -0
- moriarty/assets/modules/europe/xing.yaml +19 -0
- moriarty/assets/modules/fitness/fitbit.yaml +27 -0
- moriarty/assets/modules/fitness/garmin.yaml +27 -0
- moriarty/assets/modules/fitness/myfitnesspal.yaml +27 -0
- moriarty/assets/modules/fitness/strava.yaml +33 -0
- moriarty/assets/modules/fitness/zwift.yaml +28 -0
- moriarty/assets/modules/food/allrecipes.yaml +27 -0
- moriarty/assets/modules/food/tasty.yaml +27 -0
- moriarty/assets/modules/food/yelp.yaml +32 -0
- moriarty/assets/modules/food/zomato.yaml +28 -0
- moriarty/assets/modules/forums/4chan.yaml +26 -0
- moriarty/assets/modules/forums/8kun.yaml +26 -0
- moriarty/assets/modules/forums/9gag.yaml +26 -0
- moriarty/assets/modules/forums/discourse.yaml +26 -0
- moriarty/assets/modules/forums/disqus.yaml +31 -0
- moriarty/assets/modules/forums/hackernews.yaml +32 -0
- moriarty/assets/modules/forums/launchpad.yaml +27 -0
- moriarty/assets/modules/forums/phpbb.yaml +25 -0
- moriarty/assets/modules/forums/quora.yaml +32 -0
- moriarty/assets/modules/forums/serverfault.yaml +27 -0
- moriarty/assets/modules/forums/slashdot.yaml +28 -0
- moriarty/assets/modules/forums/stackexchange.yaml +32 -0
- moriarty/assets/modules/forums/superuser.yaml +27 -0
- moriarty/assets/modules/forums/vbulletin.yaml +25 -0
- moriarty/assets/modules/forums/xenforo.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/kiwifarms.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/lolcow.yaml +26 -0
- moriarty/assets/modules/gaming/apextracker.yaml +27 -0
- moriarty/assets/modules/gaming/battlenet.yaml +26 -0
- moriarty/assets/modules/gaming/chess.yaml +30 -0
- moriarty/assets/modules/gaming/discord-public.yaml +27 -0
- moriarty/assets/modules/gaming/dotabuff.yaml +32 -0
- moriarty/assets/modules/gaming/epicgames.yaml +25 -0
- moriarty/assets/modules/gaming/faceit.yaml +33 -0
- moriarty/assets/modules/gaming/fortnitetracker.yaml +32 -0
- moriarty/assets/modules/gaming/gog.yaml +26 -0
- moriarty/assets/modules/gaming/itch.yaml +32 -0
- moriarty/assets/modules/gaming/kongregate.yaml +25 -0
- moriarty/assets/modules/gaming/minecraft.yaml +31 -0
- moriarty/assets/modules/gaming/opgg.yaml +32 -0
- moriarty/assets/modules/gaming/origin.yaml +26 -0
- moriarty/assets/modules/gaming/playstation.yaml +30 -0
- moriarty/assets/modules/gaming/roblox.yaml +31 -0
- moriarty/assets/modules/gaming/xbox.yaml +25 -0
- moriarty/assets/modules/github.yaml +68 -0
- moriarty/assets/modules/gitlab.yaml +60 -0
- moriarty/assets/modules/instagram.yaml +48 -0
- moriarty/assets/modules/latam/fotolog.yaml +27 -0
- moriarty/assets/modules/latam/orkut.yaml +26 -0
- moriarty/assets/modules/latam/taringa.yaml +27 -0
- moriarty/assets/modules/learning/coursera.yaml +26 -0
- moriarty/assets/modules/learning/udemy.yaml +26 -0
- moriarty/assets/modules/linkedin.yaml +40 -0
- moriarty/assets/modules/marketplaces/depop.yaml +28 -0
- moriarty/assets/modules/marketplaces/ebay.yaml +32 -0
- moriarty/assets/modules/marketplaces/grailed.yaml +27 -0
- moriarty/assets/modules/marketplaces/mercari.yaml +26 -0
- moriarty/assets/modules/marketplaces/poshmark.yaml +27 -0
- moriarty/assets/modules/marketplaces/reverb.yaml +27 -0
- moriarty/assets/modules/marketplaces/vinted.yaml +28 -0
- moriarty/assets/modules/medium.yaml +44 -0
- moriarty/assets/modules/music/audiomack.yaml +26 -0
- moriarty/assets/modules/music/bandcamp.yaml +30 -0
- moriarty/assets/modules/music/beatport.yaml +28 -0
- moriarty/assets/modules/music/deezer.yaml +26 -0
- moriarty/assets/modules/music/discogs.yaml +32 -0
- moriarty/assets/modules/music/genius.yaml +26 -0
- moriarty/assets/modules/music/lastfm.yaml +30 -0
- moriarty/assets/modules/music/mixcloud.yaml +26 -0
- moriarty/assets/modules/music/reverbnation.yaml +31 -0
- moriarty/assets/modules/music/soundcloud.yaml +31 -0
- moriarty/assets/modules/music/spotify.yaml +26 -0
- moriarty/assets/modules/music/tidal.yaml +26 -0
- moriarty/assets/modules/nsfw/adultwork.yaml +27 -0
- moriarty/assets/modules/nsfw/bongacams.yaml +28 -0
- moriarty/assets/modules/nsfw/cam4.yaml +28 -0
- moriarty/assets/modules/nsfw/chaturbate.yaml +28 -0
- moriarty/assets/modules/nsfw/clips4sale.yaml +27 -0
- moriarty/assets/modules/nsfw/extralunchmoney.yaml +27 -0
- moriarty/assets/modules/nsfw/fansly.yaml +28 -0
- moriarty/assets/modules/nsfw/fetlife.yaml +28 -0
- moriarty/assets/modules/nsfw/iwantclips.yaml +27 -0
- moriarty/assets/modules/nsfw/justforfans.yaml +28 -0
- moriarty/assets/modules/nsfw/loyalfans.yaml +28 -0
- moriarty/assets/modules/nsfw/manyvids.yaml +27 -0
- moriarty/assets/modules/nsfw/myfreecams.yaml +28 -0
- moriarty/assets/modules/nsfw/niteflirt.yaml +26 -0
- moriarty/assets/modules/nsfw/pornhub.yaml +32 -0
- moriarty/assets/modules/nsfw/redtube.yaml +27 -0
- moriarty/assets/modules/nsfw/stripchat.yaml +28 -0
- moriarty/assets/modules/nsfw/xhamster.yaml +27 -0
- moriarty/assets/modules/nsfw/xvideos.yaml +27 -0
- moriarty/assets/modules/nsfw/youporn.yaml +27 -0
- moriarty/assets/modules/photography/eyeem.yaml +25 -0
- moriarty/assets/modules/photography/fotki.yaml +25 -0
- moriarty/assets/modules/photography/photobucket.yaml +26 -0
- moriarty/assets/modules/photography/smugmug.yaml +25 -0
- moriarty/assets/modules/photography/vsco.yaml +27 -0
- moriarty/assets/modules/pinterest.yaml +40 -0
- moriarty/assets/modules/podcasts/anchor.yaml +26 -0
- moriarty/assets/modules/podcasts/castbox.yaml +26 -0
- moriarty/assets/modules/podcasts/podbean.yaml +26 -0
- moriarty/assets/modules/professional/about.yaml +31 -0
- moriarty/assets/modules/professional/academia.yaml +27 -0
- moriarty/assets/modules/professional/angellist.yaml +27 -0
- moriarty/assets/modules/professional/calendly.yaml +26 -0
- moriarty/assets/modules/professional/issuu.yaml +27 -0
- moriarty/assets/modules/professional/mendeley.yaml +27 -0
- moriarty/assets/modules/professional/notion.yaml +27 -0
- moriarty/assets/modules/professional/orcid.yaml +27 -0
- moriarty/assets/modules/professional/producthunt.yaml +31 -0
- moriarty/assets/modules/professional/researchgate.yaml +32 -0
- moriarty/assets/modules/professional/scribd.yaml +27 -0
- moriarty/assets/modules/professional/slideshare.yaml +31 -0
- moriarty/assets/modules/professional/trello.yaml +26 -0
- moriarty/assets/modules/professional/typeform.yaml +27 -0
- moriarty/assets/modules/reddit.yaml +46 -0
- moriarty/assets/modules/regional/amino.yaml +27 -0
- moriarty/assets/modules/regional/ask-fm.yaml +32 -0
- moriarty/assets/modules/regional/babycenter.yaml +26 -0
- moriarty/assets/modules/regional/cafemom.yaml +27 -0
- moriarty/assets/modules/regional/care2.yaml +27 -0
- moriarty/assets/modules/regional/diaspora.yaml +26 -0
- moriarty/assets/modules/regional/ello.yaml +27 -0
- moriarty/assets/modules/regional/gaia.yaml +27 -0
- moriarty/assets/modules/regional/habbo.yaml +27 -0
- moriarty/assets/modules/regional/imvu.yaml +27 -0
- moriarty/assets/modules/regional/lemmy.yaml +27 -0
- moriarty/assets/modules/regional/peertube.yaml +26 -0
- moriarty/assets/modules/regional/pixelfed.yaml +27 -0
- moriarty/assets/modules/regional/plurk.yaml +26 -0
- moriarty/assets/modules/regional/recroom.yaml +27 -0
- moriarty/assets/modules/regional/secondlife.yaml +26 -0
- moriarty/assets/modules/regional/vine-archive.yaml +27 -0
- moriarty/assets/modules/regional/vrchat.yaml +27 -0
- moriarty/assets/modules/regional/weheartit.yaml +27 -0
- moriarty/assets/modules/social/anilist.yaml +27 -0
- moriarty/assets/modules/social/beacons.yaml +26 -0
- moriarty/assets/modules/social/blogger.yaml +27 -0
- moriarty/assets/modules/social/crunchyroll.yaml +27 -0
- moriarty/assets/modules/social/discord.yaml +27 -0
- moriarty/assets/modules/social/dreamwidth.yaml +26 -0
- moriarty/assets/modules/social/facebook.yaml +34 -0
- moriarty/assets/modules/social/goodreads.yaml +32 -0
- moriarty/assets/modules/social/imdb.yaml +27 -0
- moriarty/assets/modules/social/kitsu.yaml +27 -0
- moriarty/assets/modules/social/letterboxd.yaml +32 -0
- moriarty/assets/modules/social/linktree.yaml +26 -0
- moriarty/assets/modules/social/livejournal.yaml +27 -0
- moriarty/assets/modules/social/mastodon.yaml +30 -0
- moriarty/assets/modules/social/minds.yaml +25 -0
- moriarty/assets/modules/social/myanimelist.yaml +32 -0
- moriarty/assets/modules/social/ravelry.yaml +27 -0
- moriarty/assets/modules/social/snapchat.yaml +25 -0
- moriarty/assets/modules/social/telegram.yaml +35 -0
- moriarty/assets/modules/social/tiktok.yaml +35 -0
- moriarty/assets/modules/social/trakt.yaml +28 -0
- moriarty/assets/modules/social/wattpad.yaml +32 -0
- moriarty/assets/modules/social/wordpress-com.yaml +26 -0
- moriarty/assets/modules/sports/espn.yaml +26 -0
- moriarty/assets/modules/sports/untappd.yaml +32 -0
- moriarty/assets/modules/stackoverflow.yaml +47 -0
- moriarty/assets/modules/steam.yaml +47 -0
- moriarty/assets/modules/streaming/caffeine.yaml +25 -0
- moriarty/assets/modules/streaming/dlive.yaml +27 -0
- moriarty/assets/modules/streaming/trovo.yaml +25 -0
- moriarty/assets/modules/travel/airbnb.yaml +26 -0
- moriarty/assets/modules/travel/booking.yaml +26 -0
- moriarty/assets/modules/travel/couchsurfing.yaml +27 -0
- moriarty/assets/modules/travel/tripadvisor.yaml +32 -0
- moriarty/assets/modules/tumblr.yaml +40 -0
- moriarty/assets/modules/twitch.yaml +48 -0
- moriarty/assets/modules/twitter.yaml +39 -0
- moriarty/assets/modules/youtube.yaml +42 -0
- moriarty/assets/templates/cves/CVE-2017-5638.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2018-7600.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2019-11510.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2019-19781.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14882.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14883.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2020-3452.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-5902.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-21972.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2021-21985.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-26084.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2021-41773.yaml +25 -0
- moriarty/assets/templates/cves/CVE-2021-42013.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-44228.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2022-0185.yaml +21 -0
- moriarty/assets/templates/cves/CVE-2022-1388.yaml +36 -0
- moriarty/assets/templates/cves/CVE-2022-22954.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2022-22965.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2022-26134.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22515.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22527.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2023-23752.yaml +33 -0
- moriarty/assets/templates/cves/CVE-2023-27350.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-2868.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-34362.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-3519.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2023-4966.yaml +27 -0
- moriarty/assets/templates/default-logins/admin-weak.yaml +40 -0
- moriarty/assets/templates/default-logins/wordpress-default.yaml +38 -0
- moriarty/assets/templates/exposures/aws-credentials.yaml +35 -0
- moriarty/assets/templates/exposures/backup-files.yaml +36 -0
- moriarty/assets/templates/exposures/database-files.yaml +34 -0
- moriarty/assets/templates/exposures/docker-exposed.yaml +31 -0
- moriarty/assets/templates/exposures/env-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/git-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/phpinfo.yaml +36 -0
- moriarty/assets/templates/exposures/svn-exposed.yaml +28 -0
- moriarty/assets/templates/fuzzing/api-endpoints.yaml +39 -0
- moriarty/assets/templates/fuzzing/common-files.yaml +37 -0
- moriarty/assets/templates/fuzzing/open-redirect-fuzz.yaml +35 -0
- moriarty/assets/templates/fuzzing/xss-search-fuzz.yaml +29 -0
- moriarty/assets/templates/git-config.yaml +18 -0
- moriarty/assets/templates/misconfigurations/cors-misconfiguration.yaml +30 -0
- moriarty/assets/templates/misconfigurations/debug-enabled.yaml +29 -0
- moriarty/assets/templates/misconfigurations/directory-listing.yaml +33 -0
- moriarty/assets/templates/misconfigurations/jwt-none-algo.yaml +30 -0
- moriarty/assets/templates/misconfigurations/ssl-tls-weak.yaml +23 -0
- moriarty/assets/templates/vulnerabilities/lfi-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/open-redirect.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/rce-basic.yaml +34 -0
- moriarty/assets/templates/vulnerabilities/sqli-error.yaml +39 -0
- moriarty/assets/templates/vulnerabilities/ssrf-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/xss-reflected.yaml +38 -0
- moriarty/assets/templates/vulnerabilities/xxe-basic.yaml +30 -0
- moriarty/assets/wordlists/subdomains-1000.txt +1063 -0
- moriarty/cli/__init__.py +3 -0
- moriarty/cli/app.py +120 -0
- moriarty/cli/async_utils.py +19 -0
- moriarty/cli/dns.py +83 -0
- moriarty/cli/domain_cmd.py +572 -0
- moriarty/cli/email.py +383 -0
- moriarty/cli/email_investigate.py +224 -0
- moriarty/cli/intelligence.py +329 -0
- moriarty/cli/output.py +62 -0
- moriarty/cli/rdap.py +94 -0
- moriarty/cli/state.py +38 -0
- moriarty/cli/tls.py +91 -0
- moriarty/cli/user.py +227 -0
- moriarty/core/cache_backend.py +223 -0
- moriarty/core/config_manager.py +303 -0
- moriarty/correlator/__init__.py +0 -0
- moriarty/data/__init__.py +81 -0
- moriarty/data/ioc/__init__.py +142 -0
- moriarty/data/ioc/matcher.py +254 -0
- moriarty/data/ioc/types.py +267 -0
- moriarty/data/local_intelligence.py +507 -0
- moriarty/data/signature_loaders/__init__.py +103 -0
- moriarty/data/signature_loaders/base.py +54 -0
- moriarty/data/signature_loaders/ioc_feed.py +356 -0
- moriarty/data/signature_loaders/wappalyzer.py +112 -0
- moriarty/dsl/__init__.py +0 -0
- moriarty/dsl/loader.py +99 -0
- moriarty/dsl/schema.py +47 -0
- moriarty/export/__init__.py +0 -0
- moriarty/intelligence/__init__.py +27 -0
- moriarty/intelligence/__main__.py +150 -0
- moriarty/intelligence/config.py +395 -0
- moriarty/intelligence/ioc.py +267 -0
- moriarty/intelligence/signatures.py +550 -0
- moriarty/intelligence/storage.py +501 -0
- moriarty/interop/__init__.py +0 -0
- moriarty/logging/__init__.py +0 -0
- moriarty/logging/config.py +47 -0
- moriarty/models/__init__.py +16 -0
- moriarty/models/assertion.py +24 -0
- moriarty/models/entity.py +22 -0
- moriarty/models/evidence.py +37 -0
- moriarty/models/relation.py +24 -0
- moriarty/models/types.py +28 -0
- moriarty/modules/__init__.py +0 -0
- moriarty/modules/avatar_hash.py +184 -0
- moriarty/modules/directory_fuzzer.py +322 -0
- moriarty/modules/dns_scan.py +40 -0
- moriarty/modules/domain_scanner.py +620 -0
- moriarty/modules/email_check.py +98 -0
- moriarty/modules/email_investigate.py +267 -0
- moriarty/modules/email_security.py +274 -0
- moriarty/modules/googlemaps_lookup.py +106 -0
- moriarty/modules/headless_executor.py +201 -0
- moriarty/modules/orchestrator.py +60 -0
- moriarty/modules/passive_recon.py +444 -0
- moriarty/modules/phone_extractor.py +151 -0
- moriarty/modules/pipeline_orchestrator.py +726 -0
- moriarty/modules/port_scanner.py +129 -0
- moriarty/modules/rdap.py +61 -0
- moriarty/modules/rdap_extended.py +188 -0
- moriarty/modules/stealth_mode.py +610 -0
- moriarty/modules/subdomain_discovery.py +595 -0
- moriarty/modules/technology_profiler.py +361 -0
- moriarty/modules/template_executor.py +239 -0
- moriarty/modules/template_scanner.py +1048 -0
- moriarty/modules/tls_scan.py +46 -0
- moriarty/modules/tls_validator.py +188 -0
- moriarty/modules/vuln_scanner.py +483 -0
- moriarty/modules/waf_detector.py +585 -0
- moriarty/modules/wayback_discovery.py +234 -0
- moriarty/modules/web_crawler.py +163 -0
- moriarty/net/__init__.py +0 -0
- moriarty/net/dns_cache.py +175 -0
- moriarty/net/dns_client.py +188 -0
- moriarty/net/rdap_client.py +52 -0
- moriarty/net/smtp_client.py +114 -0
- moriarty/net/tls_client.py +111 -0
- moriarty/parsers/__init__.py +0 -0
- moriarty/parsers/html_parser.py +136 -0
- moriarty/tests/__init__.py +0 -0
- moriarty/tests/test_email_service.py +17 -0
- moriarty/tests/test_models.py +46 -0
- moriarty/tests/test_orchestrator.py +30 -0
- moriarty/tests/test_tls_client.py +18 -0
- moriarty_project-0.1.6.dist-info/METADATA +388 -0
- moriarty_project-0.1.6.dist-info/RECORD +418 -0
- moriarty_project-0.1.6.dist-info/WHEEL +4 -0
- moriarty_project-0.1.6.dist-info/entry_points.txt +2 -0
moriarty/cli/user.py
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
|
+
import re
|
6
|
+
|
7
|
+
import typer
|
8
|
+
import httpx
|
9
|
+
from rich import box
|
10
|
+
from rich.table import Table
|
11
|
+
|
12
|
+
from .async_utils import run_async
|
13
|
+
from .output import console, emit_json, emit_yaml, ensure_state
|
14
|
+
from ..dsl.loader import TemplateLoader
|
15
|
+
from ..modules.template_executor import ExecutionResult, TemplateExecutor
|
16
|
+
|
17
|
+
app = typer.Typer(add_completion=False, help="Enumeração de usernames.")
|
18
|
+
|
19
|
+
|
20
|
+
@app.command("enum")
|
21
|
+
def enum(
|
22
|
+
ctx: typer.Context,
|
23
|
+
username: str = typer.Option(..., "--username", "-u", help="Username a pesquisar."),
|
24
|
+
sites: str = typer.Option("top20", help="Sites: top20, all, tag:X, ou caminho para .yml"),
|
25
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
26
|
+
retry: int = typer.Option(0, min=0, help="Tentativas de retry por site."),
|
27
|
+
nsfw: bool = typer.Option(False, "--nsfw", help="Include checking of NSFW sites from default list."),
|
28
|
+
print_all: bool = typer.Option(False, "--print-all", help="Output sites where the username was not found."),
|
29
|
+
print_found: bool = typer.Option(False, "--print-found", help="Output sites where the username was found."),
|
30
|
+
timeout_override: Optional[float] = typer.Option(None, "--timeout", help="Time (in seconds) to wait for response to requests."),
|
31
|
+
) -> None:
|
32
|
+
"""Enumera username em múltiplos sites."""
|
33
|
+
import logging
|
34
|
+
|
35
|
+
state = ensure_state(ctx)
|
36
|
+
|
37
|
+
# Override timeout se especificado
|
38
|
+
if timeout_override is not None:
|
39
|
+
state.options.timeout = timeout_override
|
40
|
+
|
41
|
+
# Suprime logs INFO/WARNING de bibliotecas externas
|
42
|
+
if not state.options.verbose:
|
43
|
+
logging.getLogger("httpx").setLevel(logging.ERROR)
|
44
|
+
logging.getLogger("httpcore").setLevel(logging.ERROR)
|
45
|
+
logging.getLogger("moriarty.modules.template_executor").setLevel(logging.ERROR)
|
46
|
+
|
47
|
+
# Carrega templates
|
48
|
+
loader = TemplateLoader()
|
49
|
+
loader.load_builtin()
|
50
|
+
|
51
|
+
# Filtra templates
|
52
|
+
if sites == "all":
|
53
|
+
templates = loader.list_templates()
|
54
|
+
elif sites == "top20":
|
55
|
+
templates = loader.list_templates(tag="top20")
|
56
|
+
elif sites.startswith("tag:"):
|
57
|
+
tag = sites[4:]
|
58
|
+
templates = loader.list_templates(tag=tag)
|
59
|
+
else:
|
60
|
+
# Caminho para arquivo/diretório
|
61
|
+
from pathlib import Path
|
62
|
+
path = Path(sites)
|
63
|
+
if path.is_file():
|
64
|
+
templates = [loader.load_from_path(path)]
|
65
|
+
elif path.is_dir():
|
66
|
+
templates = loader.load_from_directory(path)
|
67
|
+
else:
|
68
|
+
raise typer.BadParameter(f"Invalid sites specification: {sites}")
|
69
|
+
|
70
|
+
# Filtra templates
|
71
|
+
# 1. Filtra habilitados
|
72
|
+
templates = [t for t in templates if t.enabled]
|
73
|
+
|
74
|
+
# 2. Filtra headless se necessário
|
75
|
+
if state.options.headless == "never":
|
76
|
+
templates = [t for t in templates if not t.require_headless]
|
77
|
+
|
78
|
+
# 3. Filtra NSFW se não solicitado
|
79
|
+
if not nsfw:
|
80
|
+
templates = [t for t in templates if not t.nsfw]
|
81
|
+
|
82
|
+
if not templates:
|
83
|
+
console.print("[warning]Nenhum template encontrado para executar.")
|
84
|
+
return
|
85
|
+
|
86
|
+
allowed_vars = {"username"}
|
87
|
+
templates = _filter_templates_by_variables(templates, allowed_vars)
|
88
|
+
|
89
|
+
console.print(f"[info]🔎 Buscando username em {len(templates)} sites...")
|
90
|
+
console.print()
|
91
|
+
|
92
|
+
# Executa com spinner
|
93
|
+
with console.status("[cyan]Verificando perfis...", spinner="dots"):
|
94
|
+
cookie_store: Dict[str, httpx.Cookies] = {}
|
95
|
+
executor = TemplateExecutor(timeout=state.options.timeout, cookie_store=cookie_store)
|
96
|
+
results = run_async(_execute_all(executor, templates, username, state.options.concurrency))
|
97
|
+
|
98
|
+
# Saída
|
99
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
100
|
+
|
101
|
+
# Filtra resultados para exibição
|
102
|
+
if print_found:
|
103
|
+
# Mostra apenas encontrados
|
104
|
+
filtered_results = [r for r in results if r.exists]
|
105
|
+
elif print_all:
|
106
|
+
# Mostra todos (padrão se nenhum filtro)
|
107
|
+
filtered_results = results
|
108
|
+
else:
|
109
|
+
# Mostra todos por padrão
|
110
|
+
filtered_results = results
|
111
|
+
|
112
|
+
if output_format == "json":
|
113
|
+
payload = _results_to_dict(filtered_results, username)
|
114
|
+
emit_json(payload, json_output, state.options.output)
|
115
|
+
elif output_format == "yaml":
|
116
|
+
payload = _results_to_dict(filtered_results, username)
|
117
|
+
emit_yaml(payload, json_output, state.options.output)
|
118
|
+
else:
|
119
|
+
_render_table(filtered_results, username, show_not_found=print_all or not print_found)
|
120
|
+
|
121
|
+
|
122
|
+
async def _execute_all(
|
123
|
+
executor: TemplateExecutor,
|
124
|
+
templates: List[Any],
|
125
|
+
username: str,
|
126
|
+
concurrency: int,
|
127
|
+
) -> List[ExecutionResult]:
|
128
|
+
"""Executa todos os templates concorrentemente."""
|
129
|
+
semaphore = asyncio.Semaphore(concurrency)
|
130
|
+
|
131
|
+
async def bounded_execute(template: Any) -> ExecutionResult:
|
132
|
+
async with semaphore:
|
133
|
+
return await executor.execute(template, {"username": username})
|
134
|
+
|
135
|
+
tasks = [bounded_execute(t) for t in templates]
|
136
|
+
return await asyncio.gather(*tasks)
|
137
|
+
|
138
|
+
|
139
|
+
def _render_table(results: List[ExecutionResult], username: str, show_not_found: bool = True) -> None:
|
140
|
+
"""Renderiza resultados em tabela."""
|
141
|
+
table = Table(title=f"Username Enumeration · {username}", box=box.SIMPLE_HEAVY)
|
142
|
+
table.add_column("Site", style="cyan", no_wrap=True)
|
143
|
+
table.add_column("Exists", style="white", no_wrap=True)
|
144
|
+
table.add_column("Confidence", style="white", no_wrap=True)
|
145
|
+
table.add_column("Extracted", style="dim")
|
146
|
+
table.add_column("URL", style="blue", overflow="fold")
|
147
|
+
|
148
|
+
# Ordena por exists e confidence
|
149
|
+
sorted_results = sorted(results, key=lambda r: (r.exists, r.confidence), reverse=True)
|
150
|
+
|
151
|
+
for result in sorted_results:
|
152
|
+
# Pula não encontrados se show_not_found=False
|
153
|
+
if not show_not_found and not result.exists:
|
154
|
+
continue
|
155
|
+
|
156
|
+
exists_icon = "✓" if result.exists else "✗"
|
157
|
+
exists_color = "green" if result.exists else "dim"
|
158
|
+
|
159
|
+
confidence_str = f"{result.confidence:.2f}"
|
160
|
+
|
161
|
+
extracted_str = ", ".join(f"{k}={v}" for k, v in result.extracted.items()) if result.extracted else "—"
|
162
|
+
|
163
|
+
table.add_row(
|
164
|
+
result.site,
|
165
|
+
f"[{exists_color}]{exists_icon}[/{exists_color}]",
|
166
|
+
confidence_str,
|
167
|
+
extracted_str,
|
168
|
+
result.url,
|
169
|
+
)
|
170
|
+
|
171
|
+
console.print(table)
|
172
|
+
|
173
|
+
# Estatísticas
|
174
|
+
total = len(results)
|
175
|
+
found = sum(1 for r in results if r.exists)
|
176
|
+
console.print(f"\n[info]Total: {total} sites · Found: {found} ({found/total*100:.1f}%)")
|
177
|
+
|
178
|
+
|
179
|
+
def _results_to_dict(results: List[ExecutionResult], username: str) -> Dict[str, Any]:
|
180
|
+
"""Converte resultados para dict."""
|
181
|
+
return {
|
182
|
+
"username": username,
|
183
|
+
"total_sites": len(results),
|
184
|
+
"found_count": sum(1 for r in results if r.exists),
|
185
|
+
"results": [
|
186
|
+
{
|
187
|
+
"site": r.site,
|
188
|
+
"url": r.url,
|
189
|
+
"exists": r.exists,
|
190
|
+
"confidence": r.confidence,
|
191
|
+
"extracted": r.extracted,
|
192
|
+
"page_hash": r.page_hash,
|
193
|
+
"latency_ms": r.latency_ms,
|
194
|
+
"status_code": r.status_code,
|
195
|
+
"error": r.error,
|
196
|
+
}
|
197
|
+
for r in results
|
198
|
+
],
|
199
|
+
}
|
200
|
+
|
201
|
+
|
202
|
+
_PLACEHOLDER_PATTERN = re.compile(r"\{([a-zA-Z0-9_]+)\}")
|
203
|
+
|
204
|
+
|
205
|
+
def _filter_templates_by_variables(templates: List[Any], allowed: set[str]) -> List[Any]:
|
206
|
+
filtered: List[Any] = []
|
207
|
+
for template in templates:
|
208
|
+
placeholders = _collect_placeholders(template)
|
209
|
+
if placeholders - allowed:
|
210
|
+
continue
|
211
|
+
filtered.append(template)
|
212
|
+
return filtered
|
213
|
+
|
214
|
+
|
215
|
+
def _collect_placeholders(template: Any) -> set[str]:
|
216
|
+
values = [template.url_template]
|
217
|
+
values.extend(template.headers.values())
|
218
|
+
if template.body:
|
219
|
+
values.append(str(template.body))
|
220
|
+
placeholders: set[str] = set()
|
221
|
+
for value in values:
|
222
|
+
for match in _PLACEHOLDER_PATTERN.findall(str(value)):
|
223
|
+
placeholders.add(match)
|
224
|
+
return placeholders
|
225
|
+
|
226
|
+
|
227
|
+
__all__ = ["app"]
|
@@ -0,0 +1,223 @@
|
|
1
|
+
"""Cache backends with LRU eviction and persistence support."""
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import pickle
|
5
|
+
import sqlite3
|
6
|
+
import time
|
7
|
+
from collections import OrderedDict
|
8
|
+
from dataclasses import dataclass
|
9
|
+
from pathlib import Path
|
10
|
+
from typing import Any, Dict, Iterable, Optional, Tuple
|
11
|
+
|
12
|
+
import structlog
|
13
|
+
|
14
|
+
logger = structlog.get_logger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class CacheRecord:
|
19
|
+
"""Representa um registro em cache."""
|
20
|
+
|
21
|
+
key: Tuple[str, str]
|
22
|
+
value: Any
|
23
|
+
expires_at: float
|
24
|
+
ttl: int
|
25
|
+
last_access: float
|
26
|
+
|
27
|
+
|
28
|
+
class BaseCacheBackend:
|
29
|
+
"""Interface base para backends de cache."""
|
30
|
+
|
31
|
+
name: str = "base"
|
32
|
+
|
33
|
+
def __init__(self):
|
34
|
+
self.metrics = {
|
35
|
+
"evictions": 0,
|
36
|
+
"writes": 0,
|
37
|
+
"reads": 0,
|
38
|
+
}
|
39
|
+
|
40
|
+
def get(self, key: Tuple[str, str]) -> Optional[CacheRecord]: # pragma: no cover - interface
|
41
|
+
raise NotImplementedError
|
42
|
+
|
43
|
+
def set(self, key: Tuple[str, str], value: Any, ttl: int) -> None: # pragma: no cover - interface
|
44
|
+
raise NotImplementedError
|
45
|
+
|
46
|
+
def delete(self, key: Tuple[str, str]) -> None:
|
47
|
+
raise NotImplementedError
|
48
|
+
|
49
|
+
def clear(self) -> None:
|
50
|
+
raise NotImplementedError
|
51
|
+
|
52
|
+
def purge_expired(self) -> None:
|
53
|
+
raise NotImplementedError
|
54
|
+
|
55
|
+
def warm(self, records: Iterable[CacheRecord]) -> None:
|
56
|
+
for record in records:
|
57
|
+
now = time.time()
|
58
|
+
remaining_ttl = int(record.expires_at - now)
|
59
|
+
if remaining_ttl > 0:
|
60
|
+
self.set(record.key, record.value, remaining_ttl)
|
61
|
+
|
62
|
+
def stats(self) -> Dict[str, Any]:
|
63
|
+
return {"backend": self.name, **self.metrics}
|
64
|
+
|
65
|
+
|
66
|
+
class MemoryCacheBackend(BaseCacheBackend):
|
67
|
+
"""Cache em memória com política LRU."""
|
68
|
+
|
69
|
+
name = "memory"
|
70
|
+
|
71
|
+
def __init__(self, max_size: int, eviction_policy: str = "lru"):
|
72
|
+
super().__init__()
|
73
|
+
self.max_size = max_size
|
74
|
+
self.eviction_policy = eviction_policy.lower()
|
75
|
+
self._store: OrderedDict[Tuple[str, str], CacheRecord] = OrderedDict()
|
76
|
+
|
77
|
+
def get(self, key: Tuple[str, str]) -> Optional[CacheRecord]:
|
78
|
+
record = self._store.get(key)
|
79
|
+
if not record:
|
80
|
+
return None
|
81
|
+
|
82
|
+
if record.expires_at <= time.time():
|
83
|
+
self._store.pop(key, None)
|
84
|
+
return None
|
85
|
+
|
86
|
+
if self.eviction_policy == "lru":
|
87
|
+
self._store.move_to_end(key)
|
88
|
+
|
89
|
+
record.last_access = time.time()
|
90
|
+
self.metrics["reads"] += 1
|
91
|
+
return record
|
92
|
+
|
93
|
+
def set(self, key: Tuple[str, str], value: Any, ttl: int) -> None:
|
94
|
+
expires_at = time.time() + ttl
|
95
|
+
record = CacheRecord(key=key, value=value, expires_at=expires_at, ttl=ttl, last_access=time.time())
|
96
|
+
self._store[key] = record
|
97
|
+
if self.eviction_policy == "lru":
|
98
|
+
self._store.move_to_end(key)
|
99
|
+
self.metrics["writes"] += 1
|
100
|
+
self._evict_if_needed()
|
101
|
+
|
102
|
+
def delete(self, key: Tuple[str, str]) -> None:
|
103
|
+
self._store.pop(key, None)
|
104
|
+
|
105
|
+
def clear(self) -> None:
|
106
|
+
self._store.clear()
|
107
|
+
|
108
|
+
def purge_expired(self) -> None:
|
109
|
+
now = time.time()
|
110
|
+
expired_keys = [key for key, record in self._store.items() if record.expires_at <= now]
|
111
|
+
for key in expired_keys:
|
112
|
+
self._store.pop(key, None)
|
113
|
+
|
114
|
+
def _evict_if_needed(self) -> None:
|
115
|
+
while len(self._store) > self.max_size > 0:
|
116
|
+
key, _ = self._store.popitem(last=False)
|
117
|
+
self.metrics["evictions"] += 1
|
118
|
+
|
119
|
+
|
120
|
+
class SQLiteCacheBackend(BaseCacheBackend):
|
121
|
+
"""Cache persistente em SQLite com política LRU."""
|
122
|
+
|
123
|
+
name = "sqlite"
|
124
|
+
|
125
|
+
def __init__(self, db_path: Path, max_size: int):
|
126
|
+
super().__init__()
|
127
|
+
self.db_path = db_path
|
128
|
+
self.max_size = max_size
|
129
|
+
self._connection = sqlite3.connect(str(db_path), check_same_thread=False)
|
130
|
+
self._connection.execute(
|
131
|
+
"""
|
132
|
+
CREATE TABLE IF NOT EXISTS cache (
|
133
|
+
cache_key TEXT PRIMARY KEY,
|
134
|
+
value BLOB NOT NULL,
|
135
|
+
expires_at REAL NOT NULL,
|
136
|
+
last_access REAL NOT NULL,
|
137
|
+
ttl INTEGER NOT NULL
|
138
|
+
)
|
139
|
+
"""
|
140
|
+
)
|
141
|
+
self._connection.commit()
|
142
|
+
|
143
|
+
def get(self, key: Tuple[str, str]) -> Optional[CacheRecord]:
|
144
|
+
cursor = self._connection.execute(
|
145
|
+
"SELECT value, expires_at, last_access, ttl FROM cache WHERE cache_key = ?",
|
146
|
+
(self._serialize_key(key),),
|
147
|
+
)
|
148
|
+
row = cursor.fetchone()
|
149
|
+
if not row:
|
150
|
+
return None
|
151
|
+
|
152
|
+
value_blob, expires_at, _, ttl = row
|
153
|
+
if expires_at <= time.time():
|
154
|
+
self.delete(key)
|
155
|
+
return None
|
156
|
+
|
157
|
+
value = pickle.loads(value_blob)
|
158
|
+
record = CacheRecord(
|
159
|
+
key=key,
|
160
|
+
value=value,
|
161
|
+
expires_at=expires_at,
|
162
|
+
ttl=ttl,
|
163
|
+
last_access=time.time(),
|
164
|
+
)
|
165
|
+
self._connection.execute(
|
166
|
+
"UPDATE cache SET last_access = ? WHERE cache_key = ?",
|
167
|
+
(record.last_access, self._serialize_key(key)),
|
168
|
+
)
|
169
|
+
self._connection.commit()
|
170
|
+
self.metrics["reads"] += 1
|
171
|
+
return record
|
172
|
+
|
173
|
+
def set(self, key: Tuple[str, str], value: Any, ttl: int) -> None:
|
174
|
+
expires_at = time.time() + ttl
|
175
|
+
blob = pickle.dumps(value)
|
176
|
+
last_access = time.time()
|
177
|
+
self._connection.execute(
|
178
|
+
"REPLACE INTO cache (cache_key, value, expires_at, last_access, ttl) VALUES (?, ?, ?, ?, ?)",
|
179
|
+
(self._serialize_key(key), blob, expires_at, last_access, ttl),
|
180
|
+
)
|
181
|
+
self._connection.commit()
|
182
|
+
self.metrics["writes"] += 1
|
183
|
+
self._evict_if_needed()
|
184
|
+
|
185
|
+
def delete(self, key: Tuple[str, str]) -> None:
|
186
|
+
self._connection.execute(
|
187
|
+
"DELETE FROM cache WHERE cache_key = ?",
|
188
|
+
(self._serialize_key(key),),
|
189
|
+
)
|
190
|
+
self._connection.commit()
|
191
|
+
|
192
|
+
def clear(self) -> None:
|
193
|
+
self._connection.execute("DELETE FROM cache")
|
194
|
+
self._connection.commit()
|
195
|
+
|
196
|
+
def purge_expired(self) -> None:
|
197
|
+
now = time.time()
|
198
|
+
self._connection.execute("DELETE FROM cache WHERE expires_at <= ?", (now,))
|
199
|
+
self._connection.commit()
|
200
|
+
|
201
|
+
def warm(self, records: Iterable[CacheRecord]) -> None:
|
202
|
+
for record in records:
|
203
|
+
remaining_ttl = int(record.expires_at - time.time())
|
204
|
+
if remaining_ttl > 0:
|
205
|
+
self.set(record.key, record.value, remaining_ttl)
|
206
|
+
|
207
|
+
def _serialize_key(self, key: Tuple[str, str]) -> str:
|
208
|
+
return "|".join(key)
|
209
|
+
|
210
|
+
def _evict_if_needed(self) -> None:
|
211
|
+
if self.max_size <= 0:
|
212
|
+
return
|
213
|
+
cursor = self._connection.execute("SELECT COUNT(*) FROM cache")
|
214
|
+
count = cursor.fetchone()[0]
|
215
|
+
if count <= self.max_size:
|
216
|
+
return
|
217
|
+
overflow = count - self.max_size
|
218
|
+
self._connection.execute(
|
219
|
+
"DELETE FROM cache WHERE cache_key IN (SELECT cache_key FROM cache ORDER BY last_access ASC LIMIT ?)",
|
220
|
+
(overflow,),
|
221
|
+
)
|
222
|
+
self._connection.commit()
|
223
|
+
self.metrics["evictions"] += overflow
|