ひむ日記

本名は設楽です

YAPC::Fukuoka 2025 探訪記 Day 1

himura467.hatenablog.com
が長くなりすぎてしまったので分割しました。
本エントリは Day 1 のトークの感想をまとめたものです。
Day 2 の感想はこちら

iPhone のマイナンバーカードを使った本人確認の実装 by kgoro

Verify with Wallet API を使って手元のマイナンバーカードで何か遊べないかなという思いがあり、ちょうど実装に触れているトークがあったので聴いてみることに。
結論としては Verify with Wallet API を使うためには利用申請が必要なようで、個人で趣味で用いるのは難しそうでした。

運転免許証やマイナンバーカードをスマートフォンに格納するための技術方式である mdoc を用いて読み書きを行う、という話がなされていましたが、電子保険証などの技術の背景を知ることができてよかったです。

途中 ル方式 という名前が出てきてどういうネーミングなんだ?と思ったのですが、調べたところイロハ順みたいですね。日本らしくて良い。

「正規表現をつくる」をつくる by makenowjust

speakerdeck.com

Perl といえば正規表現、ということで正規表現トークを聞きにきました。

正規表現を作る上で、マッチさせたい文字列を過不足なく表現する正規表現が作れたら最高なのですが、例えばメールアドレスだと RFC に準拠していないメールアドレスが存在したりしてどこまでカバーできる正規表現を作るべきか迷うことがたまにありました。

また、ReDoS 攻撃*1と呼ばれる「正規表現と特定の文字列のマッチをするときに異常な時間がかかってしまう脆弱性を利用した攻撃」に対する耐性も気にしながら正規表現を書く必要があります。

これらの問題にうまく対処しつつ、ユーザが求める正規表現を作ってくれるプログラムを模索しよう、というようなお話でした!

id:makenowjust さんは Kyoto.なんか #6 以来二年ぶりくらいにお会いしましたが、お元気そうで何よりでした!

なぜインフラコードのモジュール化は難しいのか - アプリケーションコードとの本質的な違いから考える by 宮下 剛輔

speakerdeck.com

自分は Terraform でリソースを定義する際に Best practices for root modules  |  Terraform  |  Google Cloud Documentation に沿ってモジュールを切り分けて運用しているのですが、時間の流れとともに構成が新しくなるにつれて「現在のモジュールの切り分け方で適切なのか?」という疑問が湧くことが度々ありました。

トークではそのような疑問・違和感を「凝集度」「結合度」という言葉を用いてうまく噛み砕いてくださって、個人的な日頃のもやもやが少し晴れました。

アプリケーションコードでは実装の詳細を隠蔽してインタフェースを提供する設計によりカプセル化疎結合性を担保し、モジュールの中身を理解しなくても利用できる状態を作るのに対し、IaC ではそもそも詳細が関心ごとでありモジュールの中身を理解して使う必要があるため抽象化についての考え方を変える必要がある、というのは確かにな (あんまり考えたことなかったな) と思いました。

そのような難しさとどう向き合うかについても具体的な話がされていましたので、早速うちの Terraform モジュールのリファクタリングを実践してみるぞ!

Amazon ECSデプロイツールecspressoの開発を支える「正しい抽象化」の探求 by 藤原俊一郎

speakerdeck.com

id:sfujiwara さんが開発している ecspresso を例に、設計における適切な抽象化についてお話しされていました。

抽象化の度合いによってインタフェースが吸収しなければならない実装が異なるため開発・メンテナンスする側のコストが大きく変わってくるという話は、実例として提示されていた各種 IaC ツールの差分の違いがすごく分かりやすかったです。

自分が LT で喋ったライブラリGoogle の実装をラップしたものなのですが、元の実装に深く依存している上に微妙に抽象化をしてしまっているので、メンテナンスコストなどを考えると今後困るんだろうな、と身につまされる思いでした。

大規模OSSに一人で立ち向かうには by Sosuke Suzuki

speakerdeck.com

