{
    "version": "https://jsonfeed.org/version/1",
    "title": "Blog -- mari.zip",
    "home_page_url": "https://mari.zip/blog",
    "feed_url": "https://mari.zip/feed/feed.json",
    "description": "strangely quiet here without you",
    "author": {
        "name": "Mari (mellowagain)",
        "url": "https://mari.zip"
    },
    "items": [
        {
            "id": "call-for-rust-2020",
            "content_html": "\n\n\nRust is a programming language I genuinly love. Seeing so much community involvement in a language which has great\nprinciples such as great performance and guaranteed memory-safety - right at compile time - is amazing and refreshing.\nSo after having found out that [the Rust team asked for opinions on Rust 2020](https://blog.rust-lang.org/2019/10/29/A-call-for-blogs-2020.html),\nI saw my opportunity to take part in this community and maybe even shape the future of Rust.\n\n## Scratching the bottom of the barrel\n\nHaving used Rust in only [one public project](https://github.com/mellowagain/kyo-rs), I am somewhat of a newbie. Still,\nI have some wishes for Rust in 2020 and maybe even beyond:\n\n* [Newcomer Accessability](#newcomer-accessability)\n* [Improved Compile times](#improved-compile-times)\n* [More mature ecosystem](#more-mature-ecosystem)\n\n## Newcomer Accessability\n\nRust is a weird language. Coming from a background in Java and C++, I've struggled in Rust at first, fighting the compiler\non almost every possible occasion. Within my friend circle I've also noticed some of my friends struggeling in picking\nup Rust and wrapping their heads around some unique principles like Borrowing and Lifetimes.\n\nWhat I wish for Rust in 2020 is improved accessability for newcomers. The Rust book is great but if I'm honest, not\nsomething I could read with much understanding. Sometimes it just becomes too technical or oversimplifies.\n\nThe ways people learn languages is very different so I think we should have a few different tutorials and guides\nin how to pick up the language. Rust has the perfect community for something like this.\n\n## Improved Compile times\n\nSometimes after working on my Rust project for some time, the compiler decides to recompile all crates. Why does this happen?\nI'd love if Rust would have a explanation why this would happen (for example: Updated dependency x, recompiling everything dependent upon it)\n\nAnyhow, there has already been huge work regarding improving compile times and this is great. I wish for Rust to continue\nto improve this for 2020 and beyond.\n\n## More mature ecosystem\n\nI know this is more of a wish for the Rust ecosystem than Rust itself but I still think it has a valid place here. The whole\nRust ecosystem seems kinda, young? Looking on [crates.io](https://crates.io/), many crates have not yet reached the maturity version\nof `1.0.0` and higher. I wish that more crates would put maturity on their roadmaps in the near future.\n\nBut maybe it's also naive to think that crates should reach maturity. I like to think that Rust itself is a mature language\nbut some people disagree - thus also eliminating the wish for reaching maturity. I'd love to hear the takes of other people in the\ncommunity on this (maybe) issue.\n\n## Wrapping up\n\nOverall I don't have much for Rust. It is already a great language and loved by many people in the world, including me. I have faith\nand trust in the community for continuing to improve the language. Rust 2018 was a great improvement when it came out and I can't\nwait to see what Rust 2021 will bring with it.\n\n\n",
            "url": "https://mari.zip/blog/call-for-rust-2020",
            "title": "Call for Rust 2020",
            "summary": "The Rust Team wants community voices for Rust 2020. Let's `.unwrap()` my opinion regarding it.",
            "date_modified": "2019-11-11T00:00:00.000Z",
            "author": {
                "name": "Mari (mellowagain)",
                "url": "https://mari.zip"
            }
        },
        {
            "id": "great-things-of-2019",
            "content_html": "\n\n\nThe best of 2019 that I discovered, loved and kept close to me. This blog post is inspired by [fogus: The Best Things and Stuff of 2019](http://blog.fogus.me/2019/12/30/the-best-things-and-stuff-of-2019/). Everything is in no particular order.\n\n## Great blog posts read\n\n* [We Need Chrome No More](https://redalemeden.com/blog/2019/we-need-chrome-no-more)\n* [Public hacker test on Swiss Post’s e-voting system](https://www.evoting-blog.ch/en/pages/2019/public-hacker-test-on-swiss-post-s-e-voting-system)\n* [List of stories set in a future now past](https://en.wikipedia.org/wiki/List_of_stories_set_in_a_future_now_past)\n* [I interviewed at six top companies in Silicon Valley in six days](https://blog.usejournal.com/i-interviewed-at-six-top-companies-in-silicon-valley-in-six-days-and-stumbled-into-six-job-offers-fe9cc7bbc996)\n* [Most of What We Read on the Internet is Written by Insane People](https://www.reddit.com/r/slatestarcodex/comments/9rvroo/most_of_what_you_read_on_the_internet_is_written/)\n* [Let’s stop copying C (2016)](https://eev.ee/blog/2016/12/01/lets-stop-copying-c/)\n\n## Great articles read\n\n* [How to not be alone (2013)](https://www.nytimes.com/2013/06/09/opinion/sunday/how-not-to-be-alone.html)\n* [Coders Programming Themselves Out of a Job (2018)](https://www.theatlantic.com/technology/archive/2018/10/agents-of-automation/568795/)\n* [A Sleeping Disorder That Turns Life into a Waking Dream](https://www.nytimes.com/2019/10/02/magazine/mysterious-sleeping-disorder-diagnosis.html)\n* [SIM swap horror story: I've lost decades of data and Google won't help](https://www.zdnet.com/article/sim-swap-horror-story-ive-lost-decades-of-data-and-google-wont-lift-a-finger/)\n* [Living in Switzerland ruined me for America and its lousy work culture (2016)](https://www.vox.com/2015/7/21/8974435/switzerland-work-life-balance)\n* [The wave of unicorn IPOs](https://www.economist.com/briefing/2019/04/17/the-wave-of-unicorn-ipos-reveals-silicon-valleys-groupthink)\n* [Your digital identity has three layers, and you can only protect one of them](https://qz.com/1525661/your-digital-identity-has-three-layers-and-you-can-only-protect-one-of-them/)\n\n## Favorite podcasts listened to\n\n2019 was the year I started listening to podcasts actively. I regret not having done that much earlier, when I first found out about them.\nWell in my defense, I only subscribed to Spotify Premium this year (even thought it's not the only way to listen to these!)\n\n* [Startup](https://gimletmedia.com/shows/startup) - *I loved the episodes about Gimlet, the company that created this podcast. It is a genuine great and emotional adventure about the journey of creating a startup and I enjoyed every second of it. I binged all episodes about Gimlet in less than a month.*\n* [Reply All](https://gimletmedia.com/shows/reply-all) - *I found out about this podcast from Waveform (the one below) and the stories told are seriously great.*\n* [Waveform](https://open.spotify.com/show/6o81QuW22s5m2nfcXWjucc) - *In-depth discussions about the latest tech from MKBHD, the largest technology channel on YouTube. Having high expectations when this was announced, I was not disappointed when I actually listened to it.*\n\n## Favorite musicians discovered\n\nAll artists here are in the Lo-Fi genre. It is my favorite music genre and I listen to it almost exclusively, both at home and on my almost daily public transport rides\nto work/school.\n\n* [City Girl](https://twitter.com/citygirltime) - *I love that almost every song has a story behind it which completes the City Girl character.*\n* [Dontcry](https://open.spotify.com/artist/3vzJueN7TkCtYpz1myVmDU)\n\n## Favorite shows discovered\n\n* [A Place Further Than The Universe](https://anilist.co/anime/99426/A-Place-Further-Than-the-Universe/)\n* [Gabriel Dropout](https://anilist.co/anime/21878/Gabriel-DropOut/)\n* [Hibike Euphonium](https://anilist.co/anime/20912/Sound-Euphonium/)\n* [I Want to Eat Your Pancreas](https://anilist.co/anime/99750/I-Want-to-Eat-Your-Pancreas/)\n* [K-ON!](https://anilist.co/anime/5680/KON/)\n* [Kaguya-sama: Love is War](https://anilist.co/anime/101921/Kaguyasama-Love-is-War/)\n* [The Pet Girl of Sakurasou](https://anilist.co/anime/13759/The-Pet-Girl-of-Sakurasou/)\n\n## Favorite games discovered\n\n* [Muse Dash (Android)](https://play.google.com/store/apps/details?id=com.prpr.musedash&hl=en)\n* [Cytus II (Android)](https://play.google.com/store/apps/details?id=com.rayark.cytus2&hl=en)\n* [Overwatch (PC)](https://playoverwatch.com/en-us/)\n* [Business Tour (PC)](https://store.steampowered.com/app/397900/Business_Tour__Board_Game_with_Online_Multiplayer/)\n* [Anxiety: An Interactive Story (Web)](https://ncase.me/anxiety-demo/) - *A interactive game where YOU play as the anxiety. Small demo that I really enjoyed. Looking forward to the actual game!*\n\n## Countries visited\n\nFor the first time in:\n\n* Qatar\n* United Kingdom\n\nVisited again:\n\n* Germany\n* Philippines\n\n## Great tools discovered\n\nEverything from apps, platforms, extensions etc. that I discovered in 2019 and use (almost) daily.\n\n* [Spotify Premium](https://www.spotify.com) - *Unlimited skipping, no-ads and offline listening. Don't know how I survived 2018 with just Spotify free. Streaming is just too convient.*\n* [SponsorBlock](https://sponsor.ajay.app/) - *Automatically skips sponsor spots in YouTube videos, don't know how I was able to watch YouTube without this.*\n* [Tildes](https://tildes.net/) - *News aggregator like HN but with higher quality comments and posts. If you want an invite, just send me a tweet via Twitter, I got a few invite codes.*\n* [Neon](https://www.neon-free.ch/en/) - *Banking startup in Switzerland. Great product and easy to use app, will probably switch to it fully in the future once it IPO'd (or got acquired).*\n* [GSMArena](https://www.gsmarena.com/) - *News and information about everything smartphone related - as I'm a tech enthusiast I check it out on the daily.*\n\n## Programming languages I hacked in\n\n* [Rust](https://www.rust-lang.org/)\n* [TypeScript](https://www.typescriptlang.org/)\n* [Go](https://golang.org/)\n* [PHP](https://www.php.net/)\n\n## Tech products I bought\n\nIn order of bought starting from the beginning of 2019 until the end.\n\n* [Samsung Galaxy Watch](https://www.samsung.com/global/galaxy/galaxy-watch/) - *Having a smart watch is just too convient and I see why these days so many people in my age have one.*\n* [Sony WH-1000XM3](https://www.sony.com/electronics/headband-headphones/wh-1000xm3/buy/wh1000xm3-b) - *Active Noise Cancelling (ANC) headphones really made a huge difference. Suddenly I was actually looking forward to the almost daily public transport rides.*\n* [Logitech G Pro](https://www.logitechg.com/en-ch/products/gaming-mice/pro-hero.html) - *My old mouse stopped working after four years of use so this'll hopefully be a worthy successor.*\n* [Huawei Matebook 13](https://consumer.huawei.com/en/laptops/matebook-13/) - *Got it at a discount and honestly a great, fast and portable laptop.*\n* [Nintendo Switch](https://www.nintendo.com/switch/) - *Wanted one since the beginning of 2019 and was able to get it off on Black Friday. Really cool console which I love for its portability. Finally I can really game on the go.*\n\n## Plans for 2020\n\n* Write a blog post at least once two months.\n* Start building a portofolio on GitHub.\n* Contribute more to open-source projects.\n* Shrink my [Plan to Watch](https://myanimelist.net/animelist/mari3842h?status=6) list.\n* Pass my upcoming Cambridge CAE exam in March.\n* Pass the four month personal project we have in school in August.\n* Stop some coping mechanisms.\n\nSo let's start this year with high spirit. See you maybe for the \"Great things in 2020\" blog post.\n\n\n",
            "url": "https://mari.zip/blog/great-things-of-2019",
            "title": "Great things of 2019",
            "summary": "The best stuff that I discovered, read, watched etc and more in 2019.",
            "date_modified": "2020-01-12T00:00:00.000Z",
            "author": {
                "name": "Mari (mellowagain)",
                "url": "https://mari.zip"
            }
        },
        {
            "id": "great-things-of-2020",
            "content_html": "\n\n\nA continuation of my post [Great things of 2019](/blog/great-things-of-2019) but for 2020.\nI've switched phones in September but forgot to back up my Materialistic saved data, so I lost most cool blog posts & articles I've read.\nThus these two sections may heavily be biased towards stuff that got posted on HN in Q4 of 2020. As always, everything is in no particular order.\n\n## Great blog posts read\n\n* [My GPT-3 Blog Got 26 Thousand Visitors in 2 Weeks](https://liamp.substack.com/p/my-gpt-3-blog-got-26-thousand-visitors)\n* [Minecraft's \"Pack.png\" Seed Reversal Methodology](https://docs.google.com/document/d/1PpZqHWXPLjOsXf_T7uyH4rWuxUMxzBlxvv5gm19P_Z8/edit)\n* [How the Minecraft Title Screen Seed was Found (Video)](https://www.youtube.com/watch?v=GaRurhiK-Lk)\n* [What is the Value of Browser Diversity?](https://daverupert.com/2020/09/the-value-of-browser-diversity/)\n* [How to back up your password manager](https://www.ctrl.blog/entry/password-manager-backup.html)\n* [The HTTP headers you don't expect](https://frenxi.com/http-headers-you-dont-expect/)\n\n## Great articles read\n\n* [I had Covid-19, and these are the things nobody tells you](https://www.latimes.com/sports/story/2020-08-12/column-bill-plaschke-covid-19-experience)\n* [The Minecraft Institvte of Technology](https://www.technologyreview.com/2020/08/18/1006217/the-minecraft-institvte-of-technology/)\n* [Remote Software Developers Earn 22% More Than Non-Remote Developers](https://whoisnnamdi.com/remote-software-developers-earn-more/)\n* [Year Without a Summer](https://en.wikipedia.org/wiki/Year_Without_a_Summer) (w/ [HN discussion](https://news.ycombinator.com/item?id=22400480))\n* [SoftBank expects $24 billion in losses from Vision Fund, WeWork and OneWeb investments](https://techcrunch.com/2020/04/13/softbank-expects-24-billion-in-losses-from-vision-fund-wework-and-oneweb-investments/)\n\n## Favorite podcasts listened to\n\n* [Anime in America](https://www.crunchyroll.com/animeinamerica/index.html) - *A interesting look at the history of Anime and Manga and how it came to from Japan to the US. Despite living in Europe, some of the stuff that was mentioned seemed all too familiar.*\n* [Trash Taste Podcast](https://www.youtube.com/c/TrashTaste) - *A genuinely funny podcast by three anitubers. It features hilarious stories, trash opinions and bad takes and I've loved every minute of it. I've gotten way too many weird looks because I've started laughing out of nowhere in public transport because of this podcast.*\n\nContinued listening to:\n\n* [Reply All](https://gimletmedia.com/shows/reply-all)\n* [Waveform](https://open.spotify.com/show/6o81QuW22s5m2nfcXWjucc)\n\nI've commented on these podcasts on last year's post.\n\n## Favorite musicians discovered\n\nWhile I have discovered many new musicians in 2020, none of them have sticked with me or become a huge part of my music listening. I've mostly used Spotify's recommendation engine.\n\n## Favorite shows discovered\n\n* My Teen Romantic Comedy SNAFU ([S1](https://anilist.co/anime/14813/My-Teen-Romantic-Comedy-SNAFU/), [S2](https://anilist.co/anime/20698/My-Teen-Romantic-Comedy-SNAFU-TOO/), [S3](https://anilist.co/anime/108489/My-Teen-Romantic-Comedy-SNAFU-Climax/)) - *This show came out of nowhere and ended up being my all-time favorite series, with season three even being my highest rated anime of all time (10/10). I've **genuinly** loved every moment of this show. I highly recommend this show, especially because season 3 ends very satisfactory.*\n* [Orange](https://anilist.co/anime/21647/Orange/)\n* [Just Because!](https://anilist.co/anime/98820/Just-Because/)\n* [Carole & Tuesday](https://anilist.co/anime/101281/Carole--Tuesday/)\n* [Grand Blue](https://anilist.co/anime/100922/Grand-Blue-Dreaming/) - *This has to be the funniest anime I've ever seen. Highly recommended for having a fun time.*\n\n## Favorite games discovered\n\n* [Animal Crossing: New Horizons (Switch)](https://animal-crossing.com/new-horizons/)\n* [Cyberpunk 2077 (PC)](https://www.cyberpunk.net/ch/en/)\n* [Half Life Alyx (PC, VR)](https://www.half-life.com/en/alyx)\n* [Valorant (PC)](https://playvalorant.com/en-us/)\n\nI haven't discovered many new games in 2020. I've mostly continued playing games I already knew and loved such as Overwatch.\n\n## Countries visited\n\nBecause of the COVID-19 pandemic, I was sadly unable to visit any new countries this year. However, I was able to visit again:\n\n* Germany\n\nIt was just a day trip, a quick hop over the border basically. No, I did not catch covid (as far as I know).\n\n## Great tools discovered\n\nEverything from apps, platforms, extensions and more that I discovered in 2020 and use (almost) daily.\n\n* [KDEConnect](https://kdeconnect.kde.org/) / [GSConnect](https://extensions.gnome.org/extension/1319/gsconnect/) / [Your Phone](https://www.microsoft.com/en-us/p/Your-phone/9nmpj99vjbwv?activetab=pivot:overviewtab) - *I spend most of my screen time in front of my computer but I still want to receive notifications and interact with mobile apps from my desktop. These three apps (two for Linux and one for Windows) allow me to do that and it works surprisingly good.*\n* [Microsoft Todo](https://todo.microsoft.com/) - *I'm trying to organize my life a little bit better and this has helped immensely. My Samsung Reminders app automatically syncs to it.*\n* [Neat URL](https://addons.mozilla.org/en-US/firefox/addon/neat-url/) - *I love sharing links with other people but ever since the introduction of Google Analytics many urls are poised with useless arguments such as `utm_source`. This extension gets rid of them.*\n* [Nebula](https://watchnebula.com/) - *Nebula is a independent streaming site which hosts videos from my favorite YouTubers such as Wendover Productions and TechAltar. It also contains great exclusive series and documentaries. It is very cheap and supports your favorite creators directly, so I can highly recommend giving it a shot.*\n* [Patreon](https://patreon.com/) - *I've used Patreon in the past to receive donations for my projects but 2020 was the first year I gave money to someone else on Patreon. I've subscribed to OtakuVs to support the creation of their anime.*\n* [Samsung Notes](https://www.samsung.com/global/galaxy/apps/samsung-notes/) - *As I've gotten myself a device from the Note series, I had to use the S-Pen. And damn it's useful, mostly because of the great Samsung Notes app features and syncronization with OneNote.*\n* [Webtoons](https://www.webtoons.com/en/) - *I've discovered the world of Webtoons. You can imagine this to be some sort of modern version of Manga, optimized for reading on smartphones. I recommend True Beauty.*\n* [Windows Terminal](https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab) - *Finally a useable terminal on Windows.*\n\nThis list does not include tools that aren't exciting, such as Microsoft Teams which I used extensively in online school while there was a lockdown.\n\n## Programming languages I hacked in\n\nI didn't learn any new programming languages in 2020. I've focused more on frameworks such as Pyramid (Python) and actix (Rust).\n\n## Tech products I bought\n\n* [Samsung LC24RG50FQUXEN](https://www.samsung.com/uk/business/monitors/monitor-crg50/lc24rg50fquxen/) (February) - *Great value curved 144hz monitor. It has become my main monitor and joined my triple monitor setup.*\n* [SteelSeries Arctis 7 Wireless](https://steelseries.com/gaming-headsets/arctis-7) (April) - *God I hate wires! After having yet another headset break on me, I've decided to actually spend a triple digit amount of money to buy an actual good headset and I'm not regretting it. It has held up pretty well already and being able to walk around the apartment while gaming or listening to online school lessons is so convenient.*\n* [HyperX Fury 32 GB 3200Mhz DDR4 RAM](https://www.hyperxgaming.com/us/memory/fury-ddr4-rgb) (June) - *At the start of the year I've found that I've been hitting my 16 GB limit on my machine pretty often with all programs and games I have constantly open. The logical step was to upgrade and when digitec had a sale in June this was perfect. RAM prices really have come down since I've built my pc and I was able to buy this 32 GB kit for the price of the 16 GB kit I had in my pc since I built it in 2017.*\n* [Samsung Galaxy Note20 Ultra 5G](https://www.samsung.com/us/smartphones/galaxy-note20-5g/) (August) - *I upgrade my phone every two years, primarily because the battery wears out. I've stayed with Samsung as a phone brand as I've already bought into their ecosystem with my Galaxy Watch & Buds. Seeing the camera issues that happened with the S20 Ultra in february I couldn't allow myself to buy a phone with these issues so it had to be the newest flagshig from the Note line. I've since really grown to the pen on the phone and I use it pretty often in school.*\n* [WD Black SN750 1 TB NVMe SSD](https://shop.westerndigital.com/products/internal-drives/wd-black-sn750-nvme-ssd#WDS100T3X0C) (November) - *My 250GB SSD has become full so I had to upgrade. Thanks to a great black friday deal on Amazon, I even got myself an NVMe one.*\n* [HyperX Alloy Origins](https://www.hyperxgaming.com/us/keyboards/alloy-origins-mechanical-gaming-keyboard) (November) - *Since the start of the year I've had problems with sometimes double typing keys on my CoolerMaster Masterkeys L. I've already cleaned it and it didn't help so it was time to replace it. Black friday at Media Markt got me covered with a nice mechanical keyboard. I've found these HyperX red switches to be very much the same as the CherryMX Reds I had on the Coolermaster.*\n* [Logitech G Pro X Superlight Wireless](https://www.logitechg.com/en-us/products/gaming-mice/pro-x-superlight-wireless-mouse.html) (December) - *As already mentioned above, I've bought into the wireless hype. I was eyeing the Logitech G Pro Wireless since a few months already and when I wanted to buy it on Black Friday it wasn't discounted. Thus I've decided to spend the additional money to get the newest product of Logitech, the Superlight variant of the G Pro Wireless.*\n* [Dream Machine DM Pad XL](https://www.dreammachines.io/en/dmpadxl) (December) - *With a new mouse we also need a new mouse pad, right? On the long term I'm planning to replace this with a Artisan mousepad so it'll probably not stay for very long.*\n\nA few comments about the tech I bought in 2019:\n\n* Buying a [Samsung Galaxy Watch](https://www.samsung.com/global/galaxy/galaxy-watch/) in 2019 might've been one of the best decisions I could've made. Once COVID-19 took over our lives, it was recommended not to touch surfaces because of fears of catching the virus. My smartwatch allowed me to see notifications directly on my wrist without having to take out my phone and touch it.\n* Noise Cancellation of the [Sony WH-1000XM3](https://www.sony.com/electronics/headband-headphones/wh-1000xm3/buy/wh1000xm3-b) got worse after multiple updates (or maybe use?). I'm planning on replacing the ear cups to see if that makes a difference.\n* Despite a lockdown and home schooling, I wasn't able to use my [Nintendo Switch](https://www.nintendo.com/switch/) as much as I would've loved to.\n\n## Plans from 2020\n\nIn last years' article I wrote down a few plans I had. I sadly wasn't able to complete all of them:\n\n| Goal                                                              | Achieved | Comment                                                                                                                                     |\n|-------------------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------|\n| Write a blog post at least once two months.                       | No       | In fact, the only post in 2020 was the Great things of 2019 article. It is easy to blame the pandemic but I know it was just me being lazy. |\n| Start building a portofolio on GitHub.                            | Yes      | A little bit, but not completely.                                                                                                           |\n| Contribute more to open-source projects.                          | Yes      | I completed Hacktoberfest 2020 for the first time.                                                                                          |\n| Shrink my Plan to Watch list.                                     | No       | It grew even more. I'm now at 126 shows (at the time of writing).                                                                           |\n| Pass my upcoming Cambridge CAE exam in March.                     | Yes      | Passed with Grade B                                                                                                                         |\n| Pass the four month personal project we have in school in August. | Yes      | Passed with 4.5                                                                                                                             |\n| Stop some coping mechanisms.                                      | No       |                                                                                                                                             |\n\nThat is 4 out 7 goals achieved or a 57.14% success rate.\n\n## Plans for 2021\n\nIn addition of trying to complete last years' goals, I'd like to:\n\n* Pass ending exams for my apprenticeship\n* Get a new job when my contract ends in August\n* Get my drivers license\n* Get into investing and the stock market\n\n\n",
            "url": "https://mari.zip/blog/great-things-of-2020",
            "title": "Great things of 2020",
            "summary": "2020 was not a year most people would call great but that doesn't mean there wasn't great stuff I've discovered, read or watched.",
            "date_modified": "2021-01-31T00:00:00.000Z",
            "author": {
                "name": "Mari (mellowagain)",
                "url": "https://mari.zip"
            }
        },
        {
            "id": "isolated-dev-environments",
            "content_html": "\n\n\nThe past few months have not been the best for developers. There has been too many supply chain attacks, targeting not\njust the NPM ecosystem but also the Cargo ecosystem as well as GitHub actions:\n\n- [The Shai-Hulud 2.0 npm worm](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/)\n- [GitLab discovers widespread npm supply chain attack](https://about.gitlab.com/blog/gitlab-discovers-widespread-npm-supply-chain-attack/)\n- [Malicious Rust Packages Hit crates.io](https://www.abhs.in/blog/rust-crates-io-supply-chain-attack-developer-credentials-2026)\n- [Ghostaction: 3,325 Secrets Stolen Through Compromised GitHub Workflows](https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen/)\n\nThis recent uptick of attacks and self-propagating worms is scary, and it means we have to start taking security more\nseriously as developers. I have looked around and found [`litterbox`](https://litterbox.work/), a Linux sandbox environment\ncatered to the needs of developers. While it is in early stage, I decided to give it a try and it was surprisingly easy.\n\n## What litterbox is and what it isn't\n\nBefore using any tool, it's good to get a sense of what it does and what it doesn't. Notably, Litterbox is not a full\nvirtual machine, instead running inside of rootless Podman containers with only access to a dedicated home folder\n(located in `~/Litterbox/homes/<container name>`) and nothing above it. It also features a special SSH agent, showing a\nGUI prompt every time a program wants to use your SSH key. See the appendix the end of the article for a screenshot of that.\n\nMore importantly, it is **not a virtual machine**. This means that all programs still run on your original OS' kernel and\nyour native Wayland server. This is especially bad because having access to the Wayland server means also having access\nto your global clipboard, a limitation that you sadly are not able to work around (for now, I hope).\n\nOf course if there is an exploit in the Linux kernel or anything that is exposed to the Litterbox (including Wayland and\nany devices you explicitly attached with `litterbox devices`), that can then also be exploited. But recent supply chain attacks have\nmostly been trying to get your credentials to stuff like Git, NPM, crates.io etc. so this provides a good shield\nagainst that. Read all about the limitations of Litterbox on its [README](https://github.com/Gerharddc/litterbox?tab=readme-ov-file#isolation-limitations).\n\n## My development environment\n\nSo let's get ready to set up a Litterbox. I have decided to have **one litterbox per project**. This gives the best\nisolation between projects but at the expense of disk space, as all runtimes, dependencies and IDE's need to be\ninstalled in every litterbox separately. That is a trade-off I am willing to make for the sake of security. You can\nchoose to instead define a litterbox per-language or however you see fit.\n\nI'm going to set up a container for this very website, [mari.zip](https://github.com/mellowagain/website) so we need:\n\n* `nodejs`, as my project is a Next.js app\n* `pnpm`, the projects default package manager\n* `WebStorm`, the JetBrains IDE of choice for Node web development\n* A new ssh key for the litterbox\n\nThis list is different per-project, for example for [GitArena](https://github.com/mellowagain/gitarena) I installed `cargo`\nand `RustRover` instead.\n\n## Installing litterbox\n\nInstalling it is as simple as running:\n\n```bash\ncurl -fsSL https://litterbox.work/install.sh | sh\n```\n\nThis will install the latest litterbox version **for your local user**, in my case `litterbox 0.3.2`. Explicitly not\nsystem-wide, as it should be. Of course, you can critique the old curl and then pipe into bash, but if you're like that\nit seems that litterbox is easy to compile by yourself, being fully written in Rust.\n\n## Creating the litterbox\n\nCreating the litterbox is a simple two-step progress, first defining it and then building the container. For the\nname I have chosen marizip to represent the project that is inside of it.\n\n```bash\nlitterbox define marizip\n```\n\nIt will then ask you for a template, I picked `CachyOS` becaue my main system is Arch so the commands are similiar enough\nto not get mixed up between main system and container. There is an argument to be had to explicitly use a different distro\nfor your container to always be sure you're running commands in the correct environment, but I decided against it.\n\nNext up we need to build the litterbox:\n\n```bash\nlitterbox build marizip\n```\n\nIt will prompt you to set a user password. I have Bitwarden as my password manager, so I generate a new, unique password\nfor all of my litterboxes.\n\nAfterwards it will ask you a lot of questions, these are **very important** to consider as after they have been defined\nyou cannot change them and would have to rebuild your litterbox if you really wanted to.\n\n## The questions\n\n### Network mode\n\n```text\n? Choose the network mode for this Litterbox:\n> Pasta (isolated user-mode networking stack)\n  Pasta with automatic port forwarding (host to container)\n  Pasta with automatic port forwarding (container to host)\n  Pasta with automatic port forwarding (bidirectional)\n  Host networking (i.e. NO ISOLATION)\n```\n\nThis should be self explaining. As mari.zip is a web app, I often use `pnpm run dev` to quickly spin up a dev server\nto see changes immediately, so I chose `Pasta with automatic port forwarding (container to host)`. Depending on your\napplications, you should choose differently. **Do not choose the last option, unless you have good reason to.**\n\n### CAP_NET_RAW\n\n```text\n? Do you want to support `ping` inside this Litterbox? (y/N)\n[This will enable `CAP_NET_RAW`.]\n```\n\nIf you're around the Kubernetes or devops world, you probably [already know of this](https://kyverno.io/policies/best-practices/require-drop-cap-net-raw/require-drop-cap-net-raw/).\n`CAP_NET_RAW` enables applications to craft and send arbitrary network packets, as used by tools like `ping` and `nmap`\nas well as binding to any network address regardless of ownership and intercepting traffic on the network interface.\n**Unless you have a specific need for it, do not enable it.**\n\n### CAP_NET_ADMIN\n\n```text\n? Do you want to support TUN/TAP creation inside this Litterbox? (y/N)\n[This will enable `CAP_NET_ADMIN` and expose `/dev/net/tun`.]\n```\n\n`CAP_NET_ADMIN` is the equivalent of granting root access to network, allowing programs to bring interfaces up and down,\nassigning IP addresses, modifying the routing table, modifying iptables rules and creating and configuring network namespaces.\nThis is mostly useful if you'd like to run an iptables firewall or a VPN daemon inside the litterbox. **Again, unless you\nhave a specific need for it, do not enable it.**\n\n### Packet forwarding\n\n```text\n? Do you want to enable packet forwarding inside this Litterbox? (y/N)\n```\n\nPacket forwarding allows programs within the litterbox to act as packet routers, routing packets from one interface\nto another. This is useful if you're running a VPN server or a proxy within the container. This is **not** however\nneeded for my use case where I just want to visit the local dev server from my main machines browser outside the container.\nThis is just for routing traffic _between_ network interfaces. **Again, unless you have a specific need for it, do not enable it.**\n\n### User groups\n\n```text\n? Do you want to keep your user groups inside this Litterbox? (y/N)\n[This will preserve your host user's group memberships.]\n```\n\nIn Linux a lot of access is managed through groups, for example `docker` (for rootless docker) or `root` (for running `sudo`).\nI found this to only really useful if you're passing in `litterbox devices` which are bound to a specific group. **It is most\ncleanly to not enable it but for your use case it might be required.** For my normal web development however, it isn't.\n\n### seccomp confinement\n\n```text\n? Do you want to disable seccomp confinement? (y/N) $\n[This enables 'dangerous' syscalls required by things like the Mojo debugger.]\n```\n\nSeccomp stands for Secure Computing Mode and is a kernel feature to filter syscalls programs can call. Confinement restricts\nthem to be the normal syscalls most programs use, but for some special ones like debuggers which use `ptrace`, you\nwould need to enable it. **Enable this if your programs need it.**\n\n### Pipewire\n\n```text\n? Do you want to expose PipeWire inside this Litterbox? (y/N)\n[This will allow audio applications to work inside the Litterbox.]\n```\n\nThis one is relatively simple. Do you need audio in your container like speaker output or microphone input? If yes,\ngo ahead and enable it but for my use case I do not need it.\n\n### SHM size\n\n```text\n? Shared memory size in GB (leave empty for default): ()\n[Sets --shm-size for the container (e.g., 8 for 8G).]\n```\n\nSetting a big enough shared memory size is essential for programs using IPC, such as for example web browsers or in my\ncase JetBrains IDE's such as WebStorm. I set it to 4 GB for mine, but depending on your setup you might want to choose\na different size.\n\n## Installing dependencies\n\nNow the litterbox should be successfully built we need to go ahead and install our projects required dependencies. First\nwe need to attach to a terminal within the container:\n\n```bash\nlitterbox enter marizip\n```\n\nFirst we should update all packages in our system:\n\n```bash\nparu -Syu\n```\n\nand then for the project itself we just need Node.js and pnpm, you should adjust for the dependencies required for your project:\n\n```bash\nparu -S nodejs npm\nsudo npm install --global corepack@latest\ncorepack enable pnpm\n```\n\nand for Webstorm we need to install some additional packages, as described in my [Installing JetBrains IDE in litterbox](https://github.com/Gerharddc/litterbox/discussions/63) post:\n\n```bash\nparu -S webstorm webstorm-jre freetype2 ttf-dejavu fontconfig libxkbcommon libxkbcommon-x11\nfc-cache -fv\n```\n\nIf you want to render the Markdown preview in the JetBrains IDE additionally install:\n\n```bash\nparu -S alsa-lib pango libxrandr libxdamage libxcomposite libcups at-spi2-core nss\n```\n\nThen we can launch WebStorm for the first time within the container with a forced override to use Wayland:\n\n```bash\n_JAVA_OPTIONS=\"-Dawt.toolkit.name=WLToolkit\" webstorm\n```\n\nWebstorm will warn us that we used the `_JAVA_OPTIONS` override, so we should persist the forced usage of Wayland the right way.\nWe do this by clicking on the Settings cog and then `Edit Custom VM options` and adding the argument into the newly opened file/window:\n\n```text\n-Dawt.toolkit.name=WLToolkit\n```\n\nFrom now on we can just start it within the container by typing `webstorm`, no need to set the `_JAVA_OPTIONS` env variable first.\n\n## Setting up ssh keys\n\nAs said, I like to have a separate SSH key for every litterbox. I chose `marizip` for the SSH key name, but you can choose whatever,\nit **doesn't** have to be the same as the container name. **The password it prompts for is for the SSH key storage, not the container**:\n\n```bash\nlitterbox keys generate marizip\nlitterbox keys attach marizip marizip\n```\n\nYou might have to restart your litterbox once or twice to have the new key be correctly attached to it. Litterbox stops\nthe container automatically when all windows to it all closed.\n\nNow to allow cloning and pushing from GitHub, I add the SSH key as a **project specific** [deploy key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys#deploy-keys)\nso it's scoped to only the project that is actually running inside the Litterbox. First we need to get our public key:\n\n```bash\nlitterbox keys print marizip\n```\n\nand then we can add it to our GitHub project by going to the repo → Settings → Deploy Keys and then adding it as a read\nand write deploy key.\n\nHaving keys attached means that everytime you `litterbox enter` to a litterbox, you will need to enter your SSH key storage password.\n\n## Adding to launcher\n\nTo be able to launch the IDE easier, I add it to my system launcher. As litterbox requests your SSH key store password, we need to have\nan interactive script to input it when required. I generated this quick Python script with Claude to do that, the only required dependency\nis `pexpect` (on Arch: `sudo pacman -S python-pexpect`). Be sure to adjust the path to your own username:\n\n```python\n#!/usr/bin/env python3\nimport pexpect\nimport sys\nimport os\n\nname     = sys.argv[1]\nide      = sys.argv[2]\npassword = os.environ['LITTERBOX_PASSWORD']\n\nchild = pexpect.spawn(f'/home/mari/.local/bin/litterbox enter {name} {ide}', timeout=60)\nchild.expect('password')\nchild.sendline(password)\nchild.expect(pexpect.EOF, timeout=None)\n```\n\nIt takes the name of the container as the first argument and the launch command for the IDE as the second.\nThe password gets pulled from the `LITTERBOX_PASSWORD` environment variable, which I set globally for my system.\n\nThen we can create a `.desktop` file in a folder our launcher looks for, in my example `~/.local/share/applications/`\n(find out with `printenv XDG_DATA_DIRS`):\n\n```ini\n[Desktop Entry]\nName=WebStorm (marizip)\nComment=Webstorm for maridotzip Project\nExec=/home/mari/.local/bin/litterbox-jb.py \"marizip\" \"webstorm\"\nIcon=webstorm\nTerminal=false\nType=Application\nCategories=Development;IDE;\nStartupWMClass=jetbrains-webstorm\n```\n\nand to apply the changes we just need to refresh our desktop database:\n\n```bash\nupdate-desktop-database ~/.local/share/applications\n```\n\n## Conclusion\n\nWe now have an isolated development environment setup. In case one of our dependencies do end up shipping malware:\n\n1. It only affects the container we are in\n2. The only secrets that can be stolen are the ones we store in our environment, which in the ideal case should be none or just development credentials with weak permissions.\n3. Our SSH key cannot be used to further spread the malware as our SSH agent popup would make us suspicious.\n\nFinally, we can code in peace. Time for the exciting stuff.\n\n## Appendix: Litterbox SSH request popup\n\n![Litterbox SSH request popup](/images/blog/dev-envs/ssh-request.png)\n\n\n",
            "url": "https://mari.zip/blog/isolated-dev-environments",
            "title": "Isolated development environments with litterbox",
            "summary": "After a recent string of supply chain attacks, it was time to isolate my development environments",
            "date_modified": "2026-03-22T00:00:00.000Z",
            "author": {
                "name": "Mari (mellowagain)",
                "url": "https://mari.zip"
            }
        },
        {
            "id": "reverse-engineering-a-protocol-impossible-to-reverse-engineer",
            "content_html": "\n\n\n[Ripple][0], a 3rd party server for the video game [osu!][1], had the following sentences\non their landing page since literally forever:\n\n> ~~reverse engineering a protocol impossible to reverse engineer since always~~\n> we are actually reverse engineering bancho successfully. for the third time.\n\nBut how much truth is behind these sentences? In this article I will give a quick\noverview in how the osu! client and the osu!Bancho server communicate with each other\nand how I've gone ahead and figured these things out.\n\n## Sniffing the traffic between client and server\n\nSo let's start by opening up Wireshark and just capturing a few packets. You'll notice\nquickly that the communication between the osu! client and the osu!Bancho server happens\nusing simple HTTP requests.\n\n![Wireshark](/images/blog/osu-re/wireshark.png)\n\nNormally, these would be sent over HTTPS, but I've gone ahead and patched my client\nto connect to osu!Bancho servers without HTTPS. If you want to decrypt the original\nHTTPS traffic, just search up ways to decrypt HTTPS traffic in Wireshark.\n\n## So much traffic today!\n\nImmediately we notice that osu! seems to send a few checks to `/web/` routes, the first one\nseems to check if my client is up-to-date, as you can see from the parameters it sends.\n\nNext up osu! sends a request to `/web/bancho_connect.php`. Now this is interesting. This\nseems to be a pre-connection mechanism by osu! for eventual ban checking or something. It just\nseems to return the registration country if supplied with correct parameters. Because this\nquery contains the md5sum of my password and my unique client hash, I've censored parts of it.\n\nWe also see a few POST requests to `/web/osu_error.php`. osu! automatically sends the whole\nclient information to that endpoint in case a error occurs, and because a few routes returned\n404 (because I conveniently null-routed them) - that shows up a few times.\n\n## Authentication\n\nBut now lets get to the actual interesting part. osu! sends a POST request to the `/` endpoint.\nLooking at the body sent, it seems to be login and client information. This is the request\nthat authenticates us with the osu!Bancho server. The body is in the following format:\n\n```plaintext\nusername\nmd5sum of the password\nVersion|UTC offset|Display full location|Colon seperated list of MAC addresses which are MD5 hashed|Block non-friend PMs\n\n```\n\nFunnily enough, because I'm running osu! on my Linux machine under Wine, the colon separated\nlist of MAC addresses contained a string which wasn't md5 hashed, it's value was `runningunderwine`.\n\nNow let's take a look at what the server responded and...\n\n![Response](/images/blog/osu-re/response.png)\n\nWhat the hell? Until now everything was nice and plain text and now we got some garbage data\nwith some strings between them? This doesn't seem right - well, actually, it does. We'll\nbe taking a look at them in the next section. Let's first address the headers that we see\nbecause this is the first time the server set some headers on the response which seem interesting.\n\n| Header         | Description                                                                                                                        |\n|----------------|------------------------------------------------------------------------------------------------------------------------------------|\n| `cho-protocol` | This is the version of the cho-protocol used in this response. The newest version known as of the writing of this article is `19`. |\n| `cho-token`    | This is the authentication token used for future requests. Think of it like a session cookie.                                      |\n| `cho-server`   | **This is a non-standard header**. It was set by this 3rd party server implementation for identification of the software.          |\n\nNow that this is out of the way, let's take a look at the seemingly random data mixed with strings\nbetween them. This data is actually a array of cho packets. But how exactly is the format of one\ncho packet?\n\n## Disassembling one packet\n\nLet's take a look at one packet sent from the server to the client:\n\n```hex\n18 00 00 0F 00 00 00 0B 0D 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21\n```\n\nLooks pretty cryptic, doesn't it? But it isn't actually that hard. A cho packet has always\na seven byte header and the actual packet data after it. It is in the following format:\n\n| Size    | Description      | Type                                                               |\n|---------|------------------|--------------------------------------------------------------------|\n| 2 bytes | Packet ID        | LE 16-bit Integer                                                  |\n| 1 byte  | Null byte        | Backwards compatibility with the 2009 osu! client, no longer used. |\n| 4 bytes | Packet Data Size | LE 32-bit Integer                                                  |\n\nThe remaining bytes after this header are all part of the actual packet body.\n\nUsing Python's `struct` module, we can easily translate the bytes above into human readable\ndata.\n\n```python\n>>> struct.unpack(\"<h\", b\"\\x18\\x00\")[0]          # Packet ID\n24\n>>> struct.unpack(\"<i\", b\"\\x0F\\x00\\x00\\x00\")[0]  # Packet Data Size\n15\n```\n\nGreat. As we can see the packet ID for our packet is `24`. I've compiled a list of known packets\nthat you can find [here][2]. The packets prefixed with `in` are sent by the osu! client and the packets\nprefixed with `out` are sent by the osu!Bancho server. Looking at the list, it seems we have\na announcement packet here.\n\n```cpp\nout_announce = 24,\n```\n\nand sending this exact packet to our osu! client confirms our thesis:\n\n![osu! Ingame](/images/blog/osu-re/osu.png)\n\nWe also got `15` for the packet data size and looking at the remaining bytes, they are\nexactly 15. Great! Seems we're on a good way already. So let's continue reading the packet\nbody.\n\n## Parsing the packet body\n\nSo let's jump right into it. The first byte we encounter is `0B`. It signalizes that the\nfollowing bytes should be interpreted as a non-empty string.\n\nSo let's try that, shall we?\n\n```python\n>>> b\"\\x0D\\x48\\x65\\x6C\\x6C\\x6F\\x2C\\x20\\x77\\x6F\\x72\\x6C\\x64\\x21\".decode(\"UTF-8\")\n'\\rHello, world!'\n```\n\nBut what's this? The string at the beginning has a carriage return. Is this actually correct?\nHint: it's not. But what is it then?\n\nAfter some search on the Internet I encounter the osu! wiki. To be more precise, I encounter\nthe wiki page for the [`.osr` File Format][3]. A `.osr` file is a encoded osu! replay file\ncontaining all cursor movement and button clicks. Looking at their table of data types,\nwe can see the following description:\n\n> **String**\n> Has three parts; a single byte which will be either 0x00, indicating that the next two parts are not present, or 0x0b (decimal 11), indicating that the next two parts are present. If it is 0x0b, there will then be a ULEB128, representing the byte length of the following string, and then the string itself, encoded in UTF-8.\n\nCould peppy have decided to use the same format for strings in cho packets as well? Let's\ntry it out.\n\nBased on the description, the byte after the `0B`, which in our case is `0D`, represents\nthe byte length of the following string. Let's convert this then.\n\n```python\n>>> 0x0D\n13\n```\n\nWow, what a coincidence! This is exactly the amount of the remaining bytes in our packet body.\nConverting the remaining bytes into a UTF-8 string and we get the correct string:\n\n```python\n>>> b\"\\x48\\x65\\x6C\\x6C\\x6F\\x2C\\x20\\x77\\x6F\\x72\\x6C\\x64\\x21\".decode(\"UTF-8\")\n'Hello, world!'\n```\n\nSuccess! We've successfully interpreted a cho packet containing a string as body. Let's try\ninterpreting one which doesn't have a string body.\n\n## Don't you reply to me\n\nThe same HTTP body also contained another packet:\n\n```hex\n05 00 00 04 00 00 00 FF FF FF FF\n```\n\nLet's try parsing this. First we get again the packet ID and the packet data size.\n\n```python\n>>> struct.unpack(\"<h\", b\"\\x05\\x00\")[0]          # Packet ID\n5\n>>> struct.unpack(\"<i\", b\"\\x04\\x00\\x00\\x00\")[0]  # Packet Data Size\n4\n```\n\nLooking again on the packet list, the packet seems to be a login reply.\n\n```\nout_login_reply = 5,\n```\n\nA login reply packet has exactly one argument, the user ID or error code. If the passed argument,\na signed 32-bit integer, is negative, a error occurred. If the argument is positive, it is the\nuser ID of user you logged into as.\n\nSo let's do that.\n\n```python\n>>> struct.unpack(\"<i\", b\"\\xFF\\xFF\\xFF\\xFF\")[0]\n-1\n```\n\nWe see that we received a negative number. This indicates a error in the login process. Looking\nat the list of errors we see that we sent invalid credentials.\n\n```cpp\nenum class login_responses : int32_t {\n    invalid_credentials = -1,\n    outdated_client = -2,\n    user_banned = -3,\n    multiaccount_detected = -4,\n    server_error = -5,\n    cutting_edge_multiplayer = -6,\n    account_password_rest = -7,\n    verification_required = -8\n};\n```\n\nSo we've also successfully parsed a packet which only contained a 32-bit integer as argument.\nThat was easy, wasn't it?\n\n## Conclusion\n\nAs we've seen from this writeup, the cho protocol is in no means impossible to reverse engineer.\nIt follows the common principle of [Type-length-value][4], a encoding scheme used for optional\ninformation elements.\n\nI hope this little overview of the cho protocol gave you a better understanding of how\nthe osu! game client and the osu!Bancho server communicate with each other.\n\nI have written this article to allow for new people to dig a bit deeper into the inner workings\nof this beautiful rhythm game. The development community around osu! is amazing and has many\ndifferent aspects which may also interest you.\n\nThis guide does not apply to the open-source version of osu!, called osu!lazer. The osu!lazer\nproject uses JSON to communicate with the osu-web server (not osu!Bancho).\n\n## Credits\n\nThis guide was created with the help of [czapek][5], a friend of mine with who I wrote a\nserver side implementation of the cho protocol, Shiro, which was used as osu!Bancho server\nthroughout this writeup.\n\nThanks to [Mempler][6] for demystifying a few values in the initial\nlogin request sent by the osu! client.\n\n[0]: https://ripple.moe\n[1]: https://osu.ppy.sh\n[2]: https://github.com/mellowagain/shiro/blob/master/src/io/layouts/packets.hh\n[3]: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osr_(file_format)\n[4]: https://en.wikipedia.org/wiki/Type-length-value\n[5]: https://github.com/cyanidee\n[6]: https://github.com/Mempler\n\n\n",
            "url": "https://mari.zip/blog/reverse-engineering-a-protocol-impossible-to-reverse-engineer",
            "title": "Reverse Engineering a Protocol Impossible to Reverse Engineer",
            "summary": "A overview of how the osu! client and the osu!Bancho server communicate with each other",
            "date_modified": "2018-10-21T00:00:00.000Z",
            "author": {
                "name": "Mari (mellowagain)",
                "url": "https://mari.zip"
            }
        }
    ]
}