本当にいい話でした。漠然と物事に対するやる気が出ました。

情熱をエミュレートするのが大事というのは本当にそうで、全然興味ない〜やる気出ない〜という時でも、あたかもやる気があるっぽい仕草をするといい感じに脳を騙すことができてパフォーマンスが上がるので、よくやっています。
今もブログを書く情熱をエミュレートしてブログを書いています。

適度に舐めるのも大事!藍染惣右介も「憧れは理解から最も遠い感情」だと言っている。

とりあえず散歩に行こうと思いました。

「バイブス静的解析」でレガシーコードを分析・改善しよう by hitode909

speakerdeck.com

id:hitode909 さんの発表が面白そうだったので見に行きました。

発表内容に関して、素朴に 4 万行のデッドコードを削除できたのはすごいなと思いました。
僕は AI くんをあまり信用できていないため、AI の出した差分は全て目を通さないと安心できず大規模なリファクタリングはそれ相応の時間がかかってしまうのですが、仕組みを整えればやりようがあると知ることができたのは驚きでした。

発表内容以外だと、このトーク会場だけずっと笑いが何処かから漏れているという異様な雰囲気で、これが YAPC か!と実感しました。

Agentに至る道 〜なぜLLMは自動でコードを書けるようになったのか〜 by macopy

speakerdeck.com

現代のエンジニアが愛用している Coding Agent が生まれるまでの歴史が解説されていました。
WebGPT や ReAct など聞いたことがあったようななかったような用語が時系列とともに解説されていて、改めて理解が深まりました。
人間はコードを書くときに Web 検索をするはず、みたいな直感を原体験として研究が進んでいく流れは納得感がありましたね。

後半のライブコーディングも聴衆と一緒に作り上げる感じがすごくよかったですね。

Perl ブートキャンプ by Takafumi ONAKA

speakerdeck.com

裏番組だったため現地で見れていないのですが、気になってしまい資料を読んだので感想を書きます。

流石に現在進行形で Perl を書いていることもあり、大体の話はうんうんと頷きながら読むことができました。
とはいえ Perl がもとはオブジェクト指向言語として作られていなかったために bless と糖衣構文でなんとかしたんだぜ、というような歴史はあまり理解していなかったのでかなり面白かったです。

現代のオブジェクト指向の書き方は最早 Perl に見えない!
カンマ演算子なるほど、全然知らなかった。学びです!

Perl ブートキャンプはインターンの時に受講しているしな、と思って*2 Coding Agent のお話を聞きに行ったのですが、めちゃめちゃ楽しそうなトークだった。録画を見ます!

SREのためのテレメトリー技術の探究 — モニタリングSaaS開発からAIOps・AIインフラまで by yuuk1

speakerdeck.com

SRE として活躍なされた後に、その経験を基にしたアイデアを活かして学術研究の道へ進む、というのは個人的にはすごく理想的な歩みだな〜と感じました。

ログ・メトリクス・トレースの量的な膨大さとそれぞれのデータ形式の違いをどう扱うかが課題であり、SRE ドメインに特化した時系列基盤モデルに期待している、という話はすごく納得感がありました (「データセットを得るのが難しい」、そうですよね...)。

初仕事を親だと思ってしまった

面白い。
初仕事として携わった領域に熱中し続けられる、というのはすごく憧れますね。

LT

プロジェクトの空気を読んで開発してくれるPerlのAIツールがほしい by kobaken

speakerdeck.com

+ をつけてスカラコンテキストで評価されるようにするテクニック、未だに忘れることがあり、ときたまテストを落としています。

間接オブジェクト記法に関して気になった方は以下のブログをチェック!
kfly8.hatenablog.com

Pythonを"理解"しているコーディングエージェントが欲しい!! by nikkie

ftnext.github.io

logging に fstring を用いると表示しないログに対しても評価が走ってしまうのでパフォーマンスが悪い、みたいな話があるんですね。なるほど知らなかった。
気にせず使っていたので気が向いた時に Linter の設定に追加しておこうかなと思いました。

LT でライブコーディング (ライブ AI コーディング) する体験、会場に人数が多い分ワイワイ応援できて楽しかったですね。

認知ではなく良い体験設計を追求する、そのための広告プロダクト開発組織における『Bet AI』とは by ほにゃにゃ / yuki

speakerdeck.com

LT とは思えないスライド量で、AI と属人性に対しての熱意を感じました。
これぞ LT という感じでしたね。

プロダクトにも、チームにも。サイボウズがAIと共に歩む理由 by tasshi

speakerdeck.com

Cybozu さんがどのように AI を活用されているかが分かりやすく紹介されていました!
プレゼンが上手い!

AIが見張り、人がもてなす — 全国400店舗のカラオケBanBanの運営をサポートするAI Agent by 西尾健人

マルチモーダルな情報を用いて異常検知を行うということで、僕の LT の内容と関わる部分があるな、と思いながら聞いていました。
めちゃめちゃ気になるところで終わったので、続きが聴きたくなる LT でした!

*1:文字列が長くなると処理が重くなる正規表現の書き方があるな〜と思ってはいたが、事象の名前は知らなかった

*2:というのと、macopy さんのトークは AI がテーマということもあり、自分の LT の温度感を掴むためにも見ておきたかった

YAPC::Fukuoka 2025 に参加し、「基盤モデルのアーキテクチャを改造してみよう」という LT をしてきました!

はじめに

YAPC::Fukuoka 2025、最高でしたね!!!

実は自分は YAPC 初参加だったのですが、同世代の IT 技術が好きな方々や、父と同世代くらいの IT 技術の黎明期から活躍されている方々とも喋ることができたりとすごく充実した 2 日間でした!
yapcjapan.org

二次会終わり

LT をしてきました

しれっと出していた LT のプロポーザルが幸いにも採択されていたので、初日の LT の一つとして自分が開発している「時系列基盤モデルをマルチモーダル拡張する」ライブラリと、それに関連する活動について発表させていただきました!
speakerdeck.com
どうしても話す内容が 5 分に収まらなかったので直前にコンテンツを削ったのですが、本番では緊張により思いの外早く最後のスライドに辿り着いてしまい、急遽削っていたコンテンツを巻き戻して話し始めるという暴挙に出たりもしました。
なかなかライブ感のある発表をお届けできたのではないでしょうか? (反省)

発表後に id:taiseiue さんに「LT を聞いて時系列基盤モデルに興味が湧きました。早速 Google Colab でプロジェクトを作りました!」と言ってもらえたり id:y_uuki さんにモデルについて具体的な質問をしていただいたりと聴講者の方々が多少なりとも関心を持ってくださったことが分かって、発表者冥利に尽きる思いです。ありがとうございます。

聴いたトークなど

めちゃめちゃ長くなってしまったので、エントリを分けました。

おわりに

YAPC コミュニティの良さを実感できた 2 日間 (+ α) でした。
とともに、まだまだ未熟だなあと改めて実感したので、次回の YAPC::Tokyo 2026 までにさらに精進したい!
とりあえず CPAN Author になりたいのと、Perl に限らずプログラミング言語の気持ちをもう少し理解できるようになりたいですね。

LT の最後に「動的型付け」と「どう敵にカタをつけるか」の両方を表すような文を使って Perl 謎かけを披露しようか迷っていたのですが、何も思いつかなかったので没になりました。
次回登壇する際にはリベンジしたいです。

謝辞

スタッフの皆さん、設営や配信などありがとうございました。
そして忘れ物をしたりとご迷惑をおかけしました、すみません。

カケハシさん、コーヒースポンサーありがとうございました。
京都のおすすめの喫茶店も紹介していただきました。今度寄ろうと思います。

ビアキチさん、美味しいクラフトビールをありがとうございました。
僕はビールが得意な方ではないのですが、フルーティな味わいでスッキリ飲めました。すごく好みです。

【MySQL】想定外のテーブルに対する副作用を生じないことを保証する

モチベーション

OSS であれ会社のソフトウェアであれ規模のデカいプロジェクトを共同開発する際に、コードベースを全て理解し、各種処理やそれらの依存関係を全て把握しながら実装するというのはマトモな人間のなせる業ではない。
また、ソフトウェアはなるべく疎結合であるように作れ、とよく言われるが、規模が大きくなるにつれてどうしても密結合になってしまう部分というのは出てくるものである。
特にシステムのコアとなる機能やその周辺コンポーネントは大きくなりがちだと思う。

とは言え、「コードを理解せずにガッと実装したら思わぬ依存先に影響が出て景気よく障害を出しちゃいました!テヘヘ」という言い分が笑って済まされるほど社会は甘くない。

さらに、プロジェクトの規模が大きくなればなるほど一つ一つの機能が持つ複雑さと影響範囲が増していくため、時間が経つにつれて手がつけられなくなっていくという恐ろしさがある*1

この、複雑化したコア機能に手を加えるケースの実装において最も警戒するべきは、予期しない副作用による既存機能への影響だと思う。
自分が直接手を加えている箇所に関しては自ずと周辺知識もつくし動作確認も慎重に行うはずであり、エッジケースや異常系に対しても十分に警戒できるが、その副作用によって全く想定外の箇所が破滅したり特定の条件下で不具合が起こったとしても、CI さえ通ってビルドが成功すれば見逃されてしまう確率が高い。

ということで、上述したような要件の実装を行なった際に少なくとも DB のレイヤーで予期しない出来事が起きないことをシステマチックに保証する方法を少し考えたので、備忘録がてら書き残しておく。

MySQL (InnoDB) において特定のテーブル以外に副作用を生じていないことを保証する方法

INFORMATION_SCHEMA.TABLES を見る

MySQL には、INFORMATION_SCHEMA というデータベースの情報を格納するデータベース*2が存在する。
ここには TABLES というテーブルがあり、このテーブルの UPDATE_TIME というカラムを見ることで各テーブルが最後に更新された日時を取得することができる。
そのため、素朴なアイデアとして INFORMATION_SCHEMA.TABLES から UPDATE_TIME が処理時刻よりも後であるテーブル をクエリすれば処理が影響するテーブルを特定できそうな気がしてくる。

しかしここで、INFORMATION_SCHEMA は必ずしも正しい値を返さないことに注意する必要がある。
MySQL は INFORMATION_SCHEMA に対するクエリを受け取ると mysql.index_stats および mysql.table_stats ディクショナリテーブルからキャッシュされた値を探しにいく。
このキャッシュの ttlinformation_schema_stats_expiry という変数で管理されており、デフォルトで 24 時間保持される。
要するに、基本的に INFORMATION_SCHEMA へのクエリはそのままではその時点での厳密な値を返してくれないので、SET SESSION information_schema_stats_expiry = 0 とかをやってあげると良さそう。

まとめると、下記のような感じで目的を達成できる。

mysql> SET SESSION information_schema_stats_expiry = 0;
Query OK

mysql> SET @before := SYSDATE(); -- 現在時刻を変数に保持しておく
Query OK

{検証したい一連の処理を実行}

mysql> SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE UPDATE_TIME > @before;
+--------------------------+
| TABLE_NAME               |
+--------------------------+
| innodb_table_stats       |
| innodb_index_stats       |
| foo                      |
| bar                      |
| baz                      |
+--------------------------+

この例では、foo, bar, baz の 3 つのテーブル以外はこの処理によって影響を受けないことが保証できる。

MySQL Server のバイナリログを見る

MySQL Server のバイナリログには、テーブル作成操作やテーブルデータへの変更などのデータベース変更を記述する「イベント」が格納される。
この「イベント」には、結果的に変更を及ぼしたかどうかに関わらず、潜在的に変更を及ぼしうる操作も含まれる。
例として以下のように、一致するレコードが存在しない DELETE を実行してみる。

mysql> DELETE FROM foo WHERE id = "non-existent-id";
Query OK, 0 rows affected

この処理では上述した INFORMATION_SCHEMA.TABLES の UPDATE_TIME は更新されないが、MySQL Server のバイナリログには DELETE を foo テーブルに対して実行したというログが記録される。

この方針なら、下記のような感じで target_table 以外のテーブルに変更を加えていないかどうかを確認できる。

mysql> FLUSH BINARY LOGS; -- ログファイルを切り替える
Query OK
{検証したい一連の処理を実行}

shell> mysqlbinlog --database $DB_NAME --verbose $LOG_FILE | grep '^### \(INSERT\|UPDATE\|DELETE\)' | grep -v '`target_table`$'

まとめ

INFORMATION_SCHEMA.TABLES を見る方法とバイナリログを見る方法のそれぞれで方法を考えた。
厳密にやるならバイナリログを見た方が良さそうだが、INFORMATION_SCHEMA.TABLES を使えば MySQL Client を用いたセッションのみで検証処理が閉じるという嬉しさがある気がする。

他にもっと良い方法がある気がしないでもないので、また思いついたら追記します!

*1:腰を据えてゆっくりリファクタリングできる余裕があればその限りではないが、ハプニングとは往々にして余裕がない時に起きるものである

*2:厳密には INFORMATION_SCHEMA に含まれるテーブルは全てビューであり、データベースディレクトリやファイルの実体が存在する訳ではない

ドイツ人のにいちゃんと仲良くなった

気づけば大学生が大学に通い出す季節になった。
友人達は Line で履修登録だのゼミの面談だのの話をしているが、僕は今日も朝からバイトをしていた。
今日は無駄に早起きしてしまったこともあり昼過ぎくらいに眠くなるかな、と考えていたが、思いの外ずっと元気に集中してバイトに臨むことができた。
時間を忘れてコードを書いていたが、気づくと 20 時を回っておりそこはかとなくお腹も空いていたので、バイト終わりにオフィス近くのタレカツのお店に立ち寄った。
高倉六角店 - 新潟カツ丼-タレカツ
このお店はなぜか外国の方に大人気で、いつ来ても席の半数くらいは外国の方が占めている。
今日も案の定繁盛しており、満席である様子だった。
外で待つか〜、と思って外に出てみると、長身のにいちゃんが店の扉から絶妙な距離離れた場所で立っているのが見えた。
このお店は大抵 2 人か 3 人連れのお客さんが多く、お一人の外国人のお客さんは珍しい。
ひょっとしたら早く食べ終わってお連れの方を待っているのかも?と思ったので、日本語で「並んでますか?」と聞いた*1ら英語で「皿洗うのを待ってるんだ」的な文言が返ってきた。
「ア、ok ~」みたいなことを言ったあと若干沈黙が流れたが、ずっと気になっていたので英語*2で「このお店って外国で有名なんですか?」と聞いた。
すると気さくに「いや、一昨日来て美味かったからもう一回来たんだよ。その前は知らなかった」みたいな答えが返ってきた。
その後真っ先にこの辺りの飯のおすすめを教えてくれ、と言われたのですがりを提案した。
和醸良麺 すがり - 四条(京都市営)/ラーメン | 食べログ
そこからは話せるヤツだと判断されたようで話が弾み、彼は現在 18 歳で高校を 6 月に卒業したあと 10 月下旬にフランクフルトの大学へ進学するということ、その間の休暇期間に初めての外国一人旅として日本を選んできてくれたということを教えてもらった。
旅行の初めは東京にいて、色々見て箱根にちょっと寄った後京都に来てくれたらしい。
東京のおすすめのラーメンも教えてもらった。恵比寿はいいよ、とのこと。
手打 親鶏中華そば 綾川 - 恵比寿/ラーメン | 食べログ
また、車が好きとのことで、大阪のどこかのサーキットで車を運転している動画を見せてもらった。日本のサーキットでは車をカスタマイズすると怒られるんだよ、そういうところも日本らしくて cool、みたいな話をしていた。id:polamjag と話が合いそうだな〜などと考えていた。
僕がもともと東京に住んでいたことを伝えると「どこら辺に住んでいたのか?」と聞かれたのだが、東京の臨海部だよ〜を表現する単語として咄嗟に waterfront 的な単語が出てこなかったので、marine-related area みたいな伝え方をした気がする。
そういえば驚いたこととして、初めての日本旅にしてはすごく箸を使うのが上手だなと感じた。外国の方は箸を使うのが苦手、というのは今では古臭いステレオタイプなのだろうか?なんなら僕よりも早く食べ終わって待ってくれていた。
ドイツにもタレカツに似た料理があるらしく (発音されたが何もわからず、単語も全く読めなかった。ウムラウトが入っていたのだけ覚えている。)、前回はタレカツを頼んでお気に入りだったそう。今回は別の味も試してみたいとのことで海老カツを頼んでいた。
店を出た後、「どっちもうまいけど fried-pork の方が好き」という評価を教えてくれた。また、「この辺りでおすすめのご飯屋さんない?」と聞かれた (さっきも聞いたじゃん)。ご飯が好きらしい。
fried-pork が好きとのことなので、近くのキッチンゴンのピネライスをおすすめした。
宿はすぐ近くにあるそうで、帰りにコンビニでデザート買って帰るよ!と言っていた。ドイツでは 24 時間営業で日曜日もやっているコンビニが大量に存在するという状況はかなり珍しいようで、興奮していた。
一緒に喋った記念として、最後に写真を撮ってもらった。

記念写真

別れ際に、日本の観光と大学生活楽しんでね〜と伝えた。
僕も彼に恥じないような大学生活を送らなきゃな。とりあえず履修登録をします。

*1:英語で話しかけようと思っていたが、見た目だけで勝手に英語で話しかけてめちゃめちゃ日本の方だったら失礼かな、と思い直前でやめた

*2:以下僕が用いている英語は全て高校生くらいのレベル

サプライチェーン攻撃と正常性バイアス

現代において、個人であれ企業であれソフトウェアを開発するにあたって少なからず誰しもがサードパーティのツールなりサービスに依存している。
そのような依存関係を悪用して標的のネットワークやシステムに侵入する攻撃である「(ソフトウェア) サプライチェーン攻撃」という手法が存在する。

最近では Nx リポジトリに対する攻撃が記憶に新しい。
Malicious versions of Nx and some supporting plugins were published · Advisory · nrwl/nx · GitHub

今後いかにセキュリティ技術が進歩したところで、オープンソースのエコシステムを人間が運営する以上はこのようなミスに起因するアクシデントを完全に防ぐことは不可能であり、各ユーザーそれぞれが責任を持って対策することが重要である。





という教科書のような講釈はそこかしこで叫ばれており、インターネットの海を漂っていると一度は見たことがある話なのではないだろうか。

しかしこれらの情報を以って実際に、業務で用いるコードのセキュリティを見直したり個人で使っている依存関係のセキュリティチェックを実施したりといった行動を起こしたユーザーはあまり多くはないと思う。

実情としては「なんやかんや世界中の優秀なエンジニアの方々のおかげで早期に発見されて既にパッチが当てられているし、身近にサプライチェーン攻撃を受けて大変なことになったユーザーがいるわけでもないし、そもそも忙しくてセキュリティを見直している暇ないし、、、」というユーザーがほとんどな気がする。

かくいう僕も上記のような認識しかしておらず、Nx に対する攻撃のメカニズムを解説した記事を読んだ上で「GitHub Actions くん、入力された文字列をコードとして解釈し得るんだ。ShellCheck みたいなツール作ったら需要あるかもな」くらいの感想を抱いただけで特に何も行動していなかった。

事件

つい昨日 chalk や debug をはじめとする npm パッケージが侵害されたことが判明した。
npm debug and chalk packages compromised

これも Nx 同様他人事として流しそうになったのだが、昔 pnpm のファイル構造を趣味で調べていたときに chalk, debug というパッケージ名を見た覚えがあり、他人事ではないかもしれん、ということに気づいた。

というのも、npm は依存しているパッケージが依存しているパッケージも再帰的にインストールするので、package.json に書かれていなくともしれっとインストールされている、というようなパッケージが存在する。

実際、以下のコマンドを用いて自分が管理するプロジェクトの環境を見てみると、next, eslint, vitest を通じて chalk と debug に依存していることが分かった。

$ grep -r "chalk\|debug" package.json node_modules/*/package.json
node_modules/eslint/package.json:    "chalk": "^4.0.0",
node_modules/eslint/package.json:    "debug": "^4.3.2",
node_modules/next/package.json:    "@types/debug": "4.1.5",
node_modules/next/package.json:    "debug": "4.1.1",
node_modules/vitest/package.json:    "@types/debug": "^4.1.12",
node_modules/vitest/package.json:    "@types/debug": {
node_modules/vitest/package.json:    "debug": "^4.4.1",
node_modules/vitest/package.json:    "@types/debug": "^4.1.12",

以下のコマンドを用いて調べたところ、幸い今回に限ってはマルウェアが仕込まれたバージョンのパッケージはインストールされていなかった。

rg -uu --max-columns=80 --glob '*.js' _0x112fa8

Ref: https://github.com/chalk/chalk/issues/656#issuecomment-3266880534
が、単に運が良かっただけでタイミングが悪ければ手元の環境にマルウェアが仕込まれていただろう。
今回のケースでは fetch が呼ばれることで悪意のあるコードが実行されるようになっていたが、もちろん手元のコードにも fetch を呼んでいる箇所は大量にあるので、もしマルウェアが仕込まれていたら悪意のあるコードも元気よく実行されていたであろうことを考えるとヒヤッとする。

対策

今回僕が被害を免れた要因の一つとして、対象となるパッケージに直接的に依存していなかったということが挙げられる。
僕は直接的に依存しているパッケージを Dependabot を用いてアップデートしており、さらにはパッチバージョンの更新に関しては自動的にマージされるようにしているため、今回マルウェアを仕込まれたパッケージに直接的に依存していた場合は、レビューなしでマージされていた可能性が高い。

今回は運良く直接的に依存しているパッケージが攻撃されなかっただけで、今後直接的に依存しているパッケージが攻撃されるということは起こり得る。
そうなった場合に、現在の状態では何の障壁もなく簡単に手元の環境に侵入されてしまう状況であることが分かった。

そのため、取り急ぎ Dependabot の cooldown という機能を用いて、リリース後一定期間経った更新のみを生成するようにした。*1
https://docs.github.com/ja/code-security/dependabot/working-with-dependabot/dependabot-options-reference#cooldown-

これにより一定期間プロダクションで活躍した"信頼のある"バージョンのパッケージしか取り込まれなくなり、ある程度のセキュリティの向上が見込める。*2

また、永遠に言われ続けている話ではあるが、ローカルの ~/.ssh に含まれるクレデンシャルを 1Password などを用いて隠すだったり、シェルの履歴に含まれるクレデンシャルを https://github.com/secretlint/secretlint を用いてマスクするなど、ローカル環境にクレデンシャルを残さないようにすることで万が一自身の環境で悪意のあるコードが実行されたとしても被害が最小限になるように準備しておくことも重要だろう。

総括

最近筆者の周りでは Covid-19 なり夏風邪なりが流行っており、改めて手洗いうがいに気をつけようと気を引き締めている今日この頃だが、ソフトウェアのセキュリティについても同様に身近なものとして適切に認識し、予防する姿勢を持つことが大切だと感じた。

手洗い・うがい・予防的統制を標語に、管理するソフトウェア共々健康に過ごしていきたい。

*1:Renovate なら minimumReleaseAge

*2:全人類がこれを導入した結果脆弱性の発見が遅れる、みたいな未来があったらそれはそれで面白い

Ghostty のテーマを毎回ランダムに変えてみる

Ghostty は 2024 年 12 月末に公開されたターミナルエミュレータである。

ghostty.org

新しいものに飛びつくのが趣味なので、もちろん僕も今年(2025 年)の元旦くらいに導入した。

2025 年 5 月現在でも Ghostty はターミナルエミュレータの中では相当若いものではあるが、とは言っても 4 ヶ月ほど使っていると流石に飽きてきてしまう。

そこで 3 分ほど飽きを防ぐ方法を考え、やはりテーマを変えるのが簡単に気分を変えられて良いのではないか、という結論に至った。

Ghostty のテーマ

Ghostty は CLI から使用可能なテーマ一覧を表示する機能を提供している。

Color Theme - Features

これを用いて良いテーマがないか探してみる。

ghostty +list-themes
themes list

多い...

$ ghostty +list-themes | wc -l
394

自分の環境では 394 個選択可能なテーマがある様子。
流石に 394 個のテーマの色合いなどを全て見て選ぶのは現実的ではない。

イデア

色合いを見た時は良いな(微妙だな)と思っても、実際に使ってみたら微妙だった(思いの外良かった)ということは往々にして起こりうる。
それを踏まえて、毎回ランダムにテーマを変えて気に入ったテーマを見つけたらメモをしておく、というような運用だと楽そう。

流石に手動でテーマを変えるのはアホらしいので自動化することにする。

テーマ文字列の取得

素朴にランダムなテーマを出力しようとしてみる。

$ ghostty +list-themes | sort -R | head -n 1
Vaughn (resources)

お尻に (resources) という謎の文字列がついている...

Ghostty のソースコードを読むと、どうやらテーマの格納場所の情報がついてくるという事情がある様子。

https://github.com/ghostty-org/ghostty/blob/464b85b64c6228f1dfcf5cd853a342e582701126/src/cli/list_themes.zig#L167

--path オプションをつけなければ)必ず {theme} ({location})\n という形でテーマが返ってくるようなので、その規則に従って正規表現で削る。

$ ghostty +list-themes | sort -R | head -n 1 | sed 's/ (.*)$//'
catppuccin-latte

良さそう。

ランダムにテーマを変えてみる

### update_theme_randomly.pl

#!/usr/bin/env perl
#
# Update Ghostty theme randomly.

use strict;
use warnings;
use Cwd 'abs_path';

my $DOTFILES_ROOT = abs_path($0);
$DOTFILES_ROOT =~ s!/ghostty/[^/]+$!!;

# Set random seed if provided
srand($ARGV[0]) if @ARGV;

# Get available themes and select one randomly
my $themes = [ map { s/ \(.*\)$//; $_ } `ghostty +list-themes` ];
chomp @$themes;
my $new_theme = $themes->[int(rand(@$themes))];

# Config file path
my $config_file = "$DOTFILES_ROOT/ghostty/config";

my $updated = 0;
my $content = '';

# Read existing configuration
open(my $in, '<', $config_file) or die "Cannot open $config_file: $!";
while (my $line = <$in>) {
    if ($line =~ /^theme/) {
        # Replace existing theme line
        $content .= "theme = $new_theme\n";
        $updated = 1;
    } else {
        $content .= $line;
    }
}
close $in;

# Append theme if not found in existing config
if (!$updated) {
    $content .= "theme = $new_theme\n";
}

# Write updated configuration
open(my $out, '>', $config_file) or die "Cannot write to $config_file: $!";
print $out $content;
close $out;

これをターミナル起動時に呼び出すために、.zshrc とかにスクリプトを呼ぶ処理を書く(Ghostty の設定の更新を行なっていないので、テーマの更新は 1 回分ずれる)。

# update ghostty theme
$HOME/.dotfiles/ghostty/update_theme_randomly.pl
起動 1 回目
起動 2 回目

これで毎回新鮮な気持ちでターミナル操作が行えそう!

皆さんも良きターミナルライフを!